# AI Agent Access
Source: https://moengage.com/docs/ai-agents
Access MoEngage documentation in formats suited for AI agents, LLMs, and automation tools.
Use the options below to give AI coding assistants and language models access to MoEngage documentation with less overhead than loading full HTML pages.
## Quick start
* **AI coding assistants (Claude Code, Cursor, etc):** Use the [MoEngage Docs MCP server](https://www.moengage.com/docs/mcp) for the best experience. It lets your assistant search and fetch documentation from within the IDE.
* **Chat interfaces (ChatGPT, Claude.ai):** Add `.md` to any docs page URL and share it in your conversation to get plain markdown instead of the full site.
* **Project rules and custom instructions:** Add MoEngage's [llms.txt](https://www.moengage.com/docs/llms.txt) URL to your AI tool’s rules so it has an index of relevant MoEngage pages.
* **Agent capabilities:** Use the [skill.md](https://www.moengage.com/docs/skill.md) URL or `npx skills add https://www.moengage.com/docs` so agents know what they can do with MoEngage and what inputs or constraints apply.
## MCP server
The [MoEngage Docs MCP server](https://www.moengage.com/docs/mcp) gives AI agents and coding assistants direct access to MoEngage documentation and references through the Model Context Protocol. Use it to bring MoEngage knowledge into tools like Claude, Cursor, and other MCP-compatible clients.
The MoEngage Docs MCP (Model Context Protocol) server connects your AI agents to MoEngage’s docs and developer resources. Configure the MoEngage Docs MCP server in your IDE or AI chat to get in-context help for your MoEngage integration.
For more on the Model Context Protocol, see the [MCP documentation](https://modelcontextprotocol.io/introduction).
If your AI agent supports MCP, you can add the MoEngage MCP server so it has access to MoEngage’s APIs and SDKs. The MoEngage MCP server lets you:
* Get quick answers about MoEngage APIs, features, and implementation
* Search documentation without leaving your editor
* Find code samples and recommended patterns for typical use cases
* Debug issues using docs and SDK references
* Write code that integrates your app with MoEngage
## Installation
To set up the MoEngage MCP server, use the contextual menu on any page and click **Connect**.
Alternatively, you can pick your IDE or AI chat provider and follow the steps below.
1. Open **Cursor** and open the `.cursor` directory in your project root. Create it if it doesn’t exist. This is where Cursor’s project configuration lives.
2. Open the `mcp.json` file in `.cursor`. Create it if it doesn’t exist. This file holds MCP server configuration for the project.
3. Add the following to `mcp.json`:
```json mcp.json theme={null}
{
"mcpServers": {
"MoEngage Docs": {
"url": "https://www.moengage.com/docs/mcp"
}
}
}
```
4. Save the file.
5. Restart Cursor.
Claude Desktop uses `npm` to run the MoEngage MCP server. You need **Node.js** installed. See [Node.js downloads](https://nodejs.org/en/download/) for details.
1. Open **Claude Desktop**.
2. Go to **File > Settings** (Windows) or **Settings** (macOS).
3. Open the **Developer** tab.
4. Click **Edit Config**.
5. Open `claude_desktop_config.json`. This file controls MCP servers for Claude Desktop.
6. Add the following to `claude_desktop_config.json`:
```json claude_desktop_config.json theme={null}
{
"mcpServers": {
"moengage-docs": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://www.moengage.com/docs/mcp"]
}
}
}
```
7. Save the file.
8. Restart Claude Desktop.
Remote MCP in Claude Desktop is currently in beta.
### Enterprise and team plans
1. Open **Claude Desktop**.
2. Go to **Admin settings > Connectors**.
3. Scroll to the bottom of the section.
4. Click **Add custom connector**.
5. Fill in:
* **Name**: MoEngage MCP
* **Remote MCP server URL**: `https://www.moengage.com/docs/mcp`
6. Click **Add**.
### Pro and max plans
1. Open **Claude Desktop**.
2. Go to **Settings > Connectors**.
3. Scroll to the bottom of the section.
4. Click **Add custom connector**.
5. Fill in:
* **Name**: MoEngage MCP
* **Remote MCP server URL**: `https://www.moengage.com/docs/mcp`
6. Click **Add**.
Run the following command in your terminal:
```bash theme={null}
claude mcp add --transport http MoEngage-docs https://www.moengage.com/docs/mcp
```
1. Create a `.vscode/mcp.json` file with the following content:
```json mcp.json theme={null}
{
"servers": {
"MoEngage Docs": {
"type": "http",
"url": "https://www.moengage.com/docs/mcp"
}
}
}
```
2. Save the file.
3. Restart VS Code.
## Usage
The MoEngage MCP exposes the following tool:
* **`search_mo_engage`** — Searches MoEngage’s documentation and knowledge base. Use it to find guides, API details, code examples, and implementation notes. Results include titles and links to the relevant docs.
## Per-page markdown
Append `.md` to any docs page URL to get a markdown version of that page. You get content only, without HTML, nav, or scripts, which uses fewer tokens than the full page.
For example, for the [API Reference introduction](/api-reference/introduction) in markdown, use:
```txt theme={null}
https://www.moengage.com/docs/api-reference/introduction.md
```
## Site-wide endpoints
These endpoints follow the [llms.txt standard](https://llmstxt.org/). You can use these endpoints for markdown-formatted content.
| Endpoint | Description | Size |
| --------------------------------------------------------------- | ----------------------------------------------------------------------- | ------ |
| [`/llms.txt`](https://www.moengage.com/docs/llms.txt) | Page index with short descriptions for the whole site | Varies |
| [`/llms-full.txt`](https://www.moengage.com/docs/llms-full.txt) | Full content of all pages. Prefer section-level endpoints when possible | Large |
## skill.md
The `skill.md` file describes what AI agents can do with MoEngage in a structured, machine-readable format. It makes capabilities, required inputs, and constraints explicit so agents can use your product more reliably.
**URL:** [https://www.moengage.com/docs/skill.md](https://www.moengage.com/docs/skill.md)
The file follows the [skill.md specification](https://agentskills.io/specification) and is kept in sync with the documentation so agents stay aligned with current MoEngage features and APIs.
`llms.txt` and `skill.md` both help agents use MoEngage documentation, but they do different things.
* **`llms.txt`** is a directory: it lists documentation pages with descriptions so agents know where to look.
* **`skill.md`** is a capability summary: it describes what agents can accomplish with your product, what inputs they need, and what constraints apply.
### Using skill.md with agents
Agents can load MoEngage’s capabilities into their context with the [skills CLI](https://www.npmjs.com/package/skills):
```bash theme={null}
npx skills add https://www.moengage.com/docs
```
This adds MoEngage’s skill description to the agent so it can take actions on behalf of users (e.g. answering integration questions or suggesting API usage).
Use the `skill.md` URL or the command above in your own AI setup so you get better, more accurate assistance when working with MoEngage.
### What’s in skill.md
The MoEngage `skill.md` file is generated from the documentation and typically includes:
* **Metadata** — Product name, description, and version.
* **Capabilities** — What agents can do with MoEngage (e.g. campaigns, segments, SDK integration).
* **Skills** — Concrete actions grouped by area (APIs, SDKs, data, etc.).
* **Workflows** — Step-by-step procedures for common tasks.
* **Integration** — Supported tools and services.
* **Context** — High-level overview of MoEngage documentation and concepts.
For the exact schema and fields, see the [agentskills.io specification](https://agentskills.io/specification).
# Bulk Import Users and Events
Source: https://moengage.com/docs/api/bulk/bulk-import-users-and-events
/api/data/data.yaml post /transition/{Workspace_ID}
The Bulk Import API sends multiple user and event requests in batch to MoEngage, using a single API request. You can send a batch request of a maximum of 100 KB in a single API call.
All bulk API requests return a 200 response code. Debugging should be done on the user profile on the dashboard.
#### User Identity Resolution
In MoEngage, data ingestion uses an ID to create or update a user. For workspaces in MoEngage with [Identity Resolution](https://help.moengage.com/hc/en-us/articles/24050999467284-Unified-Identity-Identity-Resolution) enabled, you can use the Bulk Import API to create or update users using a specific identifier, such as a mobile number or email ID. These identifiers must be enabled for the workspace in the Identity Resolution dashboard.
You can:
* Create users through Server-to-Server Data APIs even when they do not have an ID (but have other identifiers).
* Create a user or track events of a user when identifiers other than ID (for example, email ID or phone number) are known.
#### Rate Limit
A single bulk import API contains users, devices, and events together. Send a maximum of 10,000 users and 30,000 events per minute across all API requests.
# Business Events Overview
Source: https://moengage.com/docs/api/business-events/business-events-overview
Create, manage, and trigger real-time business events to power automated MoEngage campaigns.
The MoEngage Business Events API allows you to create and trigger specialized events that represent business occurrences—such as a flight delay, a price drop on a watched item, or the release of a new OTT series episode. These events act as triggers for **Business Event Triggered Campaigns**, allowing you to automate high-context communication based on external data points rather than just user behavior.
## Endpoints
The Business Events API is a collection of the following endpoints:
* [Create Business Event](/api/business-events/create-business-event): Define the schema and attributes for a new event.
* [Trigger Business Event](/api/business-events/trigger-business-event): Trigger an event to initiate associated campaigns.
* [Search Business Events](/api/business-events/search-business-events): Retrieve details of existing events using IDs or names.
## FAQs
### Manage Business Events
The supported data types include integer, float, string, date, and array.
No, business event names must be unique within your workspace.
You can use the [Search Business Events API](/api/business-events/search) to fetch a list of all events associated with your workspace.
### Trigger Campaigns
No, it is not mandatory to pass all defined attributes when triggering the event. Only include the attributes required for your campaign personalization.
Navigate to **Engage -> Campaigns** on the MoEngage Dashboard and search for the campaign associated with your Business Event to view real-time analytics and trigger counts.
The API will return a `400 Bad Request` error with the message "No active campaign found for business event name." Ensure your campaign is in the **Active** state before triggering.
## Postman Collection
Test these endpoints quickly using our pre-configured Postman collection: [View MoEngage Business Events Collection](https://www.postman.com/moengage-dev/workspace/api-docs/collection/3182294-38587f83-f039-46f3-b86e-10af2c918053)
# Create Business Event
Source: https://moengage.com/docs/api/business-events/create-business-event
/api/business-events/business-events.yaml post /business_event
This API creates business events in MoEngage. You can use these events to trigger campaigns whenever they occur. In MoEngage, you can set up event-triggered campaigns to notify users about new episodes, flight delays, or price reductions on items they have viewed, wished for, or added to their carts.
#### Rate Limit
The rate limits are at the workspace level. You can create a maximum of 50 business events for each workspace.
# Search Business Events
Source: https://moengage.com/docs/api/business-events/search-business-events
/api/business-events/business-events.yaml post /business_event/search
This API searches for business events by specifying their event IDs.
#### Rate Limit
The rate limit is 100 RPM.
# Trigger Business Event
Source: https://moengage.com/docs/api/business-events/trigger-business-event
/api/business-events/business-events.yaml post /business_event/trigger
This API triggers a business event in MoEngage. You can set up campaigns to be executed when these events are triggered.
#### Rate Limit
For Campaigns:
* You can send a maximum of 200 triggers per day
* You can send a maximum of 50 triggers per hour.
For Flows:
* You can trigger a maximum of 3 Business Trigger flows per hour.
* You can trigger a maximum of 10 Business Trigger flows per day.
# Download Campaign Report
Source: https://moengage.com/docs/api/campaign-reports/download-campaign-report
/api/stats-report/stats-report.yaml get /campaign_reports/rest_api/{APP_ID}/{FILENAME}
This API downloads campaign reports for any specific date range. You can fetch reports for one-time and periodic campaigns.
#### Limits
* **Expiry**: The generated reports will expire in **7 days** from the date of creation.
* **Max Range**: You can generate reports for up to **90 days**.
#### Generating the Signature
A unique signature must be passed in the headers to verify the caller's authenticity.
The signature is `SHA256(Api_ID + "|" + FILENAME + "|" + SECRET_KEY)`.
```python
# SAMPLE IMPLEMENTATION IN PYTHON
from hashlib import sha256
Api_ID = "YOUR-APP-ID"
FILENAME = "Report_-_test_20210217.zip"
SECRET_KEY = "YOUR-SECRET-KEY"
Signature_Key = Api_ID + "|" + FILENAME + "|" + SECRET_KEY
# Now Signature is hexdigest of sha256 of Signature_Key
Signature = sha256(Signature_Key.encode('utf-8')).hexdigest()
```
# Campaigns Overview
Source: https://moengage.com/docs/api/campaigns/campaigns-overview
Use the MoEngage Campaigns API to create, update, test, and manage Push and Email campaigns programmatically.
The MoEngage Campaigns API allows you to create and manage Push and Email campaigns. Use these endpoints to automate campaign creation, update existing campaigns, control campaign status, and retrieve campaign details.
If this API is not enabled for your account, contact your MoEngage Customer Success Manager (CSM) or the Support team to request enablement.
## Endpoints
The Campaigns API is a collection of the following endpoints:
* [Create Campaign](/api/create-campaigns/create-campaign): Creates a new Push or Email campaign.
* [Update Campaign](/api/update-campaigns/update-campaign): Updates an existing Push or Email campaign in MoEngage.
* [Search Campaigns](/api/get-campaign-details/search-campaigns): Fetches a list of Push, Email, or SMS campaigns with all current fields and status.
* [Test Campaign](/api/test-campaigns/test-campaign): Sends a test Push or Email campaign to specific users before launching it.
* [Personalized Preview](/api/test-campaigns/personalized-preview): Displays personalized content for a specific user before sending a Push, Email, or SMS campaign.
* [Get Campaign Meta](/api/get-campaign-details/get-campaign-meta): Retrieves campaign details and reachability information for scheduled campaigns.
* [Change Campaign Status](/api/update-campaigns/change-campaign-status): Updates the status of campaigns to stop, pause, or resume them.
* [Get Child Campaigns](/api/get-campaign-details/get-child-campaigns): Retrieves child campaign execution details for Periodic or Business Event-triggered campaigns.
## FAQs
### Create Email Campaign
You can use user attributes, event attributes, product sets, content API, and content block for personalizing campaigns. The syntax of the personalization Jinja is the same as supported in the MoEngage dashboard.
MoEngage dedups the campaign using the request ID. If the same request ID is passed twice in 24 hours, the second campaign creation will fail.
Campaigns are displayed under the same delivery type with which the campaigns are created through this API. For example, One-Time, Periodic, and so on.
No, only one of the two is required for creating the campaign. If both are passed, the campaign creation will display an error.
To create a campaign that uses a custom segment, include the `segmentation_details` in your campaign creation request. Within `included_filters`, set the `filter_type` to "custom\_segments" and provide the ID of your custom segment.
The following code snippet shows how to incorporate a custom segment:
```json theme={null}
"segmentation_details": {
"included_filters": {
"filter_operator": "and",
"filters": [
{
"filter_type": "custom_segments",
"name": "segment",
"id": "{{id}}"
}
]
}
}
```
### Create Push Campaign
Yes. You can create a Push campaign for a single platform such as Android, iOS, or Web. You can also create campaigns for a combination of these platforms.
Use the [Search Push Template API](/api/templates/search-push-template) and pass a request parameter such as the template name, created by, or any other supported parameter to retrieve the template ID in the response.
Select a template type, such as Stylized Basic, Timer, or any other available option. Then, refer to the template's requirements and include all fields marked as mandatory for that template type.
To create a campaign that uses a custom segment, include the `segmentation_details` in your campaign creation request. Within `included_filters`, set the `filter_type` to "custom\_segments" and provide the ID of your custom segment.
The following code snippet shows how to incorporate a custom segment:
```json theme={null}
"segmentation_details": {
"included_filters": {
"filter_operator": "and",
"filters": [
{
"filter_type": "custom_segments",
"name": "segment",
"id": "{{id}}"
}
]
}
}
```
### Update Push Campaign
The template type can be modified for the required platforms, and new content needs to be provided for the updated template type.
The platform can be added or removed during the update of the campaigns. You need to provide content for the new platform added to the campaign.
The updated campaign starts sending out as soon as changes are done, except for Event-triggered campaigns. In Event-triggered campaigns, details are cached and take up to 30 mins to send the updated campaign.
### Update Email Campaign
No, you cannot update the segmentation audience after the campaign is in Active state. You can update the segmentation audience if the campaign is in Scheduled state or create a duplicate by stopping the existing campaign to pass new segmentation details.
The updated campaign starts sending out as soon as changes are done except for Event-triggered campaigns. In Event-triggered campaigns, details are cached and take up to 30 mins to send the updated campaign.
You must call the "GET" API by the campaign name, channel, or any other filters to fetch the campaign ID of the desired campaign. For more information, refer to [Search Campaigns](/api/campaigns/campaigns#search_campaigns).
### Search Campaigns - Push
Yes. To fetch flow node campaigns, you must pass the `include_child_campaigns` key value as `true`.
Use the `flow_name` and `flow_id` keys in the response. These keys indicate that the campaign is part of a flow.
The response will include all flow node campaigns, regardless of the flow delivery type, and Engage campaigns with a delivery type of `one_time`.
### Search Campaigns - SMS
Yes. To fetch flow node campaigns, you must pass the `include_child_campaigns` key value as `true`.
Use the `flow_name` and `flow_id` keys in the response. These keys indicate that the campaign is part of a flow.
No, we currently do not have any filter in the request body for the sender name.
Yes. To fetch archived campaigns, you must pass the `include_archived_campaigns` key value as `true`.
### Test Push Campaign
Yes, you can send the test campaign to any user by passing identifier as "Email". The campaign sent will not be personalized.
The values passed under personalization details will be used for all users to whom the test campaign is to be sent and the remaining user attributes values will be picked up from the user profile.
### Test Email Campaign
Yes, you can send the test campaign to any user by passing identifier as "Email". The campaign sent will not be personalized.
The values passed under personalization details will be used for all users to whom the test campaign is to be sent and the remaining user attributes values will be picked up from the user profile.
### Get Campaign Meta
No, reachability is an estimated value that may vary over time due to factors such as app installations, uninstalls, or changes in email subscription status.
No, reachability is calculated once daily and cached for 24 hours. Multiple API calls within the same day will return the cached value.
### Personalized Preview
Yes, you can use custom templates with the Personalization Preview. The API will personalize the content within the template based on the user identifier provided and return the personalized HTML as a response.
Yes, you can pass event details as input to the API. Ensure the event name matches the one in your workspace.
### Change Campaign Status
Periodic campaign only supports Pause and Resume actions of the campaign. You can stop only One-time campaigns.
No, after the One-time campaign moved to the Active state, you cannot stop it.
## Postman Collections
We have made it easy for you to test the APIs. Click [here](https://www.postman.com/moengage-dev/workspace/api-docs/folder/3182294-c560e43e-4e5e-4d1c-a100-f5f5070780b1?action=share\&creator=3182294\&ctx=documentation) to view the Postman collection.
# Cards Overview
Source: https://moengage.com/docs/api/cards/cards-overview
Use the MoEngage Cards API to fetch, filter, and delete user-specific cards from your application.
The MoEngage Cards API allows you to fetch and delete user-specific cards from the MoEngage database. Use these endpoints to retrieve cards for a user, filter them by platform and category, check for updates since the last sync, and remove specific card campaigns.
If this API is not enabled for your account, contact your MoEngage Customer Success Manager (CSM) or the Support team to request enablement.
## Endpoints
The Cards API is a collection of the following endpoints:
* [Fetch Cards](/api/cards/fetch-cards-for-user): Retrieves all active and updated cards for a specific user, supporting filtering and pagination.
* [Delete Cards](/api/cards/delete-cards-for-user): Deletes specific card campaigns for a user from the MoEngage Cards database.
## FAQs
### Fetch Cards
You can use the `prev_sync_card_ids` (list of card IDs from the previous sync) and `last_updated_time` (Unix epoch timestamp of the last sync) fields in the request body. The API will return only the new or updated cards.
Yes. You can filter by platform using the `platforms` array (e.g., `["ANDROID", "WEB"]`) and by category using the `card_category` string field in the request body.
You must provide either the `uid` (MoEngage Standard ID like Email or Mobile Number) or the `unique_id` (Platform-specific device identifier). One of these is required.
The *unique\_id* is the unique value that identifies the user to whom the cards need to be shown. It is a platform-specific device identifier that can be generated.
The *uid* is the unique MoEngage Standard ID (Email ID Standard or the Mobile Number Standard) that identifies the user.
### Delete Cards
The Delete Cards API requires complex filtering parameters (campaign IDs, specific platforms, and user identifiers) which are best transmitted via a JSON body, even though this deviates from the standard REST pattern for `DELETE` requests.
Yes, you can specify the `platforms` array in the request body (e.g., `["android"]`) to delete the cards only from those specific platforms. If omitted, it deletes from all associated platforms.
The *unique\_id* is the unique value that identifies the user to whom the cards need to be deleted. It is a platform-specific device identifier that can be generated. The *uid* is the unique MoEngage Standard ID that identifies the user.
## Postman Collections
We have made it easy for you to test the APIs. Click [here](https://www.postman.com/moengage-dev/api-docs/collection/dpuqrlz/moengage-cards) to view the Postman collection.
# Delete Cards for User
Source: https://moengage.com/docs/api/cards/delete-cards-for-user
/api/cards/cards.yaml delete /cards/delete
This API deletes cards for a specified user from the MoEngage Cards database.
#### Rate Limit
The rate limit is **50K RPM** (Requests Per Minute) and is applicable at the workspace (App) level.
# Fetch Cards for User
Source: https://moengage.com/docs/api/cards/fetch-cards-for-user
/api/cards/cards.yaml post /cards/fetch
This API retrieves all active and updated cards for a specific user from the MoEngage Cards database. You can filter the search results based on the platform and card category and check if any card was updated for the user since the previous sync.
#### Rate Limit
The rate limit is **50K RPM** (Requests Per Minute) and is applicable at the workspace (App) level.
# Add Catalog Attributes
Source: https://moengage.com/docs/api/catalog/add-catalog-attributes
/api/catalog/catalog.yaml patch /catalog/{catalog_id}/attributes
This API adds new attributes to the catalog. If the API request contains attributes that already exist, they will not be added again.
#### Rate Limit
* Request limit: You can add 100 attributes per minute OR 1000 attributes per hour.
* Payload size limit - 5 MB only when Content-Length header is provided.
# Catalog Overview
Source: https://moengage.com/docs/api/catalog/catalog-overview
Manage product and item catalogs, define attributes, and handle bulk item ingestion.
The MoEngage Catalog API allows you to manage product and item catalogs. Use these endpoints to create new catalogs, define custom schemas, and perform bulk operations for ingesting, updating, or deleting items.
## Endpoints
The Catalog API is a collection of the following endpoints:
* [Create Catalog](/api/catalog/create-catalog): Creates a new catalog with a unique name.
* [Add Catalog Attributes](/api/catalog/add-catalog-attributes): Adds new attributes to the catalog.
* [Add Items](/api/items/add-items): Ingests items into an existing catalog.
* [Get Items](/api/items/get-items): Retrieve item attribute details.
* [Update Items](/api/items/update-items): Updates items with new attribute values.
* [Delete Items](/api/items/delete-items): Deletes existing items in a given catalog.
## FAQs
### Catalog Management
The API will return a `409 Conflict` error with the error code `duplicate-catalog-name`. Catalog names must be unique within your workspace.
Yes, you can use the **Add Catalog Attributes** (PATCH) endpoint. Note that if you send attributes that already exist in the schema, they will be ignored and listed in the `duplicate-item-attributes` array in the response.
You can define up to 50 attributes per catalog, including the 4 mandatory attributes.
API catalogs automate real-time updates such as price and quantity. They offer improved efficiency and scalability by updating only specific products, unlike file-based catalogs, which require the replacement of the whole file at each processing schedule. These APIs can be accessed and used to update from any location.
Each error code is a uniquely defined shorthand representation for the type of error, providing a quick reference that can be used to diagnose, troubleshoot, and address the problem based on a predefined set of error conditions.
No, the datatype cannot be changed once an attribute has been defined in the catalog. You can add a new attribute to the catalog with a different datatype as needed.
A maximum of 50 attributes can be added to the catalog.
Before updating existing items with new attributes, you must first add the new attribute to the catalog schema using the 'Add catalog attribute' API. Only then will your update requests for including new attributes be successful.
The request will be processed successfully marking such items as invalid. The response will include the count of these invalid item IDs.
### Item Ingestion and Updates
The API returns a `200 OK` with a detailed breakdown. The response body will include a `valid` count and an `invalid` count with a `details` array specifying which `document_ids` failed and why (e.g., data type mismatch or missing attributes).
No. The `id` is the primary key. To change an ID, you must delete the existing item and ingest it as a new item.
Yes, the bulk-delete endpoint supports a maximum of 50 item IDs per request.
All MoEngage catalog APIs operate synchronously. This means that every catalog API request is processed in real time, and you can see the changes instantly.
### Get Item Details
Each error code is a uniquely defined shorthand representation for the type of error, providing a quick reference that can be used to diagnose, troubleshoot, and address the problem based on a predefined set of error conditions.
No, the data type cannot be changed once an attribute has been defined in the catalog. You can add a new attribute to the catalog using the [Add new catalog attribute API](/api/catalog/add-catalog-attributes) with a different data type as needed.
## Postman Collections
Test these endpoints immediately using our Postman collection. [View Postman Collection](https://www.postman.com/moengage-dev/api-docs/collection/seck3f6/moengage-catalog-api)
# Create Catalog
Source: https://moengage.com/docs/api/catalog/create-catalog
/api/catalog/catalog.yaml post /catalog
This API creates a new catalog with a unique name. You can specify the necessary attributes along with their respective data types.
#### Rate Limit
* Request limit: You can create 100 catalogs per minute OR 1000 catalogs per hour.
* Payload size limit: 5 MB only when Content-Length header is provided.
# Sync Cohort Members
Source: https://moengage.com/docs/api/cohort-sync/sync-cohort-members
/api/cohort-audience/cohort-audience.yaml post /v1/integrations/cohortsync
This API adds or removes a list of users from a custom segment (cohort) in MoEngage.
* The Cohort Sync API only matches users already present in MoEngage based on the User ID (`uid`) provided in the request. This API does not create new users.
* This API endpoint does not currently support Team-level scoping. All segments generated using this call will be assigned to the Default Team automatically.
#### Rate Limits
Please adhere to the following limits:
* **Frequency:** 300 requests per minute.
* **Payload Structure:** One payload per request (each payload can contain multiple UIDs).
* **Size Limit:** The payload size cannot exceed **128KB**.
#### User Resolution
The Cohort Sync API resolves existing users in MoEngage based on predefined user identifiers:
* **Identifier:** We primarily rely on the **User ID** (`uid`) provided in the request payload.
* **Matching:** This must match the Unique User ID set in MoEngage (typically available for registered or logged-in users).
* **Profile Association:** Each Unique User ID corresponds to a single user profile. Even if a user is logged in across multiple devices, the devices are associated with that single user profile.
# Content Blocks Overview
Source: https://moengage.com/docs/api/content-blocks/content-blocks-overview
Fetch, create, and manage reusable content blocks.
Content blocks allow marketers to reuse the same content across multiple campaigns. Instead of recreating standard elements for every message, you can create a block once—such as a header, footer, or a designed call-to-action button—and reference it everywhere.
This MoEngage Content Block API allows you to fetch, create, and update these content blocks on your MoEngage dashboard.
## Endpoints
The Content Block API is a collection of the following endpoints:
* [Create Content Block](/api/content-blocks/create-content-block): Creates a content block.
* [Update Content Block](/api/content-blocks/update-content-block): Updates a content block specified by its ID.
* [Get Specific Content Blocks](/api/content-blocks/get-specific-content-blocks): Fetches specific content blocks from the available content blocks.
* [Search Content Blocks](/api/content-blocks/search-content-blocks): Searches the content blocks created in your MoEngage account.
## Postman Collections
We have made it easy for you to test the APIs. Click [here](https://www.postman.com/moengage-dev/api-docs/collection/3486165-5dc87a9b-a3ef-442f-9d45-512253c6b891) to view our official Postman collections.
# Create Content Block
Source: https://moengage.com/docs/api/content-blocks/create-content-block
/api/content-blocks/content-blocks.yaml post /content-blocks
This API creates a content block in MoEngage.
# Get Specific Content Blocks
Source: https://moengage.com/docs/api/content-blocks/get-specific-content-blocks
/api/content-blocks/content-blocks.yaml post /content-blocks/get-by-ids
This API retrieves specific content blocks from the available content blocks in your MoEngage account.
# Search Content Blocks
Source: https://moengage.com/docs/api/content-blocks/search-content-blocks
/api/content-blocks/content-blocks.yaml post /content-blocks/search
This API searches for the available content blocks in your MoEngage account.
# Update Content Block
Source: https://moengage.com/docs/api/content-blocks/update-content-block
/api/content-blocks/content-blocks.yaml put /content-blocks
This API updates the content blocks in MoEngage.
# Delete a Coupon File from the Coupon List
Source: https://moengage.com/docs/api/coupon-files/delete-a-coupon-file-from-the-coupon-list
/api/coupons/coupons.yaml delete /coupon-list/{coupon_list_id}/files/{coupon_file_id}
This API removes a specific coupon file from a coupon list. It is useful in scenarios where a test file or incorrect file is inadvertently uploaded, thereby ensuring the accuracy and effectiveness of your coupon list management.
**Information**
There is no request body or content to send for this request except for headers.
#### Rate Limit
You can delete:
* 5 coupon files per minute or
* 50 coupon files per day
# Fetch a Coupon File from Coupon List
Source: https://moengage.com/docs/api/coupon-files/fetch-a-coupon-file-from-coupon-list
/api/coupons/coupons.yaml get /coupon-list/{coupon_list_id}/files/{coupon_file_id}
This API retrieves the details of a particular coupon file added to a given coupon list. This includes information such as file status, the number of added coupons, and the file addition date.
**Information**
There is no request body or content to send for this request except for headers.
#### Rate Limit
You can fetch 10,000 coupon files from a coupon list per day.
# Fetch All Coupon Files From Coupon List
Source: https://moengage.com/docs/api/coupon-files/fetch-all-coupon-files-from-coupon-list
/api/coupons/coupons.yaml get /coupon-list/{coupon_list_id}/files
This API retrieves the details of each file in the given coupon list that is added and not deleted. The information retrieved will include the file's status, the number of coupons added from each file, and the respective file's addition date, thereby providing a comprehensive breakdown of each file's information for improved management and tracking.
There is no request body or content to send for this request except for headers.
#### Rate Limit
You can fetch 10,000 coupon files from coupon lists per day.
# Upload a Coupon File to the Coupon List
Source: https://moengage.com/docs/api/coupon-files/upload-a-coupon-file-to-the-coupon-list
/api/coupons/coupons.yaml post /coupon-list/{coupon_list_id}/files
After you create a coupon list, you must add coupons to the list to be distributed through campaigns. If a coupon list has been running for some time, it may be running low after serving several campaigns.
Using this API, you can replenish an older list or populate a new list by providing the URL of a file containing the coupons, thereby enabling their distribution through various campaigns. These coupons can be provided through a file, and the API requires the URL where your coupon file is hosted.
**Information**
Upon API request, file processing begins, and the file status will be **PENDING** by default.
* For convenience, you can set up a callback URL to trigger when the file's processing is completed.
* You can check the processing status using the [Fetch a Coupon File API](https://www.moengage.com/docs/api/coupon-files/fetch-a-coupon-file-from-coupon-list) to get the status separately.
#### Rate Limit
You can upload:
* 5 coupon files to a coupon list per minute or
* 50 coupon files to a coupon list per day
**Note:**
* **Payload size limit**: 64 MB for manual uploads or 100 MB for URL uploads.
* **Additional limits**: The maximum number of coupons per coupon list is 100 million.
# Activate Coupon List
Source: https://moengage.com/docs/api/coupon-lists/activate-coupon-list
/api/coupons/coupons.yaml put /coupon-list/{coupon_list_id}/activate
This API reactivates archived coupon lists, provided the expiry date is in the future.
**Information**
* Only active coupon lists can be utilized in campaigns.
* If you need to modify the expiry date and activate a coupon list, you must use the [Update a Coupon List API](#operation/updateCouponList).
#### Rate Limit
You can activate 100 coupon lists per day.
# Archive a Coupon List
Source: https://moengage.com/docs/api/coupon-lists/archive-a-coupon-list
/api/coupons/coupons.yaml put /coupon-list/{coupon_list_id}/archive
This API transitions an active coupon list to an archived status. Upon archival, the coupon codes within the list are deleted. Consequently, any campaigns that were previously dependent on this list will no longer be able to utilize the dynamic coupon allocation.
**Information**
Verify the usage of a given coupon list in active or planned campaigns before archiving it.
#### Rate Limit
You can archive 100 coupon lists per day.
# Create a Coupon List
Source: https://moengage.com/docs/api/coupon-lists/create-a-coupon-list
/api/coupons/coupons.yaml post /coupon-list
This API creates single-use coupon codes. You can use this API to create and organize distinct lists for different coupon code categories.
**Information**
This API creates the coupon list with basic specifications only. The coupons should be added using [Upload the Coupons](https://www.moengage.com/docs/api/coupon-files/upload-a-coupon-file-to-the-coupon-list) API to this coupon list before utilizing it in campaigns.
#### Rate Limit
You can create 100 coupon lists per day.
# Fetch All Coupon Lists
Source: https://moengage.com/docs/api/coupon-lists/fetch-all-coupon-lists
/api/coupons/coupons.yaml get /coupon-list
This API fetches all created coupon lists in a specific workspace. By default, this API returns the coupon lists marked with an *ACTIVE* status. In return, it offers detailed specifications of the active coupon lists, respective configurations, statuses, expiry dates, and alert conditions, including on-time data on the total coupons added and those that are currently available.
**Information**
There is no request body or content to send for this request except for the headers and parameters.
#### Rate Limit
You can fetch 10,000 coupon lists per day.
# Fetch Coupon List Details
Source: https://moengage.com/docs/api/coupon-lists/fetch-coupon-list-details
/api/coupons/coupons.yaml get /coupon-list/{coupon_list_id}
This API retrieves the specifications of a particular coupon list. It includes information such as configurations, statuses, expiry dates, and alert conditions with real-time counts of added and currently available coupons. Using this API, you can easily access and manage critical data about individual coupon lists.
**Information**
There is no request body or content to send for this request except for headers and parameters.
#### Rate Limit
You can fetch 10000 coupon lists per day.
# Update a Coupon List
Source: https://moengage.com/docs/api/coupon-lists/update-a-coupon-list
/api/coupons/coupons.yaml patch /coupon-list/{coupon_list_id}
This API modifies existing coupon lists within a defined workspace. It facilitates changes to specifications like list name, expiry date, and alert settings, thereby promoting efficient coupon operations management.
**Information**
This API reactivates the *ARCHIVED* or *EXPIRED* coupon list upon modification, provided the list has a future expiration date.
#### Rate Limit
You can update 100 coupon lists per day.
# Coupon Management Overview
Source: https://moengage.com/docs/api/coupons/coupons-overview
Manage unique coupon lists, upload coupon codes, and generate usage reports within the MoEngage system.
The MoEngage Coupon Management API allows you to organize and distribute unique, single-use coupon codes at scale. Use these endpoints to automate the lifecycle of coupon lists—from creation and file uploads to activation, archival, and detailed usage reporting.
## Endpoints
The Coupon Management API is categorized into three functional areas:
### Coupon Lists (Metadata and Status)
* [Create a Coupon List](/api/coupon-lists/create-a-coupon-list): Defines a new category for unique codes.
* [Fetch All Coupon Lists](/api/coupon-lists/fetch-all-coupon-lists): Retrieves a list of active or archived coupon containers.
* [Fetch Coupon List Details](/api/coupon-lists/fetch-coupon-list-details): Retrieves real-time counts of available vs. total coupons.
* [Update a Coupon List](/api/coupon-lists/update-a-coupon-list): Modifies names, expiry dates, or alert settings.
* [Activate Coupon List](/api/coupon-lists/activate-coupon-list): Reactivates archived lists with a new expiry date.
* [Archive a Coupon List](/api/coupon-lists/archive-a-coupon-list): Transitions a list to inactive and deletes associated codes.
### Coupon Files (Inventory Management)
* [Upload Coupon File](/api/coupon-files/upload-a-coupon-file-to-the-coupon-list): Populates a list via a hosted file URL.
* [Fetch All Coupon Files](/api/coupon-files/fetch-all-coupon-files-from-coupon-list): Tracks the status of all uploaded batches.
* [Fetch a Coupon File](/api/coupon-files/fetch-a-coupon-file-from-coupon-list): Checks the processing status (e.g., PENDING) of a specific file.
* [Delete a Coupon File](/api/coupon-files/delete-a-coupon-file-from-the-coupon-list): Removes specific batches (useful for correcting upload errors).
### Reports
* [Generate Usage Report](/api/reports/generate-usage-report): Generates a detailed usage report for a specific coupon list, providing details on which user received which coupon.
## Postman Collections
We have made it easy for you to test the APIs. Click [here](https://www.postman.com/moengage-dev/api-docs/collection/y1e45ee/moengage-coupon-management) to view our official Postman collections.
# Create Campaign
Source: https://moengage.com/docs/api/create-campaigns/create-campaign
/api/campaigns/campaigns.yaml post /campaigns
This API creates a new Push or Email campaign in MoEngage with specified content, audience, and delivery settings.
**API Enablement**
If this API is not enabled for your account, contact your MoEngage Customer Success Manager (CSM) or the Support team to request enablement.
#### Rate Limits
You can create 5 campaigns per minute, 25 campaigns per hour, and 100 campaigns per day.
# Segments Overview
Source: https://moengage.com/docs/api/custom-segments/custom-segments-overview
Create, update, and manage your file-based, filter-based, and cohort-synced segments.
The MoEngage Segments API allows you to manage your audience segments. This suite includes the **v2 API** for handling high-volume file-based segments and segment lifecycles, the **v3 API** for dynamic, filter-based segments, and the **Cohort Sync API** for synchronizing external audiences directly with MoEngage.
## Endpoints
The Segments API is a collection of the following endpoints:
### File Segments (v2)
The File Segments API allows you to create and manage segments by importing users from CSV files hosted at a URL.
* [Create File Segment](/api/file-segments/create-file-segment): Creates a new file segment from a CSV file URL.
* [Add Users to File Segment](/api/file-segments/add-users-to-file-segment): Adds a list of users from a CSV file to an existing file segment.
* [Remove Users from File Segment](/api/file-segments/remove-users-from-file-segment): Removes a list of users from a CSV file from an existing file segment.
* [Replace Users in File Segment](/api/file-segments/replace-users-from-file-segment): Replaces all users in an existing file segment with a new list of users from a CSV file.
### Manage Segments (v2)
The Manage Segments API allows you to control the lifecycle of your segments by archiving or unarchiving them.
* [Archive Segment](/api/manage-segments/archive-segment): Archives an existing segment (File or Filter).
* [Unarchive Segment](/api/manage-segments/unarchive-segment): Unarchives an existing segment, making it active again.
### Filter Segments (v3)
The Filter Segments API allows you to create and manage dynamic segments based on user attributes and behavioral filter conditions.
* [List Segments](/api/filter-segments/list-segments): Lists all filter segments.
* [Create Filter Segment](/api/filter-segments/create-filter-segment): Creates a new filter segment based on a set of filter conditions.
* [Get Segment by ID](/api/filter-segments/get-segment-by-id): Fetches a specific segment (File or Filter) by its ID.
* [Update Filter Segment](/api/filter-segments/update-filter-segment): Updates an existing filter segment by its ID.
### Cohort Sync
The Cohort Sync API allows you to synchronize cohorts or audiences created in your own ecosystem directly with MoEngage. This server-to-server integration enables you to add or remove users from custom segments dynamically, ensuring your marketing campaigns always target the most relevant audience.
* **Automated Segment Creation:** Automatically creates a custom segment in MoEngage if it doesn't already exist.
* **Dynamic Membership:** Real-time updates to segments allow scheduled campaigns to engage the latest set of users.
* **No Middleware Needed:** Direct server-to-server calls remove the need for manual CSV uploads or hosting external URLs.
* **Increased Efficiency:** Ideal for segment operations involving smaller subsets of users.
**Endpoint:**
* [Sync Cohort Members](/api/cohort-sync/sync-cohort-members): Adds or removes users from a custom segment.
These API endpoints do not currently support Team-level scoping. All segments generated using these calls will be assigned to the Default Team automatically.
## FAQs
### Filter-Based Segments
You can generate the payload directly from the MoEngage Dashboard. Navigate to **Test & Debug** -> **Segment Payload**, choose your filters, and click **Generate Payload**.
Use the **List Segment API** with the `name` query parameter to filter and retrieve the unique ID of the desired segment.
Both the name and the definition (filters) of a segment must be unique. If the definition matches an existing segment, the API returns a 409 Conflict.
In the case of a 409 error, the response payload includes the `existing_cs_name` and `existing_cs_id` of the conflicting segment.
Please connect with your account manager.
### File-Based Segments
Segment processing is asynchronous. MoEngage first creates the segment container (showing zero users) and then processes the file. The count will update once processing is complete.
No. File segments can only be updated (add/remove/replace) via the File Segment API using CSV imports. For attribute-based updates, use Filter Segments.
### Manage Segments
Archiving allows you to reuse segments for A/B testing or historical analysis without recreating them from scratch, while keeping your active segment list within the 1000-segment limit.
### Cohort Sync
The Cohort Sync API enables the creation of segments without needing separate files or CSVs, eliminating the requirement for a separate path or URL as seen in the File Segment API. Segment creation can be initiated by making a direct server-to-server call, eliminating the additional steps required for generating user files.
The Cohort Sync API is ideal for segments or segment operations involving fewer users.
The Cohort Sync API does not create new users in MoEngage. Instead, it resolves existing users in MoEngage based on predefined user identifiers and assigns them to the corresponding custom segment created through Cohort Sync.
## Postman Collections
Test these endpoints quickly by importing our Postman collections: [File Segments](https://www.postman.com/moengage-dev/api-docs/collection/z8f27qa/moengage-custom-segment-api), [Filter Segments](https://www.postman.com/moengage-dev/api-docs/collection/s16aovr/moengage-custom-segment-filter-based-crud-api-s), and [Cohort Sync](https://www.postman.com/moengage-dev/api-docs/collection/2siizsq/moengage-cohort-audience-sync-revamp?action=share\&creator=3182294) in Postman.
# Data Overview
Source: https://moengage.com/docs/api/data/data-overview
Manage users, track events, handle devices, and perform bulk data operations.
The MoEngage Data API provides a comprehensive suite of endpoints designed to help you manage data within MoEngage. This API enables you to create and update user profiles, track user actions (events), manage device information, and handle large-scale data ingestion via bulk and file import operations.
## Endpoints
The Data API is a collection of the following API endpoints:
* [Track User](/api/user/track-user): Adds or updates users and user properties in MoEngage.
* [Get User](/api/user/get-user): Facilitates the retrieval of information of users.
* [Merge User](/api/user/merge-users): Merges two users in MoEngage based on their ID.
* [Delete User](/api/user/delete-users): Deletes users in MoEngage.
* [Track Event](/api/event/track-event): Tracks the actions of a user.
* [Track Device](/api/device/track-device): Adds or updates devices and device properties in MoEngage.
* [Device Opt-out](/api/device/device-opt-out): Blocks or unblocks specific devices from receiving push notifications.
* [Trigger File Imports](/api/file-import/trigger-file-imports): Triggers scheduled file imports.
* [Import Details](/api/file-import/import-details): Fetches the status at an import level.
* [Import File Run History](/api/file-import/import-file-run-history): Fetches the file processing status of each file contained in an import.
* [Bulk Import](/api/bulk/bulk-import-users-and-events): Sends multiple user and event requests in batch to MoEngage.
* [Install Tracking](/api/tracking/track-app-install): Tracks the install attribution data in MoEngage.
* [Test connection](/api/utilities/test-connection-api): Validates if the entered endpoint details are valid.
For workspaces in MoEngage with the *User Identity Resolution* feature enabled, use the following Data APIs to create or update users using a specific identifier, such as a mobile number or email ID, as configured in **Settings** > **Data** > **Identity Resolution**:
* Track User
* Create Event
* Bulk Import
For more information, refer to [User Identity Resolution](https://help.moengage.com/hc/en-us/articles/24050999467284-Unified-Identity-Identity-Resolution).
You can:
* Create users through Server-to-Server Data APIs even when they do not have an ID (but have other identifiers).
* Create a user or track events of a user when identifiers other than ID (for example, email ID or phone number) are known.
## Request Body
The request body contains the mandatory field called `customer_id`. It is the unique identifier set and passed on from the MoEngage SDK as `USER_ATTRIBUTE_UNIQUE_ID` and is visible on the dashboard as `ID`.
`customer_id` is used to:
* Identify or create a user in MoEngage.
* Associate the events with the corresponding unique user profiles in MoEngage.
On receiving a Data API request in MoEngage, the `customer_id` is used to verify if the user exists in MoEngage. If the user does not exist, a new user is created with the attributes or events.
* The maximum limit for the request body is 128 KB.
* Any string of more than one characters is allowed for `customer_id` except the following values - \['unknown', 'guest', 'null', '0', '1', 'true', 'false', 'user\_attribute\_unique\_id', '(empty)', 'na', 'n/a', '', 'dummy\_seller\_code', 'user\_id', 'id', 'customer\_id', 'uid', 'userid', 'none', '-2', '-1', '2']
For example, a user created using the following request is visible in the dashboard user profile as displayed.
### Sample Request Body
Below is a sample request body for the Create User API:
```json theme={null}
{
"type": "customer",
"customer_id": "USERID1234",
"attributes": {
"first_name":"John",
"name":"John Smith",
"plan_expiry_date":"2020-05-31T00:00:00Z",
"super_user":true,
"user_persona":"browsers",
"platforms" : [{"platform":"ANDROID", "active":"true"}]
}
}
```
You can not use "moe\_" as a prefix while naming events, event attributes, or user attributes. It is a system prefix and using it might result in periodic blacklisting without prior communication.
### Supported Datetime Formats
You can pass the datetime in the following formats in the request body:
| Datetime Format | Example |
| :------------------------------------------- | :------------------- |
| `“datetime_format”:YYYY-MM-DD[T]HH:mm:ss[Z]` | 2019-03-12T17:36:05Z |
| `“datetime_format”: "YYYY-MM-DD"` | 2022-01-22 |
MoEngage performs the following validation on datetime formats before ingesting data into its system:
* Future and past date values are accepted and ingested.
* Any date values with incorrect calendar values (e.g., 2019-15-12 where 15 is not a valid month) are ingested as strings.
* Any datetime values incompatible with the formats mentioned above are converted to strings and then ingested.
## Response
Response to the Data API is a JSON object. On a successful data API request, you will receive the following response:
```json theme={null}
{
"status": "success",
"message": "Your request has been accepted and will be processed soon.",
"request_id": "kXwpDESb"
}
```
On a failed data API request, you will receive the following response:
```json theme={null}
{
"status": "fail",
"error": {
"type": "TypeError",
"message": "expected string",
"request_id": "kXwpDESb"
}
}
```
### Response Codes
The following status codes and associated error messages are returned when the request results in an error.
| Error Code | Type | Message | Description |
| :--------- | :---------------------------- | :--------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 400 | Missing header value | The Content-Type Header is required | The header value for content type is missing |
| 400 | Empty request body | A valid JSON document is required | The request body is empty |
| 400 | Malformed JSON | Could not decode the request body. The JSON was incorrect or not encoded as UTF-8. | The request JSON is not formed correctly |
| 400 | Blacklisted | Your account is blacklisted, Please contact MoEngage. | Your App is blacklisted in MoEngage |
| 400 | InvalidParams | Given app\_id is invalid. | The App ID is invalid. |
| 400 | ParamsRequired | app\_id is required in path/query params. | App ID is missing in the path or query params. |
| 400 | Empty request body | A valid JSON document is required | The request body is empty. |
| 400 | Body type is not JSON | A valid JSON document is required. | String Payload. |
| 400 | MissingAttributeError | key is expected to be datatype | The specified attributes are invalid |
| 401 | Authentication Required | Authentication Header Required | Authentication header is missing from the request. |
| 401 | Authentication required | No identity information found | Authentication header is empty. |
| 401 | Authentication required | Invalid identity information found | Failure to decode app\_key and app\_secret. |
| 401 | Authentication required | APP\_KEY missing in the authentication header | App\_key is not present in the authentication header. |
| 401 | Authentication required | APP\_SECRET missing in the authentication header | App\_secret is not present in the authentication header. |
| 401 | Authentication required | App Secret key mismatch. Please login to the dashboard to verify key | App secret key is wrong. |
| 401 | Authentication required | Invalid APP\_ID used in Authentication Header | You have used an invalid APP ID in the authentication header. |
| 403 | Account Suspended | Account Suspended | Your account is suspended. |
| 403 | Account Temporarily Suspended | Account Temporarily Suspended | Your account is suspended temporarily. |
| 409 | Authentication Mismatch | App key mismatch in params and authentication | App\_key in parameters and authentication does not match. |
| 409 | Authentication required | App Secret key is not set. Please login to the dashboard to set a key | App Secret not set. |
| 413 | Payload too large | The payload can not exceed 128KB | Request payload size is too large. |
| 415 | Unsupported Media Type | Unsupported Media Type | Unsupported media type. |
| 429 | Rate Limit Exceeded | Rate Limits for User / Event exceeded | You have exceeded the rate limits (number of users or events per minute) defined for your MoEngage account. |
| 5xx | Server Error | Any other exception | This response is returned when the system runs into an unexpected error. We recommend that you retry every 2 seconds for a maximum of 5 times in such cases. |
## User Attributes
| Key name | Display name | Fetch through Get User API | Update through Track User API | Create through Track User API |
| :-------------------------- | :------------------------------------- | :------------------------- | :---------------------------- | :---------------------------- |
| publisher\_name | Publisher Name | yes | no | yes |
| campaign\_name | Campaign Name | yes | no | yes |
| t\_rev | LTV | yes | no | no |
| t\_trans | No of Conversions | yes | no | no |
| moe\_ip\_city | Last Known City | yes | no | no |
| moe\_ip\_pin | Last Known Pincode | yes | no | no |
| moe\_ip\_subdivision | Last Known State | yes | no | no |
| moe\_ip\_country | Last Known Country | yes | no | no |
| moe\_dtzo | User Timezone Offset (Mins) | yes | no | no |
| u\_s\_c | No. of Sessions | yes | no | no |
| u\_l\_a | Last Seen | yes | no | yes |
| cr\_t | First Seen | yes | no | yes |
| u\_mb | Mobile Number (Standard) | yes | yes | yes |
| uid | ID | yes | yes | yes |
| u\_bd | Birthday | yes | yes | yes |
| u\_em | Email (Standard) | yes | yes | yes |
| locale\_language\_display | Local Language | yes | no | no |
| locale\_country\_display | Local Country | yes | no | no |
| uninstall\_time | Uninstall time | yes | no | no |
| installed | Install Status | yes | no | no |
| moe\_cr\_from | User Creation Source | yes | no | no |
| u\_n | Name | yes | yes | yes |
| u\_ln | Last Name | yes | yes | yes |
| u\_gd | Gender | yes | yes | yes |
| u\_fn | First Name | yes | yes | yes |
| geo | Geolocation | yes | no | no |
| moe\_wa\_subscription | WhatsApp Subscription Status | yes | yes | yes |
| moe\_em\_unsub\_categories | Email Unsubscribed Categories | yes | yes | yes |
| moe\_gaid | Google Advertising ID (Android) | yes | no | yes |
| advertising\_identifier | Advertising Identifier (iOS \&Windows) | yes | no | yes |
| web subscription url | Web Push Subscription Page URL | - | - | - |
| moe\_sub\_w | Web Push Subscription Status | yes | yes | yes |
| moe\_w\_ds | Browser Details | yes | no | no |
| moe\_mweb | Mobile User | yes | no | yes |
| moe\_i\_ov | OS Version iOS | - | - | - |
| moe\_it | Creation Source | no | no | no |
| moe\_spam | Spam | yes | yes | yes |
| moe\_unsubscribe | Unsubscribe | yes | yes | yes |
| moe\_hard\_bounce | Hard Bounce | yes | yes | yes |
| moe\_rsp\_android | Reachability Push Android | yes | no | no |
| moe\_rsp\_ios | Reachability Push iOS | yes | no | no |
| moe\_rsp\_web | Reachability Push Web | yes | no | no |
| moe\_rsu | Reachability Push | yes | no | no |
| moe\_sms\_subscription | SMS Subscription Status | yes | yes | yes |
| moe\_ds\_bts\_push\_hour | Best time to send Push | yes | no | no |
| moe\_ds\_bts\_email\_hour | Best time to Email | yes | no | no |
| moe\_ds\_bts\_sms\_hour | Best time to send SMS | yes | no | no |
| moe\_ds\_mpc\_best\_channel | Most Preferred Channel | yes | no | no |
## Dashboard User Profile
On sending data through the data API, it will be populated in the user profile as shown below:
## Limits
The Data API is designed to handle high volumes of data across our customer base. We enforce API limits to ensure responsible use of the API. Refer to the respective endpoint documentation for rate limits.
* If your requirement exceeds the default limits, you can contact the MoEngage support team to increase the limits.
* Make sure to adhere to the Fair Usage Policy (FUP) for high-frequency user data ingestion. This is mandatory to prevent disruption to data processing in your workspace. For more information, refer to the [Fair Usage Policy (FUP)](https://help.moengage.com/hc/en-us/articles/24151864954644-Fair-Usage-Policy-FUP).
## FAQs
### Track User
Please attempt exponential backoff of requests to ensure there is no data loss due to 5xx errors.
Getting a 200 status code as a response from MoEngage only indicates that the users in your API payload have been accepted for processing. It does not ensure that the users sent to MoEngage have been successfully ingested. \
Although, this happens very rarely and you can search for newly ingested users in:\
**Segment > Create Segment > Search for users using their IDs**
Please use the [Get User API](/api/user/get-user) to export the users.
Please use the [Delete User API](/api/user/delete-users-in-bulk) to delete existing users in MoEngage.
### Get User
All available users will be found in the `users` key, and users not available will be found in the `users_not_found` key. Please refer to the sample response in this doc.
If the `user_fields_to_export` is not passed, then all custom attributes and exportable standard attributes will be returned. For specific fields, `user_fields_to_export` needs to be passed along with the list of required fields.
### Merge User
No, the merged user will get deleted after calling this API. All the user attributes and devices of the merged user will be transferred to the retained user.
The reachability status of the user will be recalculated based on the devices present after merging the user.
Any registered user present in the MoEngage system can be merged with another registered user irrespective of the source of creation.
Not necessarily; we allow the merging of users with or without devices.
No.
No.
This user will get deleted, and if any devices are attached to this user, they will be associated with the `retained_user`. All events and user details of the `merged_user` will reflect on the `retained_user`. A merge event `MOE_USER_MERGE_EVENT` will be added to the `merged_user` (who will only have the MoEngage ID now).
The `retained_user` will now have all the user, device, and event details of the `merged_user` along with its own existing details. A `MOE_USER_MERGED` event will be added to the `retained_user`.
We will create a new user with that ID, but the MoEngage ID of this user will be different compared to the deleted user.
The user will not be reachable.
The maximum SLA is 30 minutes.
In the user profile, all events of the last 30 days are moved from the merged user to the retained user.
### Delete User
There are no rollback mechanisms for undoing the delete action. Once the delete request is processed, the user is deleted from MoEngage.
No, the events corresponding to a user are not specifically deleted; only the user and the user attributes are deleted when the delete API request is processed.
However, once the user is deleted from MoEngage, the events corresponding to the user will not be accessible. For example, if an event is used in a segmentation query, the deleted user who executed that event will not be added to the calculated segment or campaign.
Navigate to **Segment** -> **Create Segment** on the MoEngage dashboard. Type the unique identifier for the deleted user (ID, MoEngage ID, phone number, email, or any unique identifier you have configured). If the user has been deleted (hard delete), you will not see any search results. For more information about searching users, refer to \[Search User in Segmentation].
### Create Event
Events in the payload need to be mapped to a given user who has executed the event. You must use the Customer ID to identify the events mapped to a customer.
No, anonymous users can be tracked using MoEngage SDKs.
Events in MoEngage are immutable, meaning events can only be created; they cannot be updated or deleted.
### Track Device
No, you can pass only the device attributes mentioned above. Any additional custom attributes passed in the API payload are dropped during processing.
The device will be created based on the Android platform, and the IDFV value passed in the API will be dropped. If the platform is iOS and a GAID value is passed, the device will be created with iOS, but the GAID attribute will be dropped.
You can create a maximum of 1000 devices for a user. The user will be blocked if a 1001st device is created for the user.
In such cases, the existing device will be deleted, and the new device will be added.
### MoEngage Streams
The throughput and average volume of each API request depends on the volume of selected events captured into MoEngage. The default batch size (number of events for each API request) is 100.
The retrial mechanism allows MoEngage to hit your provided endpoints in multiple attempts. In case a batch of events fails (anything other than a "2XX" response from the endpoint is considered failed), the entire batch is retried. MoEngage makes a total of three retry attempts with the following intervals:
* **First Retry:** 30 seconds
* **Second Retry:** 60 seconds
* **Third Retry:** 120 seconds
If you pause Streams, data is not collected for exports and hence cannot be replayed at a later date.
No. Streams is primarily built to export your events in near real-time. Since user attributes in MoEngage are updated asynchronously, it is currently not possible to guarantee the latest values of user attributes in the exports.
As of now, you cannot export data that occurred before configuring Streams. Once configured, you will start seeing data for each event from the moment you enable your exports.
### Bulk Import
Yes, Track User API validations apply to the `Customer` payload type, and Create Event API validations apply to the `Event` payload type within the Bulk API request.
Please implement an **exponential backoff** strategy for your requests. This ensures that your system gradually reduces request frequency during high-load periods, preventing data loss due to server-side errors.
Receiving a **200 OK** status code only indicates that the users in your API payload have been successfully accepted for processing. It does not guarantee that the ingestion process is complete.
While failures are rare, you can verify ingestion by searching for the users in the MoEngage Dashboard: Navigate to **Segment** > **Create Segment** > **Search for users** using their unique IDs.
### Trigger File Imports
No, the schedule still remains the same as originally set up in the MoEngage Dashboard.
## Postman Collection
We have made it easy for you to test the APIs. Click [here](https://www.postman.com/moengage-dev/api-docs/collection/p593wcu/moengage-data-apis) to view the collection in Postman.
# File Import Overview
Source: https://moengage.com/docs/api/data/file-import-overview
Fetch the processing status at both the import and file levels.
The MoEngage File Imports API helps in proactively tracking the status of the Imports and the Files in an import without navigating to the MoEngage dashboard.
## Use Cases
* Fetch the processing status of all imports for a given date range without navigating to the MoEngage dashboard.
* Proactively alert about failures in automated campaigns. For example, if an automated campaign must run using the updated list of users ingested into MoEngage through the import option, but if the import fails for any reason, it may impact the reachability of your campaigns. Typically, you become aware of import failure only when navigating to the MoEngage dashboard or when you receive an email alert. However, with this API, you can track the status proactively even before the campaign is impacted.
## Endpoints
The File Imports API is a collection of the following endpoints:
* [Trigger File Imports API](https://www.moengage.com/docs/api/file-import/trigger-file-imports): Triggers scheduled file imports.
* [Import Details API](https://www.moengage.com/docs/api/file-import/import-details): Fetches the status at an import level.
* [Import File Run History API](https://www.moengage.com/docs/api/file-import/import-file-run-history): Fetches the file processing status of each file contained in an import.
## FAQs
### Trigger File Imports
No, the schedule still remains the same as originally set up in the MoEngage Dashboard.
## Postman Collection
Test these endpoints quickly by importing our Postman collection:
* Trigger File Imports: [**View in Postman**](https://www.postman.com/moengage-dev/api-docs/collection/u3yt8gn/moengage-file-imports-trigger-api?action=share\&creator=3182294)
* Import Details: [**View in Postman**](https://www.postman.com/moengage-dev/api-docs/collection/u3yt8gn/moengage-file-imports-trigger-api?action=share\&creator=3182294)
* Import File Run History: [View in Postman](https://www.postman.com/moengage-dev/api-docs/collection/mzt9mgo/moengage-status-and-run-history-api?action=share\&creator=3182294)
# Streams
Source: https://moengage.com/docs/api/data/moengage-streams
Forward user actions and campaign events to your API endpoint in near real-time using MoEngage Streams.
With MoEngage Streams, you can configure your API endpoint, define the events you want to forward, and then view a stream of data flowing into your system. You can then utilize the data to enrich your data warehouses and recommendation systems.
## Use Cases for MoEngage Streams
The following are a few popular use cases for Streams:
* Enrich the central data warehouse with MoEngage events such as Notification Clicked Android, Email Clicked, SMS Clicked, and so on.
* Forward the Conversion Events, such as Purchase, Song Played, Bill Payment Done, and so on, from MoEngage to the external Analytics tool.
* Feed campaign interaction events from MoEngage to your recommendation system.
* Export the notification interaction data from MoEngage to your machine learning system for optimizing the performance of your algorithms.
* Send all user events present in MoEngage to an external data lake.
## Enable Streams for Your Account
Contact your Customer Success Manager to get this enabled for your account. Note that Streams is available as a part of the Streams add-on.
Streams can export data to your API endpoint or one of the partners integrated with MoEngage.
### Set Up Streams for Exporting Data to Your API Endpoint
To export data from MoEngage to your servers, contact your MoEngage Customer Success Manager (CSM) or the Support team with the following information:
1. API endpoint to send the data. It can be something like `https://api.example.com/events`.
2. List of events that need to be sent to this API endpoint. A list of campaign events available for export is mentioned in the [next section](#campaign-interaction-events).
3. List of user attributes and device attributes that need to be sent to the API endpoint with each event.
4. If you need all campaign interaction events, we will export such events as mentioned in the [next section](#campaign-interaction-events).
You can use the following template to raise a Streams enablement request:
```text theme={null}
Hey!
Please enable Streams for my Workspace.
Workspace Region: DC-01/DC-02/DC-03/DC-04
Workspace Name: MyWorkspace
Workspace ID:
API Endpoint: [https://www.example.com/api?url_param1=vaue1](https://www.example.com/api?url_param1=vaue1)
Headers:
header1: value1
header2: value2
Authentication:
Method: No auth/Basic Auth
[Only for basic auth] Basic Auth username: "Username"
[Only for basic auth] Basic Auth password: "Password"
Events to export: All/List of events
[Optional] List of events: List of events to export
User properties to export: All/List of user properties
[Optional] List of user properties: List of user properties to export
```
**Whitelist IPs**
If your endpoints are in a Virtual Private Cloud (VPC) or not accessible publicly, you must whitelist [these](https://help.moengage.com/hc/en-us/articles/35329024618772-A-Guide-to-MoEngage-IP-Whitelisting-Mechanism#h_01JNGJBH0HCJAVHHP9MZZ8AYWM) MoEngage IPs depending on the region of your Workspace.
### Set Up Streams for Exporting Data to Partners
With Streams, you can export data directly to integrated partners so that you can enrich your marketing/analytics activities on these platforms. As of now, Streams can export data to the following partners:
* [Mixpanel](https://partners.moengage.com/hc/en-us/articles/4410027746836-Mixpanel#01FV1SH74TEQEBE0JVVAWJSWAS)
* [Amplitude](https://partners.moengage.com/hc/en-us/articles/4409507678228-Amplitude-Audiences#h_01HJ11HMQGHRZT4GR260D27QK3)
* [Segment](https://partners.moengage.com/hc/en-us/articles/12661517099284-MoEngage-Source)
* [mParticle](https://partners.moengage.com/hc/en-us/articles/10223363585428-mParticle-Inbound)
* [Rudderstack](https://partners.moengage.com/hc/en-us/articles/12718141249556-MoEngage-Source)
Please follow partner-specific integration documents for setting this up.
## Campaign Interaction Events
The following is a list of Campaign Interaction Events that MoEngage generates, which you will often need to be sent to your API endpoint:
| Event Name | Event Code | Channel |
| :---------------------------- | :------------------------------ | :---------------- |
| Email Sent | `MOE_EMAIL_SENT` | Email |
| Email Deferred | `MOE_EMAIL_DEFERRED` | Email |
| Email Delivered | `MOE_EMAIL_DELIVERED` | Email |
| Email Dropped | `MOE_EMAIL_DROP` | Email |
| Email Bounced | `MOE_EMAIL_HARD_BOUNCE` | Email |
| Email Soft Bounced | `MOE_EMAIL_SOFT_BOUNCE` | Email |
| Email Opened | `MOE_EMAIL_OPEN` | Email |
| Email Clicked | `MOE_EMAIL_CLICK` | Email |
| Email Unsubscribed | `MOE_EMAIL_UNSUBSCRIBE` | Email |
| Email Spam Complained | `MOE_EMAIL_SPAM` | Email |
| SMS Sent | `SMS_SENT` | SMS |
| SMS Delivered | `SMS_DELIVERED` | SMS |
| Notification Received Android | `NOTIFICATION_RECEIVED_MOE` | Push |
| Notification Clicked Android | `NOTIFICATION_CLICKED_MOE` | Push |
| Notification Swiped Android | `NOTIFICATION_CLEARED_MOE` | Push |
| Notification Sent iOS | `n_i_s` | Push |
| Notification Clicked iOS | `NOTIFICATION_CLICKED_IOS_MOE` | Push |
| Notification Received Web | `NOTIFICATION_RECEIVED_WEB_MOE` | Push |
| Notification Clicked Web | `NOTIFICATION_CLICKED_WEB_MOE` | Push |
| Connector Sent | `MOE_CONNECTOR_SENT` | Connector |
| Card Sent | `MOE_CARD_SENT` | Cards |
| Card Delivered | `MOE_CARD_DELIVERED` | Cards |
| Card Viewed | `MOE_CARD_VIEWED` | Cards |
| Card Clicked | `MOE_CARD_CLICKED` | Cards |
| Mobile In-App Shown | `MOE_IN_APP_SHOWN` | Mobile In-Apps |
| Mobile In-App Clicked | `MOE_IN_APP_CLICKED` | Mobile In-Apps |
| Mobile In-App Closed | `MOE_IN_APP_DISMISSED` | Mobile In-Apps |
| On-site Message Shown | `MOE_ONSITE_MESSAGE_SHOWN` | On-site Messaging |
| On-site Message Clicked | `MOE_ONSITE_MESSAGE_CLICKED` | On-site Messaging |
| On-site Message Closed | `MOE_ONSITE_MESSAGE_DISMISSED` | On-site Messaging |
| User Entered Flow | `USER_ENTERED_FLOW` | Flows |
| User Exited Flow | `USER_EXITED_FLOW` | Flows |
| User Added to Control Group | `MOE_CAMPAIGN_CONTROL_GROUP` | All channels |
* With the events above, the following event attributes will be exported by default: `campaign_id`, `campaign_name`, `campaign_type`, `campaign_channel`.
* The following event attributes are not supported for export in streams currently: `email_subject`, `email_click_url`, `inapp_widget_clicked`, `onsite_message_url_clicked`.
For more information on when the campaign events and attributes are tracked, refer to [Data Exports Glossary](https://help.moengage.com/hc/en-us/articles/15975781928468-Data-Export-Glossary).
## Authentication Methods
Streams supports the following types of authentications:
* **No auth**
* **Basic Auth**: Streams supports the standard Basic Auth implementation. You must provide us with the username and password while configuring Streams. All data related to authentication is always encrypted in our systems.
To support other authentication methods such as API Key, Bearer Token, and so on, you can communicate the same through the enablement ticket and provide us the Header key and static value to be passed. We will not be able to support dynamically refreshing API keys and tokens.
## API Request Format
When Streams sends an event to your API endpoint, the request format will be as below:
**Headers:** `"Content-Type":"application/json"`
**Request Body:**
```json theme={null}
{
"app_name": "App Name",
"source": "MOENGAGE",
"moe_request_id": "moengage unique request id for each request",
"events": [{
"event_name": "Notification Received Android",
"event_code": "NOTIFICATION_RECEIVED_MOE",
"event_uuid": "moengage unique id for each event",
"event_time": 1580967474,
"event_type": "CAMPAIGN_EVENT",
"event_source": "MOENGAGE",
"push_id": "recipient device’s push token",
"uid": "",
"event_attributes": {
"campaign_id": "353df897hkbh67658",
"campaign_name": "Name of the Campaign",
"campaign_type": "Event Trigger",
"campaign_channel": "Push"
},
"user_attributes": {
"moengage_user_id": "moe_internal_user_id",
"user_attr_1": "user_attr_val1",
"user_attr_2": "user_attr_val2"
},
"device_attributes": {
"moengage_device_id": "moe_internal_device_id",
"device_attr_1": "device_attr_val1",
"device_attr_2": "device_attr_val2"
}
}]
}
```
## Streams Data Glossary
For the full list of updated events and attributes, refer to [Data Exports Glossary](https://help.moengage.com/hc/en-us/articles/15975781928468-Data-Export-Glossary).
The keys in the API request and their description are:
| Key | Description |
| :------------------- | :----------------------------------------------------------- |
| workspace name | Your workspace name in MoEngage. |
| source | `MoEngage` to identify the requests coming from MoEngage. |
| event\_name | Display Name of the event as seen on the MoEngage dashboard. |
| event\_code | Raw event code as present in the MoEngage system. |
| event\_uuid | Unique event identifier for de-duplication. |
| event\_time | Time of event in UTC (epoch time in seconds). |
| event\_type | `CAMPAIGN_EVENT` or `USER_ACTION_EVENT`. |
| event\_source | Source identifier (value = `MoEngage`). |
| push\_id | Push token (available for Push-related events). |
| email\_id | Recipient email (available for Email-related events). |
| mobile\_number | Recipient mobile number (available for SMS-related events). |
| uid | MoEngage `customer_id` unique identifier. |
| campaign\_name | Campaign name in MoEngage. |
| campaign\_id | Campaign ID in MoEngage. |
| event\_attributes | Dictionary of additional event attributes. |
| campaign\_channel | Channel type: Push / Email / SMS. |
| user\_attributes | Dictionary of additional user properties. |
| moengage\_user\_id | MoEngage internal user ID. |
| device\_attributes | Dictionary of additional device attributes. |
| campaign\_type | Type: Periodic, Active, One-time. |
| variation\_id | Present for campaign variations. |
| locale\_id | Present for campaigns with multiple locales. |
| locale\_name | Display name of the locale. |
| parent\_campaign\_id | Identifier for localized campaign parents. |
| parent\_flow\_id | Identifier for campaigns within a MoEngage Flow. |
| parent\_flow\_name | Name of the MoEngage Flow. |
## Limitations
Please be aware of the following constraints or limitations while integrating Streams with third-party apps.
* We can send data to only one static endpoint where the access token or link has no expiry. We cannot integrate it on a dynamic endpoint where the access token is refreshed every few hours.
* We cannot modify the body or key names while streaming the data from MoEngage.
## Sync Events from One MoEngage App to Another
With MoEngage Streams, it is possible to sync your events from one MoEngage App to another. The following are some use cases:
* **Cross-Product Promotions**: If you have teams across various product offerings, keeping two apps synced can help you cross-promote your products to upsell and increase conversion.
* **Centralized Analysis**: Businesses with multiple apps can do cross-app analysis to unlock higher LTV, provide opportunities for cross-selling, and increase brand loyalty.
## Stream Events to Another MoEngage App
Speak to your CSM to get your dedicated Streams endpoint for your destination app.
Follow the enablement steps to configure the source App with the following details:
* **Endpoint:** Use the dedicated MoEngage endpoint provided for your destination app.
* **Authentication:** Enable Basic Auth. Use your destination app's **Workspace ID** as Username and its **Data API Key** as Password.
* **Header:** Provide `"Content-Type" : "application/json"`.
* **Events/Properties:** Select the list of events and user properties you want to stream.
## Frequently Asked Questions
The throughput and average volume of each API request depends on the volume of selected events captured into MoEngage. The default batch size (number of events for each API request) is 100.
In case a batch of events fail (any non-2XX response), the entire batch is retried. In total, three retry attempts are made with intervals of 30, 60, and 120 seconds.
No. If you pause Streams, data is not collected for exports and cannot be replayed at a later date.
No. Streams is built for near real-time event export. Since user attributes are updated asynchronously, we cannot guarantee the latest values in the export.
No. You can only export data generated after the Streams configuration is enabled.
# Device Opt-out
Source: https://moengage.com/docs/api/device/device-opt-out
/api/data/data.yaml post /devices/manage
This API blocks or unblocks specific devices from receiving push notifications triggered from MoEngage. To prevent push notifications from reaching a specific user or all devices associated with a user, call the API to block them. This is useful for reasons such as device theft or fraudulent activity. For example, if a device is stolen, you can use this API to block it in MoEngage, ensuring that any scheduled push notifications with sensitive content do not get delivered. You can also use the API to unblock a device if it is recovered.
#### Rate Limit
The rate limit is 1000 API requests per minute.
# Track Device
Source: https://moengage.com/docs/api/device/track-device
/api/data/data.yaml post /device/{app_id}
This API adds or updates devices and device properties in MoEngage. You can create a new device for an existing user, create new device properties for an existing user, or update the device properties of the existing user.
#### Rate Limit
A single API request contains one or more device updates. Maintain a rate limit of 10,000 device updates per minute..
# Email Subscription Overview
Source: https://moengage.com/docs/api/email-subscription/email-subscription-overview
Manage user email resubscription, opt-in status, and category preferences.
The MoEngage Email Subscription Management APIs allow you to update email preferences for your users directly within the MoEngage platform. This suite enables you to synchronize resubscription status with external Email Service Providers (ESPs) and manage granular category-level opt-ins to ensure compliance and a better user experience.
## Endpoints
The Email Subscription API consists of the following endpoints:
* [Bulk Resubscribe Users](/api/resubscribe/bulk-resubscribe-users): Resubscribes users and optionally updates ESP suppression lists.
* [Update User Email Opt-in Preferences](/api/opt-in-management/update-user-email-opt-in-preferences): Updates overall opt-in status and category-specific preferences.
## API Capabilities
| Feature | Bulk Resubscribe | Opt-in Management |
| ----------------------- | ---------------------- | ----------------- |
| **Sync with ESP** | ✓ (SendGrid supported) | ✗ |
| **Category Management** | ✗ | ✓ |
| **Bulk Processing** | ✓ (Up to 100 users) | ✗ (Single User) |
| **Async Processing** | ✓ | ✗ |
## Implementation Notes
**ESP Support:**
The Resubscription API currently supports **SendGrid** only. When `update_esp` is set to `true`, MoEngage automatically removes the email addresses from your SendGrid suppression list.
**Identity Management for Opt-in:**
* **PII Tokenization:** You must pass the `customer_id`. MoEngage uses this to locate the user as the email ID is not stored.
* **PII Encryption:** Pass either the `customer_id` or the decrypted `email_id`. If only the email ID is passed, all users associated with that email will be updated.
## FAQs
### Resubscription
We will automatically call the ESP to remove the recipient email addresses sent in the request from their suppression list.
This attribute is configured in the User Attribute that stores user’s email address field in the General Settings for the Email channel. You can either use the “Email Standard” attribute that MoEngage uses by default or configure any other custom attribute of your choice to store the email address of your users. This attribute is available in the User Profile for each user.
The Resubscription API will use this attribute to look for the users mapped to the email addresses in the recipient list and update their subscription status.
The Current Connector field in Email -> General Settings has the information about which ESP is used. The Resubscription API will use this information to update the suppression list in the ESP.
If any other ESP is sent in the request or configured as the default connector, then only the Unsubscribe standard attribute in MoEngage will be updated to false, and the ESP will not be updated (only Sendgrid ESP is supported for the Resubscription API).
When the ESP is changed in the Email General Settings, it takes up to 15 minutes for the settings to get reflected. If a resubscription request is executed within this time frame, the older settings will get picked. For example, if the ESP is changed from Amazon to SendGrid and a resubscription request is performed within 15 minutes of updating the settings, the ESP would still be Amazon. The unsubscribe flag will get updated in the MoEngage Dashboard alone.
The Data API updates only the unsubscribe attribute in MoEngage. The Resubscribe Email API additionally syncs with your ESP (SendGrid) to remove the email from their suppression list.
### Opt-in and Categories
The user attribute specified in the General Settings of email will be used to search for users matching the provided email ID.
Email ID is given higher priority, and MoEngage finds all users with the same email ID and updates them with the passed opt-in status value. However, if you have requested not to carry forward the opt-in status or unsubscribe information across profiles with the same email ID, MoEngage picks the customer\_id and uses it to update the opt-in status.
Yes, they are carried forward by default. If User A and B have the same email ID and MoEngage received consent from A, both A and B are marked as double-opted in. This can always be controlled. To do so, contact the MoEngage team.
If the API payload has even one category that is not active or present in your workspace, MoEngage throws an error and drops the request.
No, it is not mandatory. If required, you can always track this at the global level.
Suppose API key rotation is practiced, and the workspace has more than one active API key for a smoother transition. In that case, you can use any active API key associated with Email Double optin for authorization purposes.
Whenever a user's opt-in status is updated using this API, the Resubscribe API, the Update Subscription Preference API, or via the end-user interaction, MoEngage raises an event called Email Optin Status Updated with the necessary information.
* If you use PII Tokenization for your emails, ensure you pass the user ID when calling the Email Opt-in Management API. MoEngage uses this user ID to locate the user and update their opt-in status. Passing the email ID is ineffective in this case, as MoEngage does not store it.
* If you use PII Encryption to send emails, ensure you pass either the user ID or the decrypted email ID. MoEngage uses this information to locate the associated user and update their opt-in status, or to update the opt-in status of all users having that email ID.
## Postman Collections
Test these subscription APIs immediately using our Postman collection. View Postman Collection → [**Resubscribe API**](https://www.postman.com/moengage-dev/api-docs/collection/xt2ptnc/moengage-resubscribe-api) and [**Email Optin Management**](https://www.postman.com/moengage-dev/api-docs/request/fcc8l9m/email-optin-managment?tab=overview).
# Email Templates (V1) Overview
Source: https://moengage.com/docs/api/email-templates-1/email-templates-1-overview
Define, reuse, update, and manage email templates created outside the MoEngage ecosystem effortlessly.
The MoEngage Email Template API allows marketers to define, reuse, update, and manage email templates created outside the MoEngage ecosystem with ease. The templates created and updated using these APIs are supported for the Custom HTML Editor (Froala Editor) and not the Drag and Drop Editor.
## Endpoints
The Email Template API (V1) is a collection of the following endpoints:
* [Create Email Template](/api/email-templates/create-email-template-v1): Creates an email template.
* [Update a Specific Email Template](/api/email-templates/update-specific-template): Updates an email template specified by its Template ID.
* [Bulk Create/Update Email Template](/api/email-templates/bulk-createupdate-templates): Creates and updates email templates in bulk.
* [Get a Specific Email Template](/api/email-templates/get-specific-template): Fetches an email template using its Template ID.
* [Get all Email Templates](/api/email-templates/get-all-templates): Fetches all the email templates in your MoEngage account.
## FAQs
### Create Email Template
You can access templates created using the Create Email Template API in the My Saved Templates tab during the second step of campaign creation in the MoEngage Dashboard, as illustrated in the image below:
### Update a Specific Email Template
The update request will overwrite the existing template with the template shared in the update request. If the update request does not have some of the fields that the created template had, the updated template will not have them too. For example, if you do not pass any attachments in the update request, the updated template will not have any attachments, even if it had attachments while it was created.
### Bulk Create/Update Email Template
In the case of an update, the template to be updated is identified using its template id. It is mandatory to pass the id field in the required for an update template request. Otherwise, it will be treated as a create template request.
### Get a Specific Email Template
The error description contains the following message in such a case: “*Template for given template id is archived*”.
## Postman Collection
Test these endpoints quickly by importing our Postman collection: [**View in Postman**](https://www.postman.com/moengage-dev/api-docs/collection/dc04rwi/moengage-content-email-template-apis-v2?action=share\&creator=3182294)
# Email Templates (V2) Overview
Source: https://moengage.com/docs/api/email-templates-2/email-templates-2-overview
Define, reuse, update, and manage email templates created outside the MoEngage ecosystem effortlessly.
The MoEngage Email Template API allows marketers define, reuse, update, and manage email templates created outside the MoEngage ecosystem effortlessly. You can create multiple versions of the same template and mark whether they can be used in the campaigns that are active currently. Users can create templates using the Create Email Template API and update them using the Update Email Template API or edit them in the MoEngage dashboard (provided they have the specific editing permissions for the templates allowed for their role). The templates created and updated using these APIs are supported for the Custom HTML Editor (Froala Editor) and not the Drag and Drop Editor.
## Endpoints
The Email Template API (V2) is a collection of the following endpoints:
* [Create Email Template API](/api/email-templates/create-email-template-v2): Creates an email template.
* [Update Email Template API](/api/email-templates/update-email-template): Updates an email template specified by its Template ID.
* [Search Email Template API](/api/email-templates/search-email-template): Fetches an email template using its Template ID or other filters like template name, template version, and so on. It can also list all the email templates created in MoEngage using the Create Email Template API.
## FAQs
### Create Email Template API
You can access templates created using the Create Email Template API in the Imported API Templates tab in the second step of campaign creation in the MoEngage Dashboard, as illustrated in the image below:
Yes, you can create multiple templates with the same name, provided they have different versions.
# Bulk Create/Update Templates
Source: https://moengage.com/docs/api/email-templates/bulk-createupdate-templates
/api/email-templates-1/email-templates-1.yaml put /bulk/email-templates
This API creates or updates email templates in bulk. You can create or update up to 50 templates in a single request.
#### Rate Limit
The rate limits are at the workspace level, and a maximum of 1000 (sum of all the API requests per workspace) requests are allowed for a workspace per minute.
# Create Email Template (V1)
Source: https://moengage.com/docs/api/email-templates/create-email-template-v1
/api/email-templates-1/email-templates-1.yaml post /email-templates
This API creates an email template in MoEngage. You can use this API to upload templates created outside the MoEngage ecosystem to MoEngage and use them for campaign creation on the MoEngage dashboard.
#### Rate Limit
The rate limits are at the workspace level, and a maximum of 1000 (sum of all the API requests per workspace) requests are allowed for a workspace per minute.
# Create Email Template (V2)
Source: https://moengage.com/docs/api/email-templates/create-email-template-v2
/api/email-templates-2/email-templates-2.yaml post /custom-templates/email
This API creates an email template in MoEngage. You can use this API to upload templates created outside the MoEngage ecosystem to MoEngage and use them for campaign creation. The uploaded templates can be edited in the Froala editor (custom HTML editor) on the MoEngage dashboard.
#### Rate Limit
The rate limit is 100 RPM. You can upload a maximum of 10000 templates per channel.
# Get All Templates
Source: https://moengage.com/docs/api/email-templates/get-all-templates
/api/email-templates-1/email-templates-1.yaml get /email-templates
This API fetches the list of all the email templates available in your MoEngage account.
#### Rate Limit
The rate limits are at the workspace level, and a maximum of 1000 (sum of all the API requests per workspace) requests are allowed for a workspace per minute.
# Get Specific Template
Source: https://moengage.com/docs/api/email-templates/get-specific-template
/api/email-templates-1/email-templates-1.yaml get /email-templates/{id}
This API fetches an email template using its template ID.
#### Rate Limit
The rate limits are at the workspace level, and a maximum of 1000 (sum of all the API requests per workspace) requests are allowed for a workspace per minute.
# Search Email Template
Source: https://moengage.com/docs/api/email-templates/search-email-template
/api/email-templates-2/email-templates-2.yaml post /custom-templates/email/search
This API searches the email templates created in your MoEngage account.
**Note**
We are introducing mandatory pagination, effective November 15, 2025, all calls to this API must include the following two parameters:
* `page`: The page number of the results you wish to fetch.
* `entries`: The number of templates to return per page, with a maximum value of 15.
Please update all integrations to include these parameters. API requests submitted without them after the effective date will result in an error and fail to execute.
#### Rate Limit
The rate limit is 100 Requests Per Minute.
# Update Email Template
Source: https://moengage.com/docs/api/email-templates/update-email-template
/api/email-templates-2/email-templates-2.yaml put /custom-templates/email
This API updates an email template by specifying its external template ID. You can specify whether the updated version of the template can be used in active campaigns in the request.
#### Rate Limit
The rate limit is 100 Requests Per Minute.
# Update Specific Template
Source: https://moengage.com/docs/api/email-templates/update-specific-template
/api/email-templates-1/email-templates-1.yaml put /email-templates/{id}
Updates an existing email template by specifying its template ID in the path.
#### Rate Limit
The rate limits are at the workspace level, and a maximum of 1000 (sum of all the API requests per workspace) requests are allowed for a workspace per minute.
# Track Event
Source: https://moengage.com/docs/api/event/track-event
/api/data/data.yaml post /event/{Workspace_ID}
This API tracks the actions of a user.
* If you have [Portfolio](https://help.moengage.com/hc/en-us/articles/40394603054100-Portfolio) enabled for your workspace, you need to pass project\_code in the API endpoint. This identifies which project a user or event belongs to. For more information, refer to [Portfolio: Data Ingestion and Management](https://help.moengage.com/hc/en-us/articles/40358246598804-Portfolio-Data-Ingestion-and-Management).
* MoEngage does not accept any future dated events.
#### Rate Limit
A single API request contains one or more events. Maintain a rate limit of 30,000 events per minute.
# Track Experience Events
Source: https://moengage.com/docs/api/events/track-experience-events
/api/personalize-experience/personalize-experience.yaml post /experiences/events
This API tracks impressions (shown) and user interactions (clicked) for accurate experience reporting. To report an impression or click for your experience via API, use the following endpoint.
# Fetch Experience
Source: https://moengage.com/docs/api/experiences/fetch-experience
/api/personalize-experience/personalize-experience.yaml post /experiences/fetch
This API receives data on active personalization experiences. You can fetch data for one or more server-side experiences by using the **experience_key** field. MoEngage will evaluate targeting rules and in-session attributes automatically and return the correct variation for the user. Typically, you would make this call as part of your larger page and content rendering pipeline.
# Fetch Experience Metadata
Source: https://moengage.com/docs/api/experiences/fetch-experience-metadata
/api/personalize-experience/personalize-experience.yaml get /experiences/metadata
This API fetches a list of currently Active, Scheduled, and Paused experiences within a workspace.
# Import Details
Source: https://moengage.com/docs/api/file-import/import-details
/api/data/data.yaml post /fileimports/import/status
This API fetches the status at an import level. It can fetch the status of multiple imports but not the status of the files within the import.
#### Rate Limit
You can create 50 requests per minute.
# Import File Run History
Source: https://moengage.com/docs/api/file-import/import-file-run-history
/api/data/data.yaml post /fileimports/import/run/history
This API fetches the file processing status of each file contained in an import. The API request must contain either the import_name or the import_id. If you are not sure of the import_id or the import_name, you can use the [Import Details API](https://www.moengage.com/docs/api/file-import/import-details) to get the import details, which can be further used in the Import File Run History API.
#### Rate Limit
You can create 50 requests per minute.
# Trigger File Imports
Source: https://moengage.com/docs/api/file-import/trigger-file-imports
/api/data/data.yaml post /fileimports/trigger/{schedule_id}
This API triggers scheduled file imports. You can trigger periodic imports to run using this API if the import has not expired and is in any of the following states- Scheduled, Successful, Partially Successful, and Failed.
#### Rate Limit
You can trigger this API once in every five minutes for a specific schedule\_id. A Bad request response (400) response will be sent if this is exceeded.
# Add Users to File Segment
Source: https://moengage.com/docs/api/file-segments/add-users-to-file-segment
/api/custom-segments/custom-segments.yaml put /v2/custom-segments/file-segment/add-users
This API adds a list of users from a CSV file to an existing file segment.
This API endpoint does not currently support Team-level scoping. All segments generated using this call will be assigned to the Default Team automatically.
# Create File Segment
Source: https://moengage.com/docs/api/file-segments/create-file-segment
/api/custom-segments/custom-segments.yaml post /v2/custom-segments/file-segment
This API creates a new file segment from a CSV file URL.
* If your file is private, you should whitelist [these IPs](https://help.moengage.com/hc/en-us/articles/35329024618772-A-Guide-to-MoEngage-IP-Whitelisting-Mechanism#h_01JNGJNR5F141E7KRK89YW1X8H) to provide access only to MoEngage for the file.
* This API endpoint does not currently support Team-level scoping. All segments generated using this call will be assigned to the Default Team automatically.
#### Rate Limits
| Rate Limit Name | Rate Limit |
| :-------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------- |
| total active segment | The limit of the total number of active segments at a time for a client is 1000. |
| file\_segment ops per hour | The total number of file segment operations (create/add/remove) per hour per client allowed is 10. |
| file\_segment ops per day | The total number of file segment operations (create/add/remove) per day per client allowed is 100. |
| file\_segment users per day | The total number of users uploaded via the File segment is limited to 2 million per day. (This limit is customizable, contact the MoEngage Support team). |
| file\_size\_limit | The size of the file from which the segment is created/updated. For each request, the file size limit is 150 MB. |
**Notes**
* Breaching the limits will reject the request.
* Per hour and per day limits will consider the calculation based on the last hour and last 24 hrs respectively.
* The limit of 1000 file segments is calculated only for the file segments that are active. Most of our customers utilize only 30-40% of this limit at any given point.
#### CSV File Requirements
* The attribute names should be separated by new lines.
* CSV should be a single column and less than 150MB.
* Values should not end with a comma (e.g., `abcd` not `abcd,`).
* Values should not have duplicates or special characters (e.g., `abcd` not `"abcd"` or `a#bc`).
* File should not have empty rows or columns.
* A user attribute value must uniquely identify a single user.
* [Sample File Link](https://app-cdn.moengage.com/assets/Sample_GAIDs.csv)
#### Segment Processing and Availability
As soon as the request is received at the MoEngage system, MoEngage creates a segment with zero users. After this, the file is processed and users are added to the segment. If the created segment is queried in between the file processing, it will show zero or partial user count.
# Remove Users from File Segment
Source: https://moengage.com/docs/api/file-segments/remove-users-from-file-segment
/api/custom-segments/custom-segments.yaml put /v2/custom-segments/file-segment/remove-users
This API removes a list of users from a CSV file from an existing file segment.
This API endpoint does not currently support Team-level scoping. All segments generated using this call will be assigned to the Default Team automatically.
# Replace Users from File Segment
Source: https://moengage.com/docs/api/file-segments/replace-users-from-file-segment
/api/custom-segments/custom-segments.yaml put /v2/custom-segments/file-segment/replace
This API replaces all users in an existing file segment with a new list of users from a CSV file.
**Notes:**
* This API drops all existing users from the segment and adds the new users provided in the File URL.
* Only the newly added users are counted towards the daily file segment user limit.
* This API does not currently support Team-level scoping. All segments generated using this call will be assigned to the Default Team automatically.
# Create Filter Segment
Source: https://moengage.com/docs/api/filter-segments/create-filter-segment
/api/custom-segments/custom-segments.yaml post /v3/custom-segments
This API creates a new segment based on a set of filter conditions.
This API endpoint does not currently support Team-level scoping. All segments generated using this call will be assigned to the Default Team automatically.
#### Generate Request from Dashboard
To simplify the request generation, MoEngage has added an option in the dashboard where you can specify filters as per your requirement and generate the payload.
1. Login to the MoEngage dashboard.
2. Click **Test & Debug** at the lower left in the side panel.
3. Click **Segment Payload**.
4. Specify the name for your segment payload and provide the required filters.
5. Click **Generate payload** button.
#### Rate Limit
The rate limit is 50 request/minute, 200 requests/hour, and 1000 requests/day.
# Get Segment by ID
Source: https://moengage.com/docs/api/filter-segments/get-segment-by-id
/api/custom-segments/custom-segments.yaml get /v3/custom-segments/{id}
This API fetches a specific segment (File or Filter) by its ID.
This API endpoint does not currently support Team-level scoping. All segments generated using this call will be assigned to the Default Team automatically.
#### Rate Limit
The rate limit is 100 requests/minute, 1000 requests/hour, and 4000 requests/day.
# List Segments
Source: https://moengage.com/docs/api/filter-segments/list-segments
/api/custom-segments/custom-segments.yaml get /v3/custom-segments
This API lists all segments. You can optionally filter segments by an exact name match.
This API endpoint does not currently support Team-level scoping. All segments generated using this call will be assigned to the Default Team automatically.
#### Rate Limit
The rate limit is 50 request/minute, 200 requests/hour, and 1000 requests/day.
# Update Filter Segment
Source: https://moengage.com/docs/api/filter-segments/update-filter-segment
/api/custom-segments/custom-segments.yaml patch /v3/custom-segments/{id}
This API updates an existing filter segment by its ID.
This API endpoint does not currently support Team-level scoping. All segments generated using this call will be assigned to the Default Team automatically.
# GDPR or CCPA Overview
Source: https://moengage.com/docs/api/gdpr-ccpa/gdpr-ccpa-overview
Manage user data privacy rights and erasure requests to ensure GDPR and CCPA compliance.
The MoEngage GDPR or CCPA API ensures that all user data rights are respected and managed for compliance with the General Data Protection Regulation (GDPR) and the California Consumer Privacy Act (CCPA). This API allows you to submit data requests, including the permanent erasure of personal data for specific users.
For detailed implementation guides on how MoEngage handles these regulations, refer to our [GDPR Implementation](https://help.moengage.com/hc/en-us/articles/360000878126-GDPR) and [CCPA Implementation](https://help.moengage.com/hc/en-us/articles/360052917232-CCPA) documentation.
## Endpoint
The GDPR or CCPA API consists of the following endpoint:
* [Submit a Data Request](/api/gdpr/submit-a-gdprccpa-data-request): Create or update user rights (e.g., erasure requests).
## FAQs
No. Multiple users cannot be deleted using this API in a single payload. You must send individual requests for different users unless they share the same email identity (see note above).
If multiple users have the same email ID and that email ID is passed in the erasure request, MoEngage will delete **all** users associated with that specific email ID.
The maximum payload size is 128 KB. If this limit is exceeded, a 413 error response will be sent.
## Postman Collections
Test your compliance workflows using our pre-configured Postman collection. [View Postman Collection →](https://www.postman.com/moengage-dev/api-docs/request/j4fwuwk/gdpr-ccpa-api?action=share\&source=copy-link\&creator=9636111)
# Submit a GDPR / CCPA Data Request
Source: https://moengage.com/docs/api/gdpr/submit-a-gdpr-ccpa-data-request
/api/gdpr-ccpa/gdpr-ccpa.yaml post /opengdpr_requests/{appId}
GDPR or CCPA API ensures all the rights of users are created or updated for GDPR or CCPA compliance. You can erase the personal data of specific users as defined under GDPR using the Erase API.
For more details on compliance with MoEngage, refer to [GDPR-Implementation](https://help.moengage.com/hc/en-us/articles/360000878126-GDPR) and [CCPA-Implementation](https://help.moengage.com/hc/en-us/articles/360052917232-CCPA).
**Warning:** Multiple users **cannot** be deleted using this API in a single payload. If an email ID associated with multiple users is passed for an erasure request, **all** associated users will be deleted.
#### Rate Limit
The maximum limit per request is **100 KB**. The maximum payload size is **128 KB**.
# Get Campaign Meta
Source: https://moengage.com/docs/api/get-campaign-details/get-campaign-meta
/api/campaigns/campaigns.yaml post /campaigns/meta
This API retrieves campaign details and reachability information for scheduled campaigns.
#### Supported Channels
* EMAIL: Email campaigns
* PUSH: Push notification campaigns
* SMS: SMS campaigns
* WHATSAPP: WhatsApp campaigns
* FACEBOOK: Facebook campaigns
* GOOGLE ADS: Google Ads campaigns
* CONNECTORS: Connector-based campaigns
#### Reachability Information
* Available only for **scheduled** campaigns (one-time, business event-triggered, and event-triggered).
* Provides estimated user count that will receive the campaign.
* Calculated once daily and cached for 24 hours.
* May vary due to app installations/uninstalls or subscription changes.
* Reachability is an estimated value and may vary over time. It is calculated once per day and cached for 24 hours. Multiple API calls within the same day will return the cached value.
# Get Child Campaigns
Source: https://moengage.com/docs/api/get-campaign-details/get-child-campaigns
/api/campaigns/campaigns.yaml post /campaigns/{parent_campaign_id}/executions
This API retrieves child campaign execution details for Periodic or Business Event-triggered campaigns. Use this API to track execution history of recurring campaigns and monitor the performance of individual instances.
#### Information Retrieved
* Child campaign IDs
* Sent time for each execution
* Status of each child campaign
* Total number of times the parent campaign has been executed
**Note**
* Currently, you can use this API to get the child of Periodic and Business Event-triggered Email and Push campaigns.
* You can only retrieve child campaigns for campaigns created via the [Create Campaign API](https://www.moengage.com/docs/api/create-campaigns/create-campaign).
* Results are paginated with a maximum of 15 children per page.
# Search Campaigns
Source: https://moengage.com/docs/api/get-campaign-details/search-campaigns
/api/campaigns/campaigns.yaml post /campaigns/search
This API fetches a list of Push, Email, or SMS campaigns with all current fields and status. You can pass multiple filters to find specific campaigns.
#### Search Capabilities
* Filter by channel, delivery type, status, tags, name, ID, created by, created date
* Include child campaigns (flow nodes, periodic children)
* Include archived campaigns
* Paginated results (max 15 per page)
**API Enablement:**
If this API is not enabled for your account, contact your MoEngage Customer Success Manager (CSM) or the Support team to request enablement.
# Create In-app Template
Source: https://moengage.com/docs/api/in-app-templates/create-in-app-template
/api/in-app-templates/in-app-templates.yaml post /custom-templates/inapp
This API creates an In-app template in MoEngage. You can use this API to upload templates created outside the MoEngage ecosystem to MoEngage and use them for campaign creation.
**Information**
Only self-handled and HTML template types are supported.
# In-app Templates Overview
Source: https://moengage.com/docs/api/in-app-templates/in-app-templates-overview
Create, search, and update In-app templates (Self-Handled and HTML).
The MoEngage In-app Templates API allows you to seamlessly manage In-app templates within the MoEngage platform. This API enables you to upload templates created outside the MoEngage ecosystem—supporting both **Self-Handled** and **HTML** types—so they can be used for campaign creation.
With these endpoints, you can create versions of your templates, search through your existing library using various filters, and choose whether updates to a template should automatically reflect in your active campaigns.
## Endpoints
The In-app Templates API is a collection of the following endpoints:
* [Create In-app Template](/api/in-app-templates/create-in-app-template): Creates a new In-app template (Self-Handled or HTML).
* [Update In-app Template](/api/in-app-templates/update-in-app-template): Updates an existing template.
* [Search In-app Templates](/api/in-app-templates/search-in-app-templates): Finds templates using filters like name, source, type, or creator ID.
## FAQs
Currently, the API supports **SELF\_HANDLED** (JSON-based) and **INAPP\_HTML** template types.
When using the **Update In-app Template** API, set the `update_campaigns` flag to `true`. This will update all running campaigns currently using that template to the latest version.
## Postman Collection
Test these endpoints quickly by importing our Postman collection: [**View in Postman**](https://www.postman.com/moengage-dev/api-docs/collection/wada9u5/moengage-in-app-api?action=share\&source=copy-link\&creator=28342601)
# Search In-app Templates
Source: https://moengage.com/docs/api/in-app-templates/search-in-app-templates
/api/in-app-templates/in-app-templates.yaml post /custom-templates/inapp/search
This API searches the In-app templates created in your MoEngage account.
**Mandatory Pagination**
We are introducing mandatory pagination, effective **November 15, 2025**. All calls to this API must include the following two parameters:
* `page`: The page number of the results you wish to fetch.
* `entries`: The number of templates to return per page, with a maximum value of *15*.
Please update all integrations to include these parameters. API requests submitted without them after the effective date will result in an error and fail to execute.
# Update In-app Template
Source: https://moengage.com/docs/api/in-app-templates/update-in-app-template
/api/in-app-templates/in-app-templates.yaml put /custom-templates/inapp
This API updates an In-app template as per your requirements.
# Inform Overview
Source: https://moengage.com/docs/api/inform/inform-overview
Send a transactional alert to a user on one or more channels.
The MoEngage Inform API allows you to send a transactional alert to a user on one or more channels using a pre-configured Alert ID or Alert Reference Name.
## Supported Scenarios
Transactional Alerts are designed for critical user communications, including:
* Order/Booking/Purchase confirmations
* Shipping/Delivery confirmations and updates
* Security and account alerts
* Password resets
* OTP (one-time password)
* User invitations and shares
* User inaction related to previous transactions
* Fraud prevention/security alerts
This API sends notifications to all the channels simultaneously for a specified Live Alert. You can use it to do the following:
* Send a transactional message on a single channel like SMS or Email or Push.
* Send transactional messages on multiple channels.
## Endpoint
The Inform API consists of the following endpoint:
* [Inform API](/api/transactional-alerts/send-transactional-alert)
## Glossary
The following is a list of terminology that you will encounter when using the Inform API.
| Term | Definition |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Alert ID** | This is the unique identifier for an Alert. This field will be used to identify the Alert configured in the MoEngage Dashboard that contains the template for the notifications to be sent to the user. |
| **Alert Reference Name** | This field is used to identify the Alert using your reference Name and can be used to identify the alert as an alternative to Alert ID. |
| **Test Alert ID** | When creating an Alert, you can test it on an external console and MoEngage provides a unique identifier called Test Alert ID for this purpose. |
| **Test Alert Reference Name** | Test Alert Reference Name is configured while adding the alert on the Dashboard to send this Test Alert request to an external console. |
## Live vs. Test Environments
Ensure you are using the correct ID and Endpoint for your environment.
| Feature | Live Alerts | Test Alerts |
| :------------- | :------------------------------------------------ | :-------------------------------------------------------- |
| **Identifier** | Use the **Alert ID** for published alerts. | Use the **Test Alert ID** for testing. |
| **Logs** | Logs are available in the **Alert Info** section. | Logs are available in the **3rd Step** of Alert Creation. |
| **Endpoint** | `https://api-0{dc}.moengage.com` | `https://sandbox-api-0{dc}.moengage.com` |
## How Does Inform API Work and Respond?
Inform API works in two steps as described below:
1. A check is performed to verify if the API request received for Inform is valid.
2. If valid, the second process is to resolve the content and send a message using the partner.
### Response Codes
The response codes are shared in **wxyzab** format as described below:
* **w** - Status (failures are indicated with 1 and success is indicated with 2).
* **x** - Category of the error.
* **y** - Request is considered for parallel request (parallel requests is indicated with 0 and fallback requests are indicated with 1).
* **z** - Can this request be retried by you(0 indicates it cannot be retried with same details).
* **ab** - Reason details for the error.
Below are the Category details:
| Category Code | Details |
| :------------ | :-------------------------------- |
| 1 | Unauthorized |
| 2 | Bad Request |
| 4 | Internal Server Error / Ratelimit |
The Reason details are given below with each Reason Code holding specific meanings:
| Reason Code | Details |
| :---------- | :-------------------------- |
| 1 | Invalid Credentials |
| 2 | Invalid Alert ID |
| 3 | Missing Transaction ID |
| 4 | Duplicate Transaction ID |
| 5 | Long Transaction ID |
| 6 | Invalid Payload |
| 7 | Personalisation Attribute |
| 9 | Internal Server Error |
| 10 | Rate Limit |
| 11 | Personalisation Failed |
| 12 | Invalid Recipient details |
| 13 | Vendor configuration errors |
| 14 | Vendor not available |
| 15 | Vendor Payload Rejection |
| 16 | Unexpected Error Occurred |
| 17 | Invalid Origin Source |
## Payload Errors Before Accepting the API Request
The list of the payload errors that can occur before accepting the API request and the equivalent response codes to be shared under HTTP status code **4xx** for different scenarios across each functionality is given below:
| Payload Errors | Description | Scenarios | Response Codes | Resolution |
| :--------------------------------------- | :----------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------- |
| **Authorization Failure** | This error occurs when invalid authorization details such as App Key (Workspace ID) or Password are shared. | No Auth values passed. Incorrect Auth Values Passed Incorrect Password shared. No Auth & No Key Passed No App key shared / Empty App Key Incorrect App Key shared | `{"message": "Authorization Failed", "err_code": "UNAUTHORIZED"}` | Recheck the authorization details listed in Settings / Check if you passed the Test Alert ID on Live Endpoint. |
| **Invalid Alert ID** | This error occurs when an invalid Alert ID or external reference name is shared. | Missing Alert ID Alert ID \<24 characters Alert ID > 24 Characters Invalid Alert ID | `{"message": "Invalid Alert ID", "err_code": "BAD_REQUEST", "status_code": 120002}` | Recheck the Alert ID or external reference name listed on the Info page. |
| **Invalid Transaction ID** | This error occurs when the Transaction ID is not shared. | Missing Transaction ID | `{"message": "Invalid Transaction ID", "err_code": "BAD_REQUEST", "status_code": 120003}` | Share the transaction ID using the key name `transaction_id` as part of the API Call. |
| **Long Transaction ID** | This error occurs when the Transaction ID is invalid. | Long Transaction ID | `{"message": "Long Transaction ID", "err_code": "BAD_REQUEST", "status_code": 120004}` | Reduce the length of the Transaction ID to 50 characters. |
| **Duplicate Transaction ID** | This error occurs when the currently shared Transaction ID matches the previous one in the last 5 minutes. | Duplicate Transaction ID | `{"message": "Duplicate Transaction ID", "err_code": "DUPLICATE_REQUEST_RECEIVED", "status_code": 120105}` | Add a unique Transaction ID. |
| **Invalid Payload** | This error occurs when the payload is in incorrect JSON format or when incorrect Channel details are shared. | Invalid JSON / Invalid Class Channel Attribute is incorrect / Channel details missing | `{"message": "Invalid Payload", "err_code": "BAD_REQUEST", "status_code": 120006}` | Recheck the JSON format and the Channel details. Sample payload is available on our Info page. |
| **Personalisation Attribute Max length** | This error occurs when the Personalization Attribute length is greater than 1500 characters. | - | `{"message": "Personalisation attribute limit exceeded - {x}", "err_code": "BAD_REQUEST", "status_code": 120007}` | Reduce the length of the Personalization Attribute to 1500 characters / payload size of \<100 KB |
| **Invalid Recipient** | This error occurs when the recipient details like mobile number or email address are invalid. | - | `{"message": "Invalid Recipient", "err_code": "BAD_REQUEST", "status_code": 120012}` | Recheck the recipient details in the API call or the User Profile. |
| **Internal Server Error** | This error occurs when MoEngage is not able to resolve the API request. | - | `{"message": "Unexpected error occurred", "err_code": "Internal Server Error", "status_code": 140109}` | Retry using the same API call with a different Transaction ID. |
| **Rate Limit** | This error occurs when you cross the Rate Limit. | - | `{"message": "Too many requests", "err_code": "Rate Limit", "status_code": 140110}` | Make API calls within the Rate Limit. |
## Payload Errors After Accepting the API Request
Alerts can be configured for parallel/sequential fallback as described below:
* **Parallel**: For parallel requests, the payload information of success/failure requests should be added at each channel level.
* **Sequence**: For fallback requests, the payload information of success/failure requests should be added for the first channel, and other channels, info should be shared over streams.
The list of the payload details that can occur after accepting the API request and the equivalent response codes to be shared under HTTP status code \*\*200/429 \*\*for different scenarios across each functionality is given below:
| Payload Errors | Description | Response Codes | Resolution |
| :---------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :--------------------------------------------------------------------------------------------------------------------- |
| **Personalisation Failed** | This error occurs when the required Personalization attributes are not shared in the API call or User Profile doesn't have these values. | `{"message": "Successfully Received", "Request_ID": 122323, "SMS": {"message": "Personalisation Failure - {{attribute name}}", "err_code": "BAD_REQUEST", "status_code": "120011 / 121011"}}` | Either share the valid Personalization attributes in the API call or update the User Profile with the required values. |
| **Invalid Recipient details** | This error occurs when the recipient details like mobile number or email address are invalid. | `{"message": "Successfully Received", "Request_ID": 122323, "SMS": {"message": "Invalid Recipient", "err_code": "BAD_REQUEST", "status_code": "120012 / 121012"}}` | Recheck the recipient details in the API call or the User Profile. |
| **Internal Errors** | This error occurs when MoEngage is not able to resolve the API request or channel level details. | `{"message": "Successfully Received", "Request_ID": 122323, "SMS": {"message": "Unexpected error occurred", "err_code": "Internal Server Error", "status_code": "140109 / 141109"}}` | Retry using the same API call with a different Transaction ID. |
| **Vendor Errors** | This error occurs when the vendor configuration is invalid. | `{"message": "Successfully Received", "Request_ID": 122323, "SMS": {"message": "Invalid Vendor Configuration", "err_code": "Vendor Error", "status_code": "150013 / 151013"}}` | Recheck the vendor configuration in MoEngage for SMS, Push, and Email. |
| **Vendor Unavailable** | This error occurs when the vendor is not available. | `{"message": "Successfully Received", "Request_ID": 122323, "SMS": {"message": "Vendor not available", "err_code": "Vendor Error", "status_code": "150014 / 151014"}}` | NA/MoEngage will retry up to 5 times to submit the message to the vendor. |
| **Vendor Rejected** | This error occurs when the vendor rejects the Payload. | `{"message": "Successfully Received", "Request_ID": 122323, "SMS": {"message": "Rejected by Vendor with error - {{error from vendor}}", "err_code": "Vendor Error", "status_code": "150015 / 151015"}}` | Resolve the error sent by the vendor and then make the API call. |
| **Vendor Accepted** | This is sent as response when vendor accepts the request. | `{"message": "Successfully Received", "Request_ID": 122323, "SMS": {"message": "Successfully sent", "err_code": "NA", "status_code": 200000}}` | - |
## FAQs
A request is deemed a duplicate in the following cases:
* It is received within 5 minutes of a previously successful request containing the same transaction\_id
* It is received within 5 minutes of a previous request which is ‘In Progress’ (being processed) and contains the same transaction\_id
Duplicate requests are dropped and not reprocessed.
When the vendor does not accept requests from MoEngage, MoEngage retries every request a maximum of five times with 200ms exponential backoff.
Alert logs are stored for up to 30 days for every Alert in MoEngage.
This error occurs when you hit the live alert ID at the sandbox endpoint. For every alert, there are 2 IDs: one is live, and another is Test; the same behavior can be seen for alerts created on the test environment of the MoEngage Dashboard as well. Test Alert ID can be picked up by editing the Alert and going to the 3rd page.
## Postman Collection
Test these endpoints quickly by importing our Postman collection: [View in Postman](https://www.postman.com/moengage-dev/api-docs/collection/n3e0uj9/moengage-inform-api).
# API Overview
Source: https://moengage.com/docs/api/introduction
Explore MoEngage REST APIs for managing user data, campaigns, segments, templates, and integrations.
**Beta**
We are refining the new API docs. While exploring them, you may encounter minor issues. We appreciate your patience as we finalize the content.
The [existing API docs](https://developers.moengage.com/hc/en-us/categories/4404541620756-API) will be accessible until the transition is complete.
## API Categories
Create and update users, track events, manage devices, and import data in bulk.
Create and trigger business events to power automated campaigns.
Manage templates, content blocks, recommendations, coupons, and catalogs.
Create and manage Push and Email campaigns programmatically.
Create and manage file-based, filter-based, and cohort-synced user segments.
Manage email subscriptions and subscription category preferences.
Send transactional and targeted push notifications to Android, iOS, and Web.
Fetch and manage App Inbox cards for users.
Send transactional alerts across SMS, Email, and Push channels.
Start, update, and end iOS Live Activities via broadcast.
Fetch and manage personalized experiences for users.
View and retrieve archived messages.
***
## Data Centers
MoEngage maintains multiple data centers. You are assigned to a specific data center when you sign up. You can identify your data center from your dashboard URL.
| Data Center | Dashboard URL | REST API Host |
| ----------- | ------------------------------------ | ------------------------------ |
| DC-01 | `https://dashboard-01.moengage.com` | `https://api-01.moengage.com` |
| DC-02 | `https://dashboard-02.moengage.com` | `https://api-02.moengage.com` |
| DC-03 | `https://dashboard-03.moengage.com` | `https://api-03.moengage.com` |
| DC-04 | `https://dashboard-04.moengage.com` | `https://api-04.moengage.com` |
| DC-05 | `https://dashboard-05.moengage.com` | `https://api-05.moengage.com` |
| DC-06 | `https://dashboard-06.moengage.com` | `https://api-06.moengage.com` |
| DC-101 | `https://dashboard-101.moengage.com` | `https://api-101.moengage.com` |
### Choosing a Data Center
If you have data privacy requirements to store user data in a specific geographical region:
* **US region**: Sign up with DC-01 or DC-04
* **EU region**: Sign up with DC-02
* **India region**: Sign up with DC-03
* **Singapore region**: Sign up with DC-05
* **Indonesia region**: Sign up with DC-06
After data is captured in a workspace, it cannot be migrated to a different data center. Always use the REST API endpoint matching your registered data center.
***
## Base URL
All API requests are made to:
```text theme={null}
https://api-{dc}.moengage.com
```
Replace `{dc}` with your data center number (e.g., `01`, `02`, `03`). You can identify your data center from your Dashboard URL.
Each API may have additional path segments (e.g., `/v1`, `/core-services/v1`). Refer to the specific API documentation for the complete endpoint path.
***
## Authentication
All MoEngage API requests require Basic Authentication. To authenticate, you must include a Base64-encoded string of your credentials in the Authorization header of every request. Basic Authentication sends a Base64-encoded string containing your username and password with every API request. It encodes a 'username:password' string in Base64 and appends the encoded string with 'Basic '. This string is included in the authorization header as shown below:
`{"Authorization: Basic Base64_ENCODED_WORKSPACEID_APIKEY=="}`
### Required Headers
```http theme={null}
Authorization: Basic {base64_encoded_credentials}
MOE-APPKEY: {your_workspace_id}
Content-Type: application/json
```
### Generating Credentials
The `Authorization` header value is a Base64 encoding of `workspace_id:api_key`.
```bash theme={null}
# Example: Encoding credentials
echo -n "YOUR_WORKSPACE_ID:YOUR_API_KEY" | base64
```
### Getting Your Credentials
1. Log in to the [MoEngage dashboard](https://dashboard.moengage.com).
2. Navigate to **Settings** > **Account** > **APIs**.
3. Copy your **Workspace ID** and the relevant **API Key**.
You can perform authentication using a client like Postman as follows:
### API Keys by Feature
Different APIs require different API keys from your dashboard:
| API | API Key Location (Settings → Account → APIs) |
| --------------------- | -------------------------------------------------------------------------- |
| Data | Data |
| Push | Push |
| Inform | Inform |
| Campaigns and Catalog | Campaign report/Business events/Custom templates/Catalog API/Inform Report |
| Personalize | Personalize |
## Rate Limits
Rate limits vary by API. Headers are included in responses to help you manage usage.
| API | Rate Limit |
| ---------------------------- | ------------------------------------------------------ |
| **Campaigns API** | 5 requests/min, 25 requests/hour, 100 requests/day |
| **Catalog API** | 100 requests/min or 1,000 requests/hour |
| **Campaign Stats API** | 100 requests/min/workspace |
| **Custom Segments (Filter)** | 50 requests/min, 200 requests/hour, 1,000 requests/day |
| **Custom Segments (File)** | 10 operations/hour, 100 operations/day |
### Rate Limit Response Headers
```http theme={null}
x-ratelimit-limit: 100
x-ratelimit-remaining: 95
x-ratelimit-reset: 1699574400
```
### Payload Size Limits
| API | Max Payload Size |
| ---------------------- | ---------------- |
| Catalog API | 5 MB |
| Recommendations API | 1 MB |
| Bulk Import API | 100 KB |
| Custom Segments (File) | 150 MB per file |
***
## Error Handling
All APIs return consistent error responses.
### Standard Error Format
```json wrap theme={null}
{
"status": "fail",
"error": {
"message": "The request parameters are invalid",
"type": "Bad Request",
"request_id": "abc123xyz"
}
}
```
### HTTP Status Codes
| Code | Description |
| ----- | ---------------------------------- |
| `200` | Success |
| `201` | Created |
| `202` | Accepted (async processing) |
| `400` | Bad Request - Invalid parameters |
| `401` | Unauthorized - Invalid credentials |
| `403` | Forbidden - Access denied |
| `404` | Not Found - Resource doesn't exist |
| `409` | Conflict - Duplicate resource |
| `413` | Payload Too Large |
| `429` | Rate Limit Exceeded |
| `500` | Internal Server Error |
***
## Key Endpoints Reference
### Data
| Method | Endpoint | Description |
| ------ | ------------------------------------ | ------------------------ |
| `POST` | `/customer/{Workspace_ID}` | Create or update user |
| `POST` | `/customers/export` | Get user details |
| `POST` | `/customer/merge` | Merge two users |
| `POST` | `/customer/delete` | Delete users in bulk |
| `POST` | `/event/{Workspace_ID}` | Track user events |
| `POST` | `/transition/{Workspace_ID}` | Bulk import |
| `POST` | `/device/{app_id}` | Create or update device |
| `POST` | `/devices/manage` | Manage devices |
| `POST` | `/fileimports/trigger/{schedule_id}` | Trigger file import |
| `POST` | `/fileimports/import/status` | Get import status |
| `GET` | `/installInfo` | Get install info |
| `POST` | `/integrations/authentication` | Validate authentication |
| `POST` | `/opengdpr_requests/{appId}` | Create GDPR/CCPA request |
### Business Events
| Method | Endpoint | Description |
| ------ | ------------------------- | ---------------------- |
| `POST` | `/business_event` | Create business event |
| `POST` | `/business_event/trigger` | Trigger business event |
| `POST` | `/business_event/search` | Search business events |
### Content
#### Templates
| Method | Endpoint | Description |
| ------ | -------------------------------- | ------------------------ |
| `POST` | `/custom-templates/inapp` | Create In-App template |
| `PUT` | `/custom-templates/inapp` | Update In-App template |
| `POST` | `/custom-templates/inapp/search` | Search In-App templates |
| `POST` | `/custom-templates/osm` | Create OSM template |
| `PUT` | `/custom-templates/osm` | Update OSM template |
| `POST` | `/custom-templates/osm/search` | Search OSM templates |
| `POST` | `/custom-templates/sms` | Create SMS template |
| `PUT` | `/custom-templates/sms` | Update SMS template |
| `POST` | `/custom-templates/sms/search` | Search SMS templates |
| `POST` | `/email-templates` | Create Email template |
| `GET` | `/email-templates` | Get all Email templates |
| `GET` | `/email-templates/{id}` | Get Email template by ID |
| `PUT` | `/email-templates/{id}` | Update Email template |
| `POST` | `/custom-templates/email` | Create Email template V2 |
| `PUT` | `/custom-templates/email` | Update Email template V2 |
| `POST` | `/custom-templates/push` | Create Push template |
| `PUT` | `/custom-templates/push` | Update Push template |
| `POST` | `/custom-templates/push/search` | Search Push templates |
#### Content Blocks
| Method | Endpoint | Description |
| ------ | ---------------------------- | ------------------------- |
| `POST` | `/content-blocks` | Create content block |
| `PUT` | `/content-blocks` | Update content block |
| `POST` | `/content-blocks/get-by-ids` | Get content blocks by IDs |
| `POST` | `/content-blocks/search` | Search content blocks |
#### Recommendations
| Method | Endpoint | Description |
| ------ | --------------------------------------------- | ------------------------ |
| `GET` | `/recommendations/{recommendations_id}` | Get recommendations |
| `POST` | `/recommendations/{recommendations_id}/items` | Get recommendation items |
#### Coupons
| Method | Endpoint | Description |
| -------- | ------------------------------------------------------ | -------------------- |
| `POST` | `/coupon-list` | Create coupon list |
| `GET` | `/coupon-list` | List coupon lists |
| `GET` | `/coupon-list/{coupon_list_id}` | Get coupon list |
| `PATCH` | `/coupon-list/{coupon_list_id}` | Update coupon list |
| `PUT` | `/coupon-list/{coupon_list_id}/activate` | Activate coupon list |
| `PUT` | `/coupon-list/{coupon_list_id}/archive` | Archive coupon list |
| `POST` | `/coupon-list/{coupon_list_id}/files` | Upload coupon file |
| `GET` | `/coupon-list/{coupon_list_id}/files` | List coupon files |
| `GET` | `/coupon-list/{coupon_list_id}/files/{coupon_file_id}` | Get coupon file |
| `DELETE` | `/coupon-list/{coupon_list_id}/files/{coupon_file_id}` | Delete coupon file |
| `POST` | `/coupon-list/{coupon_list_id}/usage-report` | Get usage report |
#### Catalog
| Method | Endpoint | Description |
| ------- | ----------------------------------------- | ---------------------- |
| `POST` | `/catalog` | Create catalog |
| `PATCH` | `/catalog/{catalog_id}/attributes` | Add catalog attributes |
| `POST` | `/catalog/{catalog_id}/items` | Ingest catalog items |
| `POST` | `/catalog/{catalog_id}/items/search` | Search catalog items |
| `PATCH` | `/catalog/{catalog_id}/items` | Update catalog items |
| `POST` | `/catalog/{catalog_id}/items/bulk-delete` | Delete catalog items |
### Campaigns
| Method | Endpoint | Description |
| ------- | ------------------------------------------------ | ------------------------ |
| `POST` | `/campaigns` | Create campaign |
| `PATCH` | `/campaigns/{campaign_id}` | Update campaign |
| `POST` | `/campaigns/search` | Search campaigns |
| `POST` | `/campaigns/test` | Test campaign |
| `POST` | `/personalization/preview` | Preview personalization |
| `POST` | `/campaigns/meta` | Get campaign metadata |
| `POST` | `/campaigns/status` | Get campaign status |
| `POST` | `/campaigns/{parent_campaign_id}/executions` | Get campaign executions |
| `POST` | `/core-services/v1/campaign-stats` | Get campaign stats |
| `GET` | `/campaign_reports/rest_api/{APP_ID}/{FILENAME}` | Download campaign report |
### Segments
| Method | Endpoint | Description |
| ------- | ----------------------------------------------- | ------------------------- |
| `POST` | `/v2/custom-segments/file-segment` | Create file segment |
| `PUT` | `/v2/custom-segments/file-segment/add-users` | Add users to segment |
| `PUT` | `/v2/custom-segments/file-segment/remove-users` | Remove users from segment |
| `PUT` | `/v2/custom-segments/file-segment/replace` | Replace segment users |
| `GET` | `/v3/custom-segments` | List filter segments |
| `POST` | `/v3/custom-segments` | Create filter segment |
| `GET` | `/v3/custom-segments/{id}` | Get segment by ID |
| `PATCH` | `/v3/custom-segments/{id}` | Update filter segment |
| `POST` | `/v1/integrations/cohortsync` | Sync cohort audience |
| `PATCH` | `/v2/custom-segments/archive` | Archive segment |
| `PATCH` | `/v2/custom-segments/unarchive` | Unarchive segment |
### Subscriptions
| Method | Endpoint | Description |
| ------ | ------------------------------------------ | ------------------------------- |
| `POST` | `/emails/v1.0/bulk-resubscribe` | Bulk resubscribe emails |
| `PUT` | `/v1.0/opt-in-management/user-preferences` | Update opt-in preferences |
| `GET` | `/category-subscription/user-preferences` | Get subscription preferences |
| `PUT` | `/category-subscription/user-preferences` | Update subscription preferences |
| `POST` | `/category-subscription/user-preferences` | Create subscription preferences |
### Push
| Method | Endpoint | Description |
| ------ | ----------------------- | ---------------------- |
| `POST` | `/transaction/sendpush` | Send push notification |
### Cards
| Method | Endpoint | Description |
| -------- | --------------- | ------------ |
| `POST` | `/cards/fetch` | Fetch cards |
| `DELETE` | `/cards/delete` | Delete cards |
### Inform
| Method | Endpoint | Description |
| ------ | -------------- | ----------------------------------------- |
| `POST` | `/alerts/send` | Send transactional alert (SMS/Email/Push) |
### Live Activities
| Method | Endpoint | Description |
| ------ | --------------------------------- | -------------------- |
| `POST` | `/live-activity/broadcast/start` | Start Live Activity |
| `POST` | `/live-activity/broadcast/update` | Update Live Activity |
| `POST` | `/live-activity/broadcast/end` | End Live Activity |
### Personalize
| Method | Endpoint | Description |
| ------ | ----------------------- | ----------------------- |
| `POST` | `/experiences/fetch` | Fetch experiences |
| `GET` | `/experiences/metadata` | Get experience metadata |
| `POST` | `/experiences/events` | Track experience events |
### Message Archival
| Method | Endpoint | Description |
| ------ | ---------------- | ---------------------- |
| `POST` | `/archival/view` | View archived messages |
***
## Support
Need help with the API?
* **Help Center**: [help.moengage.com](https://help.moengage.com/hc/en-us)
* **Support**: Contact your Customer Success Manager or reach out via the dashboard.
# Add Items
Source: https://moengage.com/docs/api/items/add-items
/api/catalog/catalog.yaml post /catalog/{catalog_id}/items
This API ingests items into an existing catalog as long as the attributes provided during ingestion match the attributes provided during catalog creation.
#### Rate Limit
* Request limit: You can ingest 100 items per minute OR 1000 items per hour. You can ingest up to 50 items per request.
* Payload size limit: 5 MB only when Content-Length header is provided.
# Delete Items
Source: https://moengage.com/docs/api/items/delete-items
/api/catalog/catalog.yaml post /catalog/{catalog_id}/items/bulk-delete
This API deletes existing items in a given catalog.
#### Rate Limit
* Request limit: You can delete 100 items per minute OR 1000 items per hour. You can delete up to 50 items per request.
* Payload size limit: 5 MB only when Content-Length header is provided.
# Get Items
Source: https://moengage.com/docs/api/items/get-items
/api/catalog/catalog.yaml post /catalog/{catalog_id}/items/search
This API retrieves item attribute details for catalog items using their unique item IDs. The attributes can include the title, price, category, link, image_link, and the respective creation date.
#### Rate Limit
* Request limit: You can get 100 item attribute details per minute OR 1000 item attribute details per hour. You can request up to 50 items per request.
* Payload size limit: 5 MB only when the Content-Length header is provided.
The limit is a COMBINED limit across all Catalog APIs for a specific user.
# Update Items
Source: https://moengage.com/docs/api/items/update-items
/api/catalog/catalog.yaml patch /catalog/{catalog_id}/items
This API updates items with new attribute values. Attributes must adhere to the data type defined.
#### Rate Limit
* Request limit: You can update 100 items per minute OR 1000 items per hour. You can update up to 50 items per request.
* Payload size limit: 5 MB only when Content-Length header is provided.
# End Broadcast Live Activity
Source: https://moengage.com/docs/api/live-activities/end-broadcast-live-activity
/api/live-activities/live-activities.yaml post /live-activity/broadcast/end
This API terminates a broadcast Live Activity across all subscribed devices simultaneously, with options for a final state update or immediate dismissal.
#### Rate Limit
The rate limit for this endpoint is 500 requests per minute per workspace and 5 requests per minute per live activity ID.
# Live Activities Overview
Source: https://moengage.com/docs/api/live-activities/live-activities-overview
Initiate, update, and terminate shared real-time activities for iOS users.
The MoEngage Broadcast Live Activities API enables brands to manage shared, real-time experiences for large audiences on iOS. This is ideal for live sporting events, election tracking, or breaking news where multiple users need to see the same real-time updates on their lock screens or Dynamic Island.
Live Activities can only be managed for push campaigns created with the **BROADCAST\_LIVE\_ACTIVITY** delivery type via the [Create Push Campaigns API](https://developers.moengage.com/hc/en-us/articles/38466364097044-Create-Push-Campaigns). These campaigns cannot be created through the MoEngage UI.
## Endpoints
The Broadcast Live Activities API consists of the following endpoints:
* [**Start Broadcast Live Activity**](/api/live-activities/start-broadcast-live-activity): Initiates the shared activity and sends the initial content to the target audience.
* [**Update Broadcast Live Activity**](/api/live-activities/update-broadcast-live-activity): Pushes unified updates (e.g., score changes) to all subscribed devices.
* [**End Broadcast Live Activity**](/api/live-activities/end-broadcast-live-activity): Terminates the activity session across all devices.
## FAQs
No. Live Activities are a native iOS feature. This API specifically targets iOS devices supporting the ActivityKit framework.
The `broadcast_live_activity_id` refers to the overarching campaign ID created via the Push API. The `instance_id` is an optional field you can provide to track a specific session or prevent duplicate requests for the same event.
Content is updated via the `content_state` JSON object. The keys within this object must match the `ContentState` struct defined in your iOS application code.
## Postman Collection
Test these endpoints quickly by importing our Postman collection: [View in Postman](https://www.postman.com/moengage-dev/api-docs/folder/etd05kq/start-live-activity)
# Start Broadcast Live Activity
Source: https://moengage.com/docs/api/live-activities/start-broadcast-live-activity
/api/live-activities/live-activities.yaml post /live-activity/broadcast/start
This API initiates a shared, real-time activity for a large audience, such as a live sporting match or real-time election result tracking.
You can start live activities for only push campaigns created with the BROADCAST\_LIVE\_ACTIVITY delivery type using the [Create Push Campaigns API](https://www.moengage.com/docs/api/create-campaigns/create-campaign), not campaigns created through the MoEngage UI.
#### Rate Limit
The rate limit for this endpoint is 5 requests per minute per workspace.
# Update Broadcast Live Activity
Source: https://moengage.com/docs/api/live-activities/update-broadcast-live-activity
/api/live-activities/live-activities.yaml post /live-activity/broadcast/update
This API pushes a single, unified update to all subscribed Live Activities, such as an updated game score or a new development in a breaking news story.
#### Rate Limit
The rate limit for this endpoint is 500 requests per minute per workspace and 5 requests per minute per live activity ID.
# Archive Segment
Source: https://moengage.com/docs/api/manage-segments/archive-segment
/api/custom-segments/custom-segments.yaml patch /v2/custom-segments/archive
This API archives an existing segment (File or Filter). Archiving and unarchiving through APIs makes it easy to retrieve and reuse segments whenever required for purposes such as A/B testing, maintaining regulatory compliance, and improving system performance. You can access the archived segments and utilize them to analyze and market campaigns without the need to recreate them from scratch.
Archived segments will not be shown beyond 180 days.
This API endpoint does not currently support Team-level scoping. All segments generated using this call will be assigned to the Default Team automatically.
# Unarchive Segment
Source: https://moengage.com/docs/api/manage-segments/unarchive-segment
/api/custom-segments/custom-segments.yaml patch /v2/custom-segments/unarchive
This API unarchives an existing segment, making it active again.
This API endpoint does not currently support Team-level scoping. All segments generated using this call will be assigned to the Default Team automatically.
# Message Archival Overview
Source: https://moengage.com/docs/api/message-archival/messaage-archival-overview
Retrieve and view archived copies of sent communication across Push, Email, and SMS.
The MoEngage Message Archival API provides a way to store and access historical records of communications sent to your customers. By utilizing this API, you can retrieve the exact content—including titles, messages, and media URLs—that was delivered to a specific user at a specific time.
This is particularly useful for customer support teams who need to verify what a customer received, or for compliance audits where a historical record of messaging is required.
## Endpoint
The Message Archival API consists of the following endpoint:
* [View Archived Message](/api/message-archival/view-archived-message): Retrieves the full content and metadata of a specific message sent to a user via Push, Email, or SMS.
## FAQs
To retrieve a message, you must provide the `user_id`, the `campaign_id`, and the `sent_epoch_time` (Unix timestamp) of the communication. For event-triggered campaigns, passing the `event_id` is also required.
* **message\_content**: Contains the actual personalized content sent to the user.
* **backup\_content**: Contains the original template or default content used if personalization failed or was not applied.
# Message archival overview
Source: https://moengage.com/docs/api/message-archival/message-archival-overview
# View Archived Message
Source: https://moengage.com/docs/api/message-archival/view-archived-message
/api/message-archival/message-archival.yaml post /archival/view
You can use this API to store any communication sent to customers for later access.
#### Rate Limit
The rate limit for this endpoint is **1000 RPM**.
# Update User Email Opt-in Preferences
Source: https://moengage.com/docs/api/opt-in-management/update-user-email-opt-in-preferences
/api/email-subscription/email-subscription.yaml put /v1.0/opt-in-management/user-preferences
This API updates a user's overall email opt-in status and/or category-level subscription preferences within MoEngage. This API is typically used after a user submits the second confirmation through MoEngage consent-seeking emails (Double Opt-in).
#### Rate Limit
The rate limit is **1000 RPM** (requests per minute) and **360K** requests per day.
If you use PII Tokenization for your emails, ensure you pass the user ID when calling the Email Opt-in Management API. MoEngage uses this user ID to locate the user and update their opt-in status. Passing the email ID is ineffective in this case, as MoEngage does not store it.
If you use PII Encryption to send emails, ensure you pass either the user ID or the decrypted email ID. MoEngage uses this information to locate the associated user and update their opt-in status, or to update the opt-in status of all users having that email ID.
# Create OSM Template
Source: https://moengage.com/docs/api/osm-templates/create-osm-template
/api/osm-templates/osm-templates.yaml post /custom-templates/osm
This API creates a new On-Site Messaging (OSM) template. You can use this API to upload templates created outside the MoEngage ecosystem to MoEngage and use them for campaign creation.
API templates cannot be used in the Drag and Drop Editor in the MoEngage Dashboard. They are only supported for the Custom HTML Editor.
#### Rate Limit
The rate limit is 100 RPM. You can upload a maximum of 100 templates per minute.
# OSM Templates Overview
Source: https://moengage.com/docs/api/osm-templates/osm-templates-overview
Create, search, and update On-Site Messaging (OSM) templates.
The MoEngage On-Site Messaging (OSM) Templates API allows you to manage your web and app-site messaging templates. You can use this API to upload custom HTML templates created outside the MoEngage ecosystem, making them available for your OSM campaigns.
This API supports multiple template formats including **Banners**, **Pop-ups**, and **Nudges**. Note that templates created via this API are supported within the **Custom HTML Editor** in the MoEngage Dashboard and cannot be used with the Drag and Drop Editor.
## Endpoints
The OSM Templates API is a collection of the following endpoints:
* [Create OSM Template](/api/osm-templates/create-osm-template): Creates a new OSM template with an HTML payload.
* [Update OSM Template](/api/osm-templates/update-osm-template): Updates an existing OSM template and handles campaign versioning.
* [Search OSM Templates](/api/osm-templates/search-osm-templates): Retrieves templates based on filters like template type, source, or creator.
## FAQs
The API currently supports the creation and management of **BANNER**, **POP\_UP**, and **NUDGE** template types. All payloads must be in HTML format.
No. Templates uploaded via the API are only compatible with the **Custom HTML Editor** in the MoEngage Dashboard.
When updating a template, you can set the `update_campaigns` flag.
* **True**: Automatically updates all running campaigns to the new template version.
* **False**: Creates a new version without affecting existing campaigns.
## Postman Collection
Test these endpoints quickly by importing our Postman collection: [**View in Postman**](https://www.postman.com/moengage-dev/api-docs/collection/28342601-e2d062c4-11b3-45cc-9249-a58d939c3497?action=share\&source=copy-link\&creator=28342601)
# Search OSM Templates
Source: https://moengage.com/docs/api/osm-templates/search-osm-templates
/api/osm-templates/osm-templates.yaml post /custom-templates/osm/search
This API searches the OSM templates created in your MoEngage account.
**Mandatory Pagination**
We are introducing mandatory pagination, effective **November 15, 2025**. All calls to this API must include the following two parameters:
* `page`: The page number of the results you wish to fetch.
* `entries`: The number of templates to return per page, with a maximum value of *15*.
Please update all integrations to include these parameters. API requests submitted without them after the effective date will result in an error and fail to execute.
* If the request body is passed empty, then all templates will be returned.
* The `preview_image` field in the response will be generated by MoEngage for the HTML template payload.
#### Rate Limit
The rate limit is 100 RPM.
# Update OSM Template
Source: https://moengage.com/docs/api/osm-templates/update-osm-template
/api/osm-templates/osm-templates.yaml put /custom-templates/osm
This API updates an OSM template as per your requirements.
#### Rate Limit
The rate limit is 100 RPM.
# Personalize Overview
Source: https://moengage.com/docs/api/personalize-experience/personalize-overview
Fetch personalized content and report experience events from your server-side codebase.
Personalize APIs constitute a set of endpoints that allow you to deliver tailored user experiences directly from your platform's code. Unlike client-side personalization, these server-side APIs must be invoked within your rendering pipeline to receive relevant data.
Once your platform receives the personalized payload, you can use it to dynamically render content—such as banners, product recommendations, or pricing—specifically for the requesting user. MoEngage automatically evaluates targeting rules, in-session attributes, and segments to return the correct variation.
## Endpoints
The Personalize API suite is categorized into experience management and event reporting:
* [Fetch Experience](/api/experiences/fetch-experience): Evaluates targeting rules and returns the personalized payload (variations) for a user.
* [Fetch Experience Metadata](/api/experiences/fetch-experience-metadata): Retrieves a list of all currently Active, Scheduled, or Paused experiences.
* [Track Experience Events](/api/events/report-experience-events): Tracks impressions (shown) and user interactions (clicked) for accurate campaign reporting.
## Reporting Experience Events
You can report impressions and clicks for server-side experiences using either the API or a MoEngage SDK, depending on your platform:
| Method | Platforms | Notes |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Track Experience Events API](/api/events/track-experience-events) | All (Web, Mobile, TV, etc.) | **Recommended.** Works across all platforms and keeps tracking logic consistent with server-side content delivery. The API request to report clicks remains the same as the one to report impressions. The only change is to the value of the **action** field (*MOE\_PERSONALIZATION\_MESSAGE\_SHOWN* or *MOE\_PERSONALIZATION\_MESSAGE\_CLICKED*). |
| [MoEngage Web SDK](https://developers.moengage.com/hc/en-us/articles/39084350090772-Personalize-API-Experience-events-tracking#h_01JXWHX5488QT9XMEN0R5WPX6P) | Web | Use the Personalize SDK to report experience events from a website. |
| [MoEngage Android SDK](https://developers.moengage.com/hc/en-us/articles/38474488247444-Personalize-Experience-Events-Tracking#h_01JXWHX5488QT9XMEN0R5WPX6P) | Android | Report experience events natively from an Android app. |
| [MoEngage iOS SDK](https://developers.moengage.com/hc/en-us/articles/38532362954004-Personalize-Experience-Events-tracking#h_01JY0XF2DW9VKRF3S7G5FNR4XR) | iOS | Report experience events natively from an iOS app. |
## FAQs
### Experience Management
Yes. By passing multiple values in the `experience_key` array (e.g., `["hero-banner", "sidebar-promo"]`), you can receive personalized content for multiple sections of your page in one request.
The API primarily uses the `customer_id`. If that is inaccurate or missing, you can use `user_identifiers` (like email or mobile number) as a fallback, provided **Identity Resolution** is enabled in your MoEngage workspace.
### Security and Events
Only regenerate your API Secret in the event of a security breach. Note that once a new secret is saved, all existing integrations using the old key will immediately stop working.
For server-side personalization, using the **Report Experience Events API** is recommended for all platforms (Web, Mobile, TV) as it keeps the tracking logic consistent with the content delivery logic.
You can use the `b_id` field within the events payload to uniquely identify which element was clicked (e.g., "Add to Cart" vs "Wishlist") within the same personalized experience.
# Push Templates Overview
Source: https://moengage.com/docs/api/push-templates/push-templates-overview
Create, update, and search for push notification templates.
The MoEngage Push Templates API allows you to create, update, and search for push notification templates for Android and iOS platforms. Use these endpoints to manage your template library efficiently and integrate it into your automated workflows.
If this API is not enabled for your account, contact your MoEngage Customer Success Manager (CSM) or the Support team to request enablement.
## Endpoints
The Push Templates API is a collection of the following endpoints:
* [Create Push Template](/api/templates/create-push-template): Creates a push template.
* [Update Push Template](/api/templates/update-push-template): Updates a push template specified by its Template ID.
* [Search for Push Templates](/api/templates/search-for-push-templates): Fetches a push template using its Template ID or other filters like template name, platform, and so on.
## FAQs
Yes, you can send only the iOS payload if you want to create a template for iOS.
Audio and video: All types of video and audio file formats supported by standard FCM/APNS platforms are supported.
**Images:** The following formats are supported: "image/png", "image/jpeg", "image/jpg", "image/gif".
Yes, you can create multiple templates with the same name, provided they have different versions.
## Postman Collections
We have made it easy for you to test the APIs. Click here to view the [Postman collection](https://www.postman.com/moengage-dev/api-docs/folder/3182294-9043f92c-dd0c-4ad7-b619-df7d4b7c4d87).
# Push Overview
Source: https://moengage.com/docs/api/push/push-overview
Create campaigns and send personalized push notifications to individual users or segments across Android, iOS, and Web.
The MoEngage Push API allows you to trigger push notifications. It is designed for high-throughput transactional and marketing use cases, supporting complex targeting logic and deep personalization for every recipient.
Use this API to:
* **Target Segments:** Send notifications to all users or specific pre-defined segments.
* **Target Individuals:** Reach a single user using unique attributes like Email, Mobile Number, or Unique ID.
* **Personalize at Scale:** Use Jinja templating to dynamicially inject user-specific data into the notification payload.
## Endpoint
The Push API consists of the following endpoint:
* [Send Push Notification](/api/transactional/send-push-notification): Creates and sends a push notification campaign.
## FAQs
No, the MoEngage Push API currently does not support silent (data-only) notifications.
Yes, the basic template supports standard HTML tags for text formatting on supported platforms.
You can provide a `fallback` object within the payload. If the personalization logic fails (e.g., a missing user attribute), the system will automatically send the fallback content instead.
In the `targetUserAttributes` object, set the `attribute` field to `PUSH_ID` and provide the device token as the `attributeValue`.
## Postman Collection
We have made it easy for you to test the APIs. Click [here](https://www.postman.com/moengage-dev/api-docs/collection/acmujor/moengage-transaction-push-api?action=share\&source=copy-link\&creator=5883765) to view the collection in Postman.
# Fetch Recommendation Details
Source: https://moengage.com/docs/api/recommendations/fetch-recommendation-details
/api/recommendations/recommendations.yaml get /recommendations/{recommendations_id}
This API retrieves the metadata associated with a specific recommendation setup using its unique ID. The metadata can include the recommendation name, model type, status, creation and update time, and so on.
#### Rate Limit
You can fetch 1,000 recommendations per minute.
# Fetch Recommendation Results
Source: https://moengage.com/docs/api/recommendations/fetch-recommendation-results
/api/recommendations/recommendations.yaml post /recommendations/{recommendations_id}/items
This API fetches/retrieves the metadata results of any recommendations for a user based on their user ID and item ID.
#### Rate Limit
You can fetch 10,000 recommendations per minute.
# Recommendations Overview
Source: https://moengage.com/docs/api/recommendations/recommendations-overview
Fetch recommendation metadata and retrieve personalized item results.
The MoEngage Recommendation API allows you to interact with your recommendation engines. You can retrieve the configuration metadata of a specific recommendation setup or fetch the actual recommended items for a specific user based on various models like "Similar Items," "Frequently Bought Together," or "Trending."
If this API is not enabled for your account, contact your MoEngage Customer Success Manager (CSM) or the Support team to request enablement.
## Endpoints
The Recommendation API is a collection of the following endpoints:
* [Fetch Recommendation Metadata](/api/recommendations/fetch-recommendation-metadata): Fetches configuration details, status, and logic.
* [Fetch Recommendation Results](/api/recommendations/fetch-recommendation-results): Fetches personalized items for a user.
## FAQs
### General Recommendation Questions
The `recommendations_id` is a unique identifier generated when you create a recommendation in the MoEngage Recommendation module. You can find this ID on the individual recommendation's overview page in the MoEngage Dashboard.
By default, the API returns all attributes associated with an item in the catalog. For catalogs with many attributes, this can significantly increase response size and latency. Specifying only the fields you need (e.g., `["title", "price", "image_link"]`) improves performance.
### Fetch Results
The `item_id` acts as an anchor for collaborative filtering models. It is mandatory when the `RECOMMENDATION-TYPE` is set to `similar_item`, `frequently_viewed_together`, or `frequently_bought_together`.
The API requires a valid `user_id`. If the user is unknown or hasn't had any interactions recorded, the recommendation engine may return default items (like trending items) or an empty list depending on your "fallback" settings in the dashboard.
The API will return a `413 Request Entity Too Large` error. This usually happens if the `include_fields` list is excessively long or if a very high number of items are requested (if applicable).
## Postman Collections
Test the Recommendation APIs immediately using our Postman collection. [View Postman Collection](https://www.postman.com/moengage-dev/api-docs/collection/35sr4cv/moengage-recommendation-public-api)
# Generate Usage Report
Source: https://moengage.com/docs/api/reports/generate-usage-report
/api/coupons/coupons.yaml post /coupon-list/{coupon_list_id}/usage-report
This API produces a detailed usage report for a specific coupon list, providing details on which user received which coupon from which locale or variation of which campaign at what time. After it is generated, this report is delivered directly to the requested email addresses. Using this API, you can conduct a comprehensive analysis of critical data and coupon usage trends efficiently.
#### Rate Limit
You can generate:
* 5 usage reports of coupon list per minute or
* 50 usage reports of coupon list per day
# Bulk Resubscribe Users
Source: https://moengage.com/docs/api/resubscribe/bulk-resubscribe-users
/api/email-subscription/email-subscription.yaml post /emails/v1.0/bulk-resubscribe
This API resubscribes users who have previously unsubscribed on the MoEngage platform and an external email vendor platform simultaneously. This API resets the unsubscribe flag to “false” for users on MoEngage and makes a call to an External Service Provider (ESP) like SendGrid to remove the email addresses (associated with the unsubscribed users) from their suppression list.
#### Supported ESPs
The Resubscription API currently supports only **SendGrid**.
#### Rate Limit
The rate limit is **10 RPM** (requests per minute). The allowed volume is **14.4K** requests per day, with a maximum payload size of **100** recipient email addresses per request.
# Create SMS Template
Source: https://moengage.com/docs/api/sms-templates/create-sms-template
/api/sms-templates/sms-templates.yaml post /custom-templates/sms
This API creates an SMS template in MoEngage. It helps you upload templates created outside the MoEngage ecosystem to MoEngage and use them for campaign creation.
#### Rate Limit
The rate limit is **100 RPM**. You can upload a maximum of **100 templates per channel**.
# Search SMS Templates
Source: https://moengage.com/docs/api/sms-templates/search-sms-templates
/api/sms-templates/sms-templates.yaml post /custom-templates/sms/search
This API searches and retrieves a list of SMS templates, created in your MoEngage account, based on specified filter criteria.
**Mandatory Pagination Update**
We are introducing mandatory pagination, effective **November 15, 2025**, all calls to this API must include the following two parameters:
* `page`: The page number of the results you wish to fetch.
* `entries`: The number of templates to return per page, with a maximum value of **15**.
Please update all integrations to include these parameters. API requests submitted without them after the effective date will result in an error and fail to execute.
#### Rate Limit
The rate limit is **100 RPM**.
# SMS Templates Overview
Source: https://moengage.com/docs/api/sms-templates/sms-templates-overview
Use the MoEngage SMS Templates API to create, search, and update reusable SMS templates for campaigns.
The MoEngage SMS Template API allows marketers define, reuse, update, and manage SMS templates created outside the MoEngage ecosystem effortlessly. You can create multiple versions of the same template and mark whether they can be used in the campaigns that are active currently. Users can create templates using the Create SMS Template API and update them using the Update SMS Template API or edit them in the MoEngage dashboard (provided they have the specific editing permissions for the templates allowed for their role).
## Endpoints
The SMS Template API is a collection of the following endpoints:
* [Create SMS Template](/api/sms-templates/create-sms-template): Creates an SMS template.
* [Update SMS Template](/api/sms-templates/update-sms-template): Updates an SMS template specified by its Template ID.
* [Search SMS Template](/api/sms-templates/search-sms-templates): Fetches an SMS template using its Template ID or other filters like template name, template version, and so on. It can also list all the SMS templates created in MoEngage.
## FAQs
### Create SMS Template
Yes, you can create multiple templates with the same name, provided they have different versions.
## Postman Collection
Test these endpoints quickly by importing our Postman collection: [**View in Postman**](https://www.postman.com/moengage-dev/api-docs/collection/n0lb9wd/moengage-custom-templates-api?action=share\&creator=3182294)
# Update SMS Template
Source: https://moengage.com/docs/api/sms-templates/update-sms-template
/api/sms-templates/sms-templates.yaml put /custom-templates/sms
This API updates an SMS template by specifying its external template ID. You can specify in the request whether the updated version of the template can be used in active campaigns.
#### Rate Limit
The rate limit is **100 RPM**.
# Campaign Stats and Reports Overview
Source: https://moengage.com/docs/api/stats-report/stats-report-overview
Fetch real-time campaign performance statistics and download detailed campaign reports programmatically.
The MoEngage Campaign Stats and Reports API allows you to monitor your marketing performance outside of the MoEngage dashboard. Use these endpoints to retrieve real-time platform-level statistics or generate downloadable reports for long-term analysis.
## Endpoints
The Campaign Stats and Reports API is divided into two primary functional areas:
* [Get Campaign Stats](/api/stats/get-campaign-stats): Retrieves real-time performance metrics (clicks, impressions, conversions) at a platform level.
* [Download Campaign Report](/api/campaign-reports/download-campaign-report): Directly downloads campaign data files for specified date ranges.
## Comparison of Capabilities
| Feature | Campaign Stats API | Campaign Report API |
| ----------------- | -------------------------- | ------------------------- |
| **Data Recency** | Real-time | Historical (Date Range) |
| **Output Format** | JSON | ZIP/GZIP File |
| **Batch Limit** | 10 Campaigns per call | 90 Days date range |
| **Primary Use** | Live Monitoring/Dashboards | Deep-dive Analysis/Audits |
## FAQs
### Campaign Statistics
You can pass up to **10 campaign IDs** in the `campaign_ids` array per API call. If you need data for more campaigns, utilize the `offset` and `limit` parameters to paginate through your results.
The `metric_type` parameter allows you to toggle your view. **TOTAL** counts every occurrence (e.g., three clicks by one user), while **UNIQUE** counts the number of distinct users who performed the action.
Yes. The response object is nested by Platform > Locale > Variation, allowing you to see granular performance for A/B tests and localized content.
If only the start date is passed without the end date, the API will return an error response. Both the start and end dates are required to retrieve the desired response.
When providing the start and end dates without any campaign ID, the API will return the stats for both the parent and child campaigns. The stats will be available for the specified time period.
To identify the stats belonging to the parent campaign in the API response, you can use the "Campaign Details and Reachability" API. This API should be called with all the campaign IDs included in the request. The parent campaign ID field will not be available for the parent campaign, allowing you to distinguish it from the child campaigns.
Campaign Details and Reachability APIs will allow you to relate child campaigns to their parent campaigns.
### Campaign Reports
This typically happens if the `FILENAME` provided is incorrect, the report was created more than 7 days ago (expired), or the `APP_ID` in the path does not match your credentials.
Yes, the Report API supports both one-time and periodic campaigns. Ensure the filename matches the specific instance you wish to download.
Verify that your concatenation uses the pipe character (`|`) exactly as shown: `APPID|FILENAME|SECRETKEY`. Ensure the resulting string is encoded in UTF-8 before hashing with SHA256.
Campaigns might not be available to run on the selected date to fetch the report, which could result in an error message.
The reports generated will expire in 7 days from the date of creation.
You can generate reports for up to 90 days.
## Postman Collections
Test your integration and verify your signature logic using our Postman collection. [View Postman Collection](https://www.postman.com/moengage-dev/api-docs/collection/s8t1ta0/moengage-campaign-stats-api) →
# Get Campaign Stats
Source: https://moengage.com/docs/api/stats/get-campaign-stats
/api/stats-report/stats-report.yaml post /core-services/v1/campaign-stats
This API fetches data at the platform level and provides data for all types of campaigns.
#### Rate Limit
This API provides all version stats, and the call rate is limited to **100 API calls per minute** per workspace.
# Subscription Categories Overview
Source: https://moengage.com/docs/api/subscription-categories/subscription-categories-overview
Fetch and update email subscription preferences on your MoEngage dashboard.
The MoEngage Subscription Categories API allows you to manage and synchronize user communication preferences across your systems and MoEngage. These endpoints support fetching individual settings, updating preferences via campaign interactions, and performing high-volume bulk updates. For more information on Subscription categories, refer to [Subscription Categories](https://help.moengage.com/hc/en-us/articles/11053939178004).
## Endpoints
The Subscription Categories API consists of the following endpoints:
* [Get Subscription Preferences](/api/subscription-preferences/get-subscription-preferences): Fetches the subscription category preferences information for a specific user.
* [Update Subscription Preferences](/api/subscription-preferences/update-subscription-preferences): Updates the subscription category preferences information for a specific user who navigates to the custom landing page from the email notification sent to them and updates their preferences.
* [Bulk Update Subscription Preferences](https://moengage.mintlify.app/api/subscription-preferences/bulk-update-subscription-preferences): Updates subscription category preferences in bulk. Use this API for updating the user preferences to MoEngage in large volumes.
## FAQs
### Get Subscription Preferences
The user\_id (MoEngage ID) and the cid (Campaign ID) fields should be fetched from the landing page URL. For example, if the link to the custom landing page was `https://www.abc.com/managepreference`, when the user clicks the same from the email, the link will be as below:
```json theme={null}
https://www.abc.com/managepreference?user_id=7XvJW2dj3iS.rYAt4pg5ASBQtaqAMFDw9e89vZCXx_RFfN3eL0wBG008oI6cpncOQV6ESg&cid=5FGZGcA8FRv3Id89JCCczQjwxq6ApEyAarYDje2mzfRQ_WG7VyyFEc0w4L3MA.31a7wzR64fi7lfq8Km0AaeO4paGVul.4HxixDYnoUp21xyUjGtfvnrHSR2G1reTpYPHHU.r3Ac9vE&app_key=UY_GHXBXyaHbiYnCoNOu7eS.u5yIrrN3noTBNZX5mNSL4KN5C5PZ3zcXBKCCxl9w3m0ukw
```
Here, you can parse and find user\_id and cid
* user\_id is: 7XvJW2dj3iS.rYAt4pg5ASBQtaqAMFDw9e89vZCXx\_RFfN3eL0wBG008oI6cpncOQV6ESg
* cid is: 5FGZGcA8FRv3Id89JCCczQjwxq6ApEyAarYDje2mzfRQ\_WG7VyyFEc0w4L3MA.31a7wzR64fi7lfq8Km0AaeO4paGVul.4HxixDYnoUp21xyUjGtfvnrHSR2G1reTpYPHHU.r3Ac9vE and pass the same while triggering the API.
### Update Subscription Preferences
The user\_id (MoEngage ID) and the cid (Campaign ID) fields should be fetched from the landing page URL. For example, if the link to the custom landing page was `https://www.abc.com/managepreference`, when the user clicks the same from the email, the link will be as below:
```json theme={null}
https://www.abc.com/managepreference?user_id=7XvJW2dj3iS.rYAt4pg5ASBQtaqAMFDw9e89vZCXx_RFfN3eL0wBG008oI6cpncOQV6ESg&cid=5FGZGcA8FRv3Id89JCCczQjwxq6ApEyAarYDje2mzfRQ_WG7VyyFEc0w4L3MA.31a7wzR64fi7lfq8Km0AaeO4paGVul.4HxixDYnoUp21xyUjGtfvnrHSR2G1reTpYPHHU.r3Ac9vE&app_key=UY_GHXBXyaHbiYnCoNOu7eS.u5yIrrN3noTBNZX5mNSL4KN5C5PZ3zcXBKCCxl9w3m0ukw
```
Here, you can parse and find user\_id and cid
* user\_id is: 7XvJW2dj3iS.rYAt4pg5ASBQtaqAMFDw9e89vZCXx\_RFfN3eL0wBG008oI6cpncOQV6ESg
* cid is: 5FGZGcA8FRv3Id89JCCczQjwxq6ApEyAarYDje2mzfRQ\_WG7VyyFEc0w4L3MA.31a7wzR64fi7lfq8Km0AaeO4paGVul.4HxixDYnoUp21xyUjGtfvnrHSR2G1reTpYPHHU.r3Ac9vE and pass the same while triggering the API.
### Bulk Update Subscription Preferences
The maximum batch size is 50.
## Postman Collection
Test these endpoints quickly by importing our Postman collection: [**View in Postman**](https://www.postman.com/moengage-dev/api-docs/collection/30vndhm/moengage-subscription-categories-api)
# Bulk Update Subscription Preferences
Source: https://moengage.com/docs/api/subscription-preferences/bulk-update-subscription-preferences
/api/subscription-categories/subscription-categories.yaml post /category-subscription/user-preferences
This API updates subscription category preferences in bulk. You can use this API to update the user preferences to MoEngage in large volumes.
#### Rate Limit
The rate limit is 100 RPM and 360k per day.
# Get Subscription Preferences
Source: https://moengage.com/docs/api/subscription-preferences/get-subscription-preferences
/api/subscription-categories/subscription-categories.yaml get /category-subscription/user-preferences
This API fetches the subscription category preferences information for a specific user based on the encrypted User ID and Campaign ID found in the landing page URL.
#### Rate Limit
The rate limit is 100 RPM and 360k per day.
# Update Subscription Preferences
Source: https://moengage.com/docs/api/subscription-preferences/update-subscription-preferences
/api/subscription-categories/subscription-categories.yaml put /category-subscription/user-preferences
This API updates the subscription category preferences for a specific user who navigates from an email. This endpoint requires the encrypted IDs obtained from the email link.
#### Rate Limit
The rate limit is 100 RPM and 360k per day.
# Create Push Template
Source: https://moengage.com/docs/api/templates/create-push-template
/api/push-templates/push-templates.yaml post /custom-templates/push
This API creates a new push notification template for one or more platforms (Android, iOS).
#### Rate Limit
The rate limit is 100 RPM (Requests Per Minute).
# Search for Push Templates
Source: https://moengage.com/docs/api/templates/search-for-push-templates
/api/push-templates/push-templates.yaml post /custom-templates/push/search
This API searches the push templates created in your MoEngage account.
We are introducing mandatory pagination, effective November 15, 2025, all calls to this API must include the following two parameters:
* **page**: The page number of the results you wish to fetch.
* **entries**: The number of templates to return per page, with a maximum value of 15.
Please update all integrations to include these parameters. API requests submitted without them after the effective date will result in an error and fail to execute.
#### Rate Limit
The rate limit is 100 RPM (request per minute).
# Update Push Template
Source: https://moengage.com/docs/api/templates/update-push-template
/api/push-templates/push-templates.yaml put /custom-templates/push
This API updates an existing push notification template by creating a new version.
#### Rate Limit
The rate limit is 100 RPM (Requests Per Minute).
# Personalized Preview
Source: https://moengage.com/docs/api/test-campaigns/personalized-preview
/api/campaigns/campaigns.yaml post /personalization/preview
This API shows a preview of personalized content for a specific user before sending a Push, Email, or SMS campaign. This API retrieves personalized message content with all user/event attributes resolved. Use this API to validate your personalization logic and see exactly how content will appear to specific users before launching campaigns.
#### Personalization Support
* User attributes
* Event attributes
* Custom templates
* Content blocks
* Content APIs
* Product sets
#### Rate Limit
The rate limit is 10,000 requests per minute.
# Test Campaign
Source: https://moengage.com/docs/api/test-campaigns/test-campaign
/api/campaigns/campaigns.yaml post /campaigns/test
This API sends a test Push or Email campaign to specific users or identifiers before launching it to your entire audience. You can only test campaigns created via the API, not campaigns created through the MoEngage dashboard.
# Track App Install
Source: https://moengage.com/docs/api/tracking/track-app-install
/api/data/data.yaml get /installInfo
This API tracks the install attribution data in MoEngage, which you can then use to enhance your marketing automation campaigns on MoEngage.
Install attribution tracking is a great way to improve your initial relationship with your user. Knowing how, where, and even more importantly, why a user installs your app allows you to get a better understanding of who your user is and how you should introduce them to your app.
# Send Transactional Alert
Source: https://moengage.com/docs/api/transactional-alerts/send-transactional-alert
/api/inform/inform.yaml post /alerts/send
This API is used to trigger a transactional message/alert to the user via one or more configured channels.
#### Rate Limit
The default rate limit is 10K RPM.
# Send Push Notification
Source: https://moengage.com/docs/api/transactional/send-push-notification
/api/push/push.yaml post /transaction/sendpush
This API creates and sends a push notification campaign. You can use this API to create campaigns (targeting all users or a group of users) to send notifications, target a single user using a unique user attribute, and personalize payload for each user.
#### Rate Limit
The rate limit is 10,000 requests per minute.
#### Authentication
A signature is required to verify whether the client is authorized to make the API call. It is generated from a hash of the campaign name, app ID, and API key. MoEngage uses the SHA 256 method to generate this hash. Python code is used to generate the signature for your test account, and use your account's app\_id.
1. On the left navigation menu in the MoEngage dashboard, go to **Settings** > **Account** > **APIs**.
2. Copy the following details:
* **app\_id**: Under **Workspace ID (earlier app\_id)**, click the copy icon to copy the app-id.
* **api\_key**: In the **API keys** section, click the copy icon in the **Push** tile to copy the API key.
* **campaign\_name**: Ensure the campaign name matches the one used in the request body.
### Generating Signature
Python code to generate the signature for your test account, use the app\_id that is appropriate for your account.
```python
from hashlib import sha256
app_id = "{{Your Workspace ID}}"
campaign_name = "{{your campaign name}}"
api_key = "{{your push api key}}"
signature_key = app_id+'|'+ campaign_name+'|'+ api_key
signature = sha256(signature_key.encode('utf-8')).hexdigest()
print(signature)
```
```python
from hashlib import sha256
app_id = "{{Your Workspace ID}}"
campaign_name = "{{your campaign name}}"
api_key = "{{your push api key}}"
signature_key = app_id+'|'+ campaign_name+'|'+ api_key
signature = sha256(signature_key).hexdigest()
print(signature)
```
# Change Campaign Status
Source: https://moengage.com/docs/api/update-campaigns/change-campaign-status
/api/campaigns/campaigns.yaml post /campaigns/status
This API updates the status of campaigns to stop, pause, or resume them. You can only change the status of campaigns created via the [Create Campaign API](https://www.moengage.com/docs/api/create-campaigns/create-campaign) (not dashboard-created campaigns).
Currently, you can use this API to change the status of Email and Push campaigns. You can update the following statuses of the campaigns:
* Stop a scheduled One-time campaign (Email and Push)
* Pause and resume a running Periodic or Event-triggered Email campaign.
* Pause and resume the following running Push campaigns:
* Periodic
* Event-triggered
* Device-triggered
* Location-triggered
#### Rate Limit
Maximum 10 campaign IDs can be processed per request.
# Update Campaign
Source: https://moengage.com/docs/api/update-campaigns/update-campaign
/api/campaigns/campaigns.yaml patch /campaigns/{campaign_id}
This API updates an existing Push or Email campaign in MoEngage. You can only update campaigns created via the API, not campaigns created through the MoEngage dashboard.
**Update Restrictions**
You cannot update campaigns when in **Stopped** or **Archived** state.
For **Scheduled Campaigns**
* You can edit all fields **except scheduling type** for One-Time campaigns.
* You can edit all fields **except scheduling type** for Periodic/Event-Triggered campaigns if no instance has been sent yet.
For **Active Campaigns**, you cannot edit the following fields:
* Trigger Condition
* Segmentation Details
* Conversion Goal Details
* Scheduling Type
* Scheduling Start Date
For **Event-Triggered campaigns**, updated content is cached and takes up to 30 minutes to take effect.
# Delete Users
Source: https://moengage.com/docs/api/user/delete-users
/api/data/data.yaml post /customer/delete
This API deletes users in MoEngage. You cannot retrieve users once deleted. Users deleted (hard delete) using this API will be deleted after a default buffer of 24 hours. During this buffer period, the user will still be active in MoEngage and will be visible in Segments, Analytics, and Campaigns. You can update users in the buffer period. After the buffer elapses, the user is hard-deleted from MoEngage. If you create a user with the same unique identifiers as the deleted one in MoEngage (through APIs or imports), they will be created again in MoEngage.
#### Rate Limit
The rate limit is 1 user per payload per request. You can run 5000 requests per minute.
# Get User
Source: https://moengage.com/docs/api/user/get-user
/api/data/data.yaml post /customers/export
This API facilitates the retrieval of information of users by specifying the user IDs.
#### Rate Limit
The rate limit is 20 users per payload and 1000 users per minute.
# Merge Users
Source: https://moengage.com/docs/api/user/merge-users
/api/data/data.yaml post /customer/merge
This API merges two users in MoEngage based on their ID, which is a client-defined identifier for a user. You can use this API when multiple profiles have been created for a single user. For example, you can merge a user registered once with a mobile number and once with an email ID. You can also merge duplicate users created due to integration or tech issues.
#### Types of user merging in MoEngage
* Default or normal merge:
* MoEngage merges users with the same ID.
* Happens automatically, and no action is required from your side.
* Manual merge:
* MoEngage merges users having different IDs.
* Does not happen automatically; you must call the Merge User API with the list of users to be merged along with their IDs.
- User Merging is a complex functionality and, if misused, can lead to data integrity issues. If the data passed to the API is incorrect, resulting in a merge of two unintended users, MoEngage will not be able to recover/rectify the data. The retained user would have erroneous data, and segmentation queries would not provide the right results.
- MoEngage does not support transitive/canonical merging. For example, if user A is merged to B (A ->B) and then user B is merged to C (B ->C), in this scenario, events of user A are not moved to user C.
- The Merge User API is not functional in workspaces where the [Identity Resolution](https://help.moengage.com/hc/en-us/articles/24050999467284-Unified-Identity-Identity-Resolution) feature is enabled.
- If you are updating the [Unique Identifier](https://developers.moengage.com/hc/en-us/articles/4404440336148-Tracking-User-Attributes) for a user, use the Merge User API at least 2 hours after you have updated the Unique Identifier.
- Ensure that the data passed to the API is accurate. We recommend you test the merging starting with a small batch of users, such as 1, 5, 10, 20, 50, etc. Verify the merged data and users before proceeding with a bulk update.
#### Rate limit
The rate limit is 1000 user updates per minute.
# Track User
Source: https://moengage.com/docs/api/user/track-user
/api/data/data.yaml post /customer/{app_id}
This API adds or updates users and user properties in MoEngage. You can create a new user, create new user property, or update existing user properties of users.
If you have [Portfolio](https://help.moengage.com/hc/en-us/articles/40394603054100-Portfolio) enabled for your workspace, you must pass `project_code` in the API endpoint. This identifies which project a user or event belongs to. For more information, refer to [Portfolio: Data Ingestion and Management](https://help.moengage.com/hc/en-us/articles/40358246598804-Portfolio-Data-Ingestion-and-Management).
#### Rate Limit
A single API request contains one or more user updates. Maintain a rate limit of 10,000 user updates per minute.
# Test Connection API
Source: https://moengage.com/docs/api/utilities/test-connection-api
/api/data/data.yaml post /integrations/authentication
This API validates if the entered endpoint details are valid. It verifies if the provided endpoint URL, workspace ID, and data key are accessible and responds without any errors.
# Android TV
Source: https://moengage.com/docs/developer-guide/android-sdk/android-tv/android-tv
Integrate MoEngage features like data tracking, in-app messages, and cards into your Android TV app.
MoEngage supports your apps available on Android TV.
Ensure that the [Android SDK integration](/developer-guide/android-sdk/sdk-integration/basic-integration/sdk-initialization) is completed.
# Supported Features
MoEngage supports the following:
* [Data Tracking](/developer-guide/android-sdk/data-tracking)
* [HTML In-App](/developer-guide/android-sdk/in-app-messages/in-app-nativ)
* [Self-handled InApp](/developer-guide/android-sdk/in-app-messages/in-app-nativ)
* [Self-handled Cards](/developer-guide/android-sdk/cards/self-handled-cards)
# Cards
Source: https://moengage.com/docs/developer-guide/android-sdk/cards/cards
Set up MoEngage Cards to deliver persistent inbox and newsfeed messages to your Android app users.
Create targeted or automated App Inbox/NewsFeed messages that can be grouped into various categories, and target your users with different updates or offers that can stay in the Inbox/Feed over a designated period of time. For more information, refer to [Cards](https://help.moengage.com/hc/en-us/articles/360045074752-Create-Cards-Campaign).
# SDK Installation
## Install using BOM
Integration using BOM is the recommended way of integration; refer to the [Install Using BOM](/developer-guide/android-sdk/sdk-integration/basic-integration/Install-Using-BOM) document. Once you have configured the BOM add the dependency in the app/build.gradle file as shown below
```kotlin build.gradle.kts wrap theme={null}
dependencies {
implementation("com.moengage:cards-core")
}
```
Once the BOM is configured, include the specific MoEngage modules required for the application. \
Note: Version numbers are not required for these dependencies; the BOM automatically manages them.
### **SDK Dependency on Glide for Image and GIF Loading**
SDK uses [Glide](https://bumptech.github.io/glide/) for loading images and gifs. Ensure you add Glide to your application in case you don't have it already. SDK is compiled using library version **4.9.0.** We recommend you use the same version or higher in your application.
# Adding the UI Component
You can integrate the card UI into your application either by inflating the activity provided by the SDK or attaching the Fragment provided by the SDK to an existing Activity in the application.
## Integrating using Activity
The SDK manifest has declared the [*CardActivity*](https://moengage.github.io/android-api-reference/cards-ui/com.moengage.cards.ui/-card-activity/index.html) in the manifest file, and nothing additional is required until and unless you want to customize the theme of the Activity or any other launch property.\
The default declaration is as below.
```xml AndroidManifest.xml wrap theme={null}
```
For more information about how to customize, refer to Customisation.
## Integrating using Fragment
To integrate the Card UI as a fragment, you can inflate the [*CardFragment*](https://moengage.github.io/android-api-reference/cards-ui/com.moengage.cards.ui/-card-fragment/index.html) from the appropriate place inside your application.
# UI Customizations
SDK provides a certain set of UI customizations.
## Activity Customization
If you are integrating the activity provided by the SDK, you can customize the label, theme, etc.\
To customize the theme label you can either re-declare the activity in your app's manifest and provide the desired theme or label.\
Alternatively, you can override the SDK defaults as described below.
### Activity Label
The default label for the activity is **Inbox**. In case you want to change the label add the **moe\_card\_feed\_title** string in your **strings.xml** file with the label name.
```markdown strings.xml wrap theme={null}
[YOUR_LABEL_NAME]
```
### Activity Theme
The default theme applied to the Activity is **MoECardTheme.NoActionBar**.\
The following is the theme definition.
```xml colors.xml wrap theme={null}
```
```xml colors.xml wrap theme={null}
{/* Theme customisation */}
#1C64D0@color/moe_black@color/moe_white@color/moe_black
```
To customize the theme override any of the color attributes.\
To override, define the attribute with the same name in the **colors.xml** file of the application and specify the desired color.\
For example, if you want to customize the accent color define **moe\_card\_color\_accent** in your application **color.xml** as described and replace **\[YOUR\_COLOR]** with the desired color.
```xml colors.xml wrap theme={null}
[YOUR_COLOR]
```
### Activity Toolbar
The **CardActvity** has a toolbar in the layout with the below style. In case you want to customize any of the properties, override the below style completely, or you can override the individual items are well.
```xml styles.xml wrap theme={null}
```
The background color of the toolbar is set to the primary color of the theme.
## Tab Customisation
The Card UI is built with a tab layout, following is the list of customization options provided by the SDK.
* Text Appearance
* Font
* Text Size
* Tab Text-color selected/unselected
* Tab background-color selected/unselected
To customize the properties, you can override the styles or color attributes defined by the SDK in your application **colors.xml** or **styles.xml** file.
```xml style.xml wrap theme={null}
```
```xml colors.xml wrap theme={null}
#1C64D0#8E8E8E@color/moe_white@color/moe_white
```
## Text Customization
Each card has three text fields and a button
* Header
* Message
* Call to Action Button(CTA)
* Timestamp
The default style for each of these components can be overridden by overriding the below styles completely or overriding the individual items.\
Certain styling components like color and text formatting (like bold, italic, etc.) for these fields are customizable from the MoEngage Dashboard, while others, like font and text size fixed on the SDK side. Values for these can be overridden and will be applied to all cards.
The color defined in these styles are default colors and will be overridden by the colors selected during campaign creation.
```xml styles.xml wrap theme={null}
{/* Header style */}
{/* Message style */}
{/* Button style */}
{/* Timestamp Style */}
```
```xml colors.xml wrap theme={null}
{/* Text Color */}
#424242#616161#9E9E9E
```
### Timestamp format Customization
The default format for the timestamp shown on each card is **MMM dd, hh:mm a** this can be customized by passing the custom format to [*configureCards()*](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]-mo-engage/-builder/configure-cards.html) of the [*MoEngage.Builder*](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]-mo-engage/-builder/index.html)object while initializing the SDK.
## Card Customization
You can customize the following properties for a given card
* Un-clicked Indicator Color
* Card Background Color (overridden by the color selected during the campaign creation)
Override the below color resources in the **colors.xml** to use the desired color.
```xml colors.xml wrap theme={null}
#5956D6@color/moe_white
```
## Empty State
If the inbox does not contain any cards, SDK shows an empty screen with an image and message, as shown below.
The image and message can be customized if required.
#### Image Customization
To customize the image, pass in the resource id of the image in the [*configureCards()*](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]-mo-engage/-builder/configure-cards.html) API [MoEngage.Builder](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]-mo-engage/-builder/index.html) object while initializing the SDK.
#### Message Customisation
To customize the message, override the **moe\_card\_no\_message\_available** in your applications **strings.xml** file.
```xml strings.xml wrap theme={null}
[YOUR_STRING_GOES_HERE]
```
## Customize Delete Text
To customize the message of the delete button, override the below string resource in the **strings.xml** of your application.
```xml xml wrap theme={null}
[YOUR_STRING_GOES_HERE]
```
## Disable Pull to Refresh
By default, the Card Activity/Fragment has the pull to refresh feature enabled, you can disable pull to refresh using the [*configureCards()*](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]-mo-engage/-builder/configure-cards.html)API in the [*MoEngage.Builder*](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]-mo-engage/-builder/index.html)*.*
# APIs
## Unclicked Count
The SDK provides an API to fetch the number of cards which hasn't been clicked by the users. To get the count, you can use the below APIs.
```Kotlin Kotlin wrap theme={null}
// Call this API on worker thread as it reads from a file.
MoECardHelper.getUnClickedCardCount(context)
// This API returns the count asynchronously in the listener passed as a parameter.
MoECardHelper.getUnClickedCardCountAsync(context, listener)
```
```Java Java theme={null}
// Call this API on worker thread as it reads from a file.
MoECardHelper.INSTANCE.getUnClickedCardCount(context);
// This API returns the count asynchronously in the listener passed as a parameter.
MoECardHelper.INSTANCE.getUnClickedCardCountAsync(context, listener);
```
Refer to the documentation of [*MoECardHelper.getUnClickedCardCount()*](https://moengage.github.io/android-api-reference/cards-core/com.moengage.cards.core/-mo-e-card-helper/get-un-clicked-card-count.html) and [*MoECardHelper.getUnClickedCardCountAsync()*](https://moengage.github.io/android-api-reference/cards-core/com.moengage.cards.core/-mo-e-card-helper/get-un-clicked-card-count-async.html) for more information.
## New Card Count
The SDK provides an API to get the new cards for the user on the device. To get the count, use the below API.
```Kotlin Kotlin wrap theme={null}
// Call this API on worker thread as it reads from a file.
MoECardHelper.getNewCardCount(context)
// This API returns the count asynchronously in the listener passed as a parameter.
MoECardHelper.getNewCardCountAsync(context, listener)
```
```Java Java theme={null}
// Call this API on worker thread as it reads from a file.
MoECardHelper.INSTANCE.getNewCardCount(context);
// This API returns the count asynchronously in the listener passed as a parameter.
MoECardHelper.INSTANCE.getNewCardCountAsync(context, listener);
```
Refer to the documentation of [*MoECardHelper.getNewCardCount()*](https://moengage.github.io/android-api-reference/cards-core/com.moengage.cards.core/-mo-e-card-helper/get-new-card-count-async.html)and [*MoECardHelper.getNewCardCountAsync()*](https://moengage.github.io/android-api-reference/cards-core/com.moengage.cards.core/-mo-e-card-helper/get-new-card-count-async.html) for more information.
# Callbacks
The SDK provides callbacks when
* Cards are successfully synced on application launch/foreground
* The card is clicked by the user
## Sync Callback
To get a callback for sync completion on application launch/foreground implement the [*SyncCompleteListener*](https://moengage.github.io/android-api-reference/cards-core/com.moengage.cards.core.listener/-sync-complete-listener/index.html) interface and register for the callback using [*MoECardHelper.setSyncCompleteListener()*](https://moengage.github.io/android-api-reference/cards-core/com.moengage.cards.core/-mo-e-card-helper/set-sync-complete-listener.html)*.*
## Click Callback
To get a callback on the card, click implement the [*OnCardClickListener*](https://moengage.github.io/android-api-reference/cards-ui/com.moengage.cards.ui.listener/-on-card-click-listener/index.html) interface and register for the callback using the [*MoECardUiHelper.setClickListener().*](https://moengage.github.io/android-api-reference/cards-ui/com.moengage.cards.ui/-mo-e-card-ui-helper/set-click-listener.html)
# Self Handled Cards
Source: https://moengage.com/docs/developer-guide/android-sdk/cards/self-handled-cards
Build custom card views in your Android app using the MoEngage self-handled Cards SDK.
Self-handled cards give you the flexibility of creating Card Campaigns on the MoEngage Platform and displaying the cards anywhere inside the application. SDK provides APIs to fetch the campaign's data using which you can create your own view for cards.
# SDK Installation
## Installing using BOM
Integration using BOM is the recommended way of integration; refer to the [Install Using BOM](/developer-guide/android-sdk/sdk-integration/basic-integration/Install-Using-BOM) document. Once you have configured the BOM add the dependency in the *app/build.gradle* file as shown below
```kotlin build.gradle.kts wrap theme={null}
dependencies {
...
implementation("com.moengage:cards-core")
}
```
Once the BOM is configured, include the specific MoEngage modules required for the application. \
Note: Version numbers are not required for these dependencies; the BOM automatically manages them.
# Implementing Self Handled Cards
Use the below APIs to fetch the card's data and build your own UI. The SDK provides both blocking and async APIs for fetching the data. In this document, we have just added the blocking APIs, refer to the API reference for [*MoECardHelper*](https://moengage.github.io/android-api-reference/cards-core/com.moengage.cards.core/-mo-e-card-helper/index.html) for the async APIs.
## Notify on Section Load/Unload
You can show the cards on a separate screen or a section of the screen. When the cards screen/section is loaded call [*onCardSectionLoaded()*](https://moengage.github.io/android-api-reference/cards-core/com.moengage.cards.core/-mo-e-card-helper/on-card-section-loaded.html) and call [*onCardSectionUnloaded()*](https://moengage.github.io/android-api-reference/cards-core/com.moengage.cards.core/-mo-e-card-helper/on-card-section-unloaded.html) when the screen/section is no longer visible or going to background.
```Kotlin Kotlin wrap theme={null}
// call on section or screen load
MoECardHelper.onCardSectionLoaded(context,listener);
// call when the section is no longer visible or going to background.
MoECardHelper.onCardSectionUnloaded(context);
```
```Java Java theme={null}
// call on section or screen load
MoECardHelper.INSTANCE.onCardSectionLoaded(context,listener);
// call when the section is no longer visible or going to background.
MoECardHelper.INSTANCE.onCardSectionUnloaded(context);
```
## Fetch Categories
To fetch all the categories for which cards are configured, use the [*getCardCategories()*](https://moengage.github.io/android-api-reference/cards-core/com.moengage.cards.core/-mo-e-card-helper/get-card-categories.html) API.
```Kotlin Kotlin wrap theme={null}
MoECardHelper.getCardCategories(context)
```
```Java Java theme={null}
MoECardHelper.INSTANCE.getCardCategories(context);
```
Additionally, you can optionally have an **All** category which would be like a superset of other categories. Use the [*isAllCategoryEnabled()*](https://moengage.github.io/android-api-reference/cards-core/com.moengage.cards.core/-mo-e-card-helper/is-all-category-enabled.html) API.
```Kotlin Kotlin wrap theme={null}
MoECardHelper.isAllCategoryEnabled(context)
```
```Java Java theme={null}
MoECardHelper.INSTANCE.isAllCategoryEnabled(context);
```
## Fetch Cards for Categories
To fetch cards eligible for display for a specific category, use the [*getCardsForCategory()*](https://moengage.github.io/android-api-reference/cards-core/com.moengage.cards.core/-mo-e-card-helper/get-cards-for-category.html) API
```Kotlin Kotlin wrap theme={null}
MoECardHelper.getCardsForCategory(context, "[YOUR_CATEGORY]")
```
```Java Java theme={null}
MoECardHelper.INSTANCE.getCardsForCategory(context, "[YOUR_CATEGORY]");
```
To fetch all the cards eligible for display irrespective of the category, pass the category **CARD\_CATEGORY\_ALL** as shown below
```Kotlin Kotlin wrap theme={null}
MoECardHelper.getCardsForCategory(context, CARDS_CATEGORY_ALL)
```
```Java Java theme={null}
MoECardHelper.INSTANCE.getCardsForCategory(context, MoECardsCoreConstants.CARDS_CATEGORY_ALL);
```
Refer to the documentation of the [*Card*](https://moengage.github.io/android-api-reference/cards-core/com.moengage.cards.core.model/-card/index.html) model to know more about the fields and data present.
Instead of using separate APIs to fetch the Cards and categories, you can use the [*getCardsInfo()*](https://moengage.github.io/android-api-reference/cards-core/com.moengage.cards.core/-mo-e-card-helper/get-cards-info.html) API to fetch all the information in one go
```Kotlin Kotlin wrap theme={null}
MoECardHelper.getCardsInfo(context)
```
```Java Java theme={null}
MoECardHelper.INSTANCE.getCardsInfo(context);
```
## Widget and Widget Id Mapping
### Basic Card/Illustration Card
| Widget Id | Widget Type | Widget Information |
| --------- | -------------------------- | --------------------------------- |
| 0 | Image (WidgetType.IMAGE) | Image widget in the card. |
| 1 | Text (WidgetType.TEXT) | Header text for the card. |
| 2 | Text (WidgetType.TEXT) | Message text for the card. |
| 3 | Button (WidgetType.Button) | Call to action(CTA) for the card. |
## Track Statistics for Cards
Since the UI/display of the cards is controlled by the application to track statistics on delivery, display, and click, we need the application to notify the SDK.
### Delivered
To track delivery to the card section of the application, call the [*cardDelivered()*](https://moengage.github.io/android-api-reference/cards-core/com.moengage.cards.core/-mo-e-card-helper/card-delivered.html) API when the cards section of the application is loaded.
```Kotlin Kotlin wrap theme={null}
MoECardHelper.cardDelivered(context)
```
```Java Java theme={null}
MoECardHelper.INSTANCE.cardDelivered(context);
```
### Impression
Call the [*cardShown()*](https://moengage.github.io/android-api-reference/cards-core/com.moengage.cards.core/-mo-e-card-helper/card-shown.html) API when a specific card is visible on the screen.
```Kotlin Kotlin wrap theme={null}
MoECardHelper.cardShown(context, card)
```
```Java Java theme={null}
MoECardHelper.INSTANCE.cardShown(context, card);
```
### Click
Call the [*cardClicked()*](https://moengage.github.io/android-api-reference/cards-core/com.moengage.cards.core/-mo-e-card-helper/card-clicked.html) API whenever a user clicks on a card, along with the card object widget identifier for the UI element clicked should also be passed.
```Kotlin Kotlin wrap theme={null}
MoECardHelper.cardClicked(context, card, widgetId)
```
```Java Java theme={null}
MoECardHelper.INSTANCE.cardClicked(context, card, widgetId);
```
## Delete Card
Call the [*deleteCard()*](https://moengage.github.io/android-api-reference/cards-core/com.moengage.cards.core/-mo-e-card-helper/delete-card.html) API to delete a card
```Kotlin Kotlin wrap theme={null}
MoECardHelper.deleteCard(context, card)
```
```Java Java theme={null}
MoECardHelper.INSTANCE.deleteCard(context, card);
```
To delete a list of cards, use [*deleteCards()*](https://moengage.github.io/android-api-reference/cards-core/com.moengage.cards.core/-mo-e-card-helper/delete-cards.html) API.
## Refresh Cards from the Server
Use the [*fetchCards()*](https://moengage.github.io/android-api-reference/cards-core/com.moengage.cards.core/-mo-e-card-helper/fetch-cards.html) API to refresh cards from the MoEngage server if required.
```Kotlin Kotlin wrap theme={null}
MoECardHelper.fetchCards(Context, CardAvailableListener)
```
```Java Java theme={null}
MoECardHelper.INSTANCE.fetchCards(Context, CardAvailableListener);
```
* The SDK automatically refreshes/fetches cards from the MoEngage server whenever the application comes to the foreground.
* This API has a FUP if breached the existing cards i.e. the ones in the local storage of the device will be passed on in the callback.
Please take a look at the [documentation](https://moengage.github.io/android-api-reference/cards-core/com.moengage.cards.core/-mo-e-card-helper/index.html) for a complete guide on available helper APIs.
# Release checklist
Source: https://moengage.com/docs/developer-guide/android-sdk/checklist/release-checklist
Verify your MoEngage Android SDK integration against this checklist before releasing your app.
Before releasing your application with MoEngage SDK integrated verify if the following items have been implemented.
# General
* SDK is initialized in *onCreate()* of the Application class on the Main Thread.
* Disable logging for release build if enabled.
* Enable Java 8 target and source compatibility.
# Data Tracking
* Install/Update Differentiation
* Exhaustive Events and Attributes are tracked based on use-cases.
* User attributes tracked for both new and existing users
* Track the unique identifier for the user on login using *setUniqueId()*
* The logout method is called when the user is logged out of the application
# Push Notification
## FCM
* Firebase messaging dependency added and related Firebase plugins added.
* Small icon and large icon set along with other optional metadata
* In case you are using vector drawables, .webp or any file format other than .png images for notification icons, please make sure you have tested on all OS versions supported by your app.
* Check Firebase receiver in the **AndoidManifest.xml** file. Make sure only 1 receiver is added in the manifest file.
* Test Push on a physical device
* Token Registration and Payload handled by App
* Disable token registration of MoEngage SDK
* Token passed to the SDK for a fresh install, app update, and whenever FCM refreshes the token.
* Push Payload passed on to the SDK
* Token Registration and Payload handled by SDK
* SDK's FCM receiver added in the manifest
* Token change listener registered if required.
## Push Amp Plus
### Mi
* Check version compatibility of Mi push dependency with **moe-android-sdk**
* Configured App Key and App-id during SDK initialization
* Test on Mi Device
* Token Registration and Payload handled by App
* Disable token registration of MoEngage SDK
* Token passed to the SDK for a fresh install, app update, and whenever Mi refreshes the token.
* Push Payload passed on to the SDK
* Token Registration and Payload handled by SDK
* SDK's Mi receiver is added in the manifest.
* Token change listener registered if required.
### Push Kit
* Push Kit dependency added and related HMS plugins configured.
* Check version compatibility of PushKit dependency with **moe-android-sdk**
* Test on Huawei Device
## Push Templates
* Check version compatibility of the Push Templates dependency with **moe-android-sdk**
* Test a template campaign on the device.
# In-App
* Check version compatibility of the Push Templates dependency with **moe-android-sdk**
* Call *showInApp()* on all Activity or Fragment where you want to show In-Apps
* NudgeView is embedded in the required Activity or Fragment.
* Test In-App Campaigns on a device.
# Inbox
* Check version compatibility of Inbox dependency with **moe-android-sdk**
* Check if campaigns are visible in the applications inbox.
# Cards
* Check version compatibility of the Cards dependency with **moe-android-sdk**
* Check if card campaigns are visible on the device.
# Geofence
* Check version compatibility of the Geofence dependency with **moe-android-sdk**
* Application has added Google’s Location Services as a dependency in the application.
* Application requests appropriate permissions based on the OS version.
# Compliance
Source: https://moengage.com/docs/developer-guide/android-sdk/compliance/compliance
Enable or disable data tracking and manage user consent in the MoEngage Android SDK.
# Enable/Disable Data Tracking
If you don't want the MoEngage SDK not to track user data to the MoEngage System use the [disableDataTracking()](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]disable-data-tracking.html) API.
```kotlin Kotlin wrap theme={null}
import com.moengage.core.disableDataTracking
disableDataTracking(context)
```
```java Java theme={null}
MoESdkStateHelper.disableDataTracking(context);
```
Once the above API is called, no custom events or user attributes will be tracked. SDK will reject all events until [enableDataTracking()](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]enable-data-tracking.html) is called.\
Once you want to track events or user attributes, call the below API.
```kotlin Kotlin wrap theme={null}
import com.moengage.core.enableDataTracking
enableDataTracking(context)
```
```java Java theme={null}
MoESdkStateHelper.enableDataTracking(context);
```
# Enable/Disable SDK
If you don't want the MoEngage SDK not to track any user information or send any data to the MoEngage System, use the [disableSdk()](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]disable-sdk.html) API.
```kotlin Kotlin wrap theme={null}
import com.moengage.core.disableSdk
disableSdk(context)
```
```java Java theme={null}
MoESdkStateHelper.disableSdk(context);
```
Once this API is called, all the SDK APIs will be non-operational. SDK will be disabled until [enableSdk()](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]enable-sdk.html) is called.\
Once you have the user's consent use the below API to enable the SDK.
```kotlin Kotlin wrap theme={null}
import com.moengage.core.enableSdk
enableSdk(context)
```
```java Java theme={null}
MoESdkStateHelper.enableSdk(context);
```
# Delete User Data
In April 2023, Google Announced the [User Account Deletion Policy](https://android-developers.googleblog.com/2023/04/giving-people-more-control-over-their-data.html), according to which if your app allows you to create an account within your app, it must also allow the user to delete their account within the app.
Calling this API will delete the User Data/Profile from the MoEngage Server. You need to have a minimum SDK version of **12.10.00** or **above**to call this API.
```kotlin Kotlin wrap theme={null}
import com.moengage.core.MoECoreHelper
MoECoreHelper.deleteUser(context,listener)
```
```kotlin Java theme={null}
import com.moengage.core.MoECoreHelper;
MoECoreHelper.INSTANCE.deleteUser(context,listener);
```
For more information, refer to the [API Documentation.](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]-mo-e-core-helper/delete-user.html)
# Prepare for Google Play's data disclosure requirements
Source: https://moengage.com/docs/developer-guide/android-sdk/compliance/prepare-for-google-plays-data-disclosure-requirements
Review MoEngage Android SDK data collection details to complete Google Play's Data Safety disclosure.
In May 2021, Google Play [announced the new Data safety section](https://android-developers.googleblog.com/2021/05/new-safety-section-in-google-play-will.html), which is a developer-provided disclosure for an app's data collection, sharing, and security practices.
This page can help you complete the requirements for this data disclosure in regards to your usage of the MoEngage Android SDK. On this page, you can find information on whether and how our SDK handles end-user data, including any applicable settings or configurations you can control as the application developer.
We aim to be as transparent as possible in supporting you; however, as the application developer, you are solely responsible for deciding how to respond to Google Play's Data safety section form regarding your app's end-user data collection, sharing, and security practices.
# How to use the information on this page?
This page lists the end-user data collected only from *version **12.2.01*** of the MoEngage Android SDK.
If you are using a prior version of the MoEngage Android SDK, could you update to the latest version to ensure your app's disclosures are accurate? The MoEngage Android SDK will continue to be updated over time. This article will reflect these changes, so update your disclosures as necessary.
# Data collected
## Mandatory Data Collected
SDK collects the following data automatically for analytics.
| Data | By default, MoEngage SDK ... |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| IP Address | Collects the device's IP address, which may be used to estimate the general location of a device. |
| User product interactions | Collects user-product interactions and interaction information, including app launch, and application foreground-background. |
| Device Metadata | Collects device information like Device Model, OS version, Timezone, network type(if permission is granted by the user), |
## Optional Data Collected
SDK optionally collects the below data based on whether the application/user has given consent for tracking the data.
| Data | MoEngage SDK... |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| Device Metadata | Collects device information like Product Name, Manufacturer, Device Dimensions, Display type, and Carrier(if permission is granted by the user). |
| Device Identifiers | Collects device identifiers like Advertising Identifier, and Android Id. |
# Configuring Opt-outs
Source: https://moengage.com/docs/developer-guide/android-sdk/data-tracking/advanced-or-optional/configuring-opt-outs
Configure tracking opt-outs for device identifiers like GAID and Android ID in the MoEngage Android SDK.
By default, SDK tracks certain device identifiers like GAID, Android-id, activity names, etc. If required you can choose to opt-out of this tracking by using the TrackingOptOutConfig.\
Refer to the API reference of [TrackingOptOutConfig](https://moengage.github.io/android-api-reference/core/com.moengage.core.config/\[android-jvm]-tracking-opt-out-config/index.html) for more details on the available opt-outs. Use the [configureTrackingOptOut()](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]-mo-engage/-builder/configure-tracking-opt-out.html) to pass on the configuration to the SDK.
```Kotlin Kotlin wrap theme={null}
val trackingOptOut = mutableSetOf>()
trackingOptOut.add(YourActivityName::class.java)
val trackingOptOutConfig = TrackingOptOutConfig(
isCarrierTrackingEnabled = true,
isDeviceAttributeTrackingEnabled = true,
trackingOptOut
)
val moengage = MoEngage.Builder(application, appId)
.configureTrackingOptOut(trackingOptOutConfig)
.build()
MoEngage.initialise(moengage)
```
```Java Java theme={null}
Set> trackingOptOut = new HashSet<>();
trackingOptOut.add(YourActivityName.class);
MoEngage moEngage = new Builder(application, ConstantsKt.APP_ID)
.configureFcm(new FcmConfig(true))
.configureTrackingOptOut(new TrackingOptOutConfig(true, true, trackingOptOut))
.build();
MoEngage.initialise(moEngage);
```
# Device Identifier Tracking
Source: https://moengage.com/docs/developer-guide/android-sdk/data-tracking/advanced-or-optional/device-identifier-tracking
Enable or disable Android ID and advertising identifier tracking in the MoEngage Android SDK.
## Android Id Tracking
From SDK version **11.5.00**, SDK optionally tracks Android-id for the devices(by default Android-id is not tracked). To enable Android-id tracking use the [enableAndroidIdTracking()](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]enable-android-id-tracking.html) method as shown below.
```Kotlin Kotlin wrap theme={null}
import com.moengage.core.enableAndroidIdTracking
enableAndroidIdTracking(context)
```
```Java Java theme={null}
MoESdkStateHelper.enableAndroidIdTracking(context);
```
Before enabling the Android-id tracking application should take consent from the user as per the [Google Policy](https://support.google.com/googleplay/android-developer/answer/10144311).Once tracking is enabled SDK would continue tracking the Android-id until explicitly opted-out. Use the [disableAndroidIdTracking()](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]disable-android-id-tracking.html) method to opt-out of Android-id tracking.
```Kotlin Kotlin wrap theme={null}
import com.moengage.core.disableAndroidIdTracking
disableAndroidIdTracking(context)
```
```Java Java theme={null}
MoESdkStateHelper.disableAndroidIdTracking(context);
```
For the SDK version below **11.5.00** use the *TrackingOptoutConfig* while initializing the MoEngage SDK.
## Advertising Identifier Tracking
From SDK version **12.1.00**, SDK optionally tracks Advertising Identifier for the devices(by default Advertising Identifier is not tracked). To enable Advertising Identifier tracking use the [enableAdIdTracking()](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]enable-ad-id-tracking.html) method as shown below.
```Kotlin Kotlin wrap theme={null}
import com.moengage.core.enableAdIdTracking
enableAdIdTracking(context)
```
```Java Java theme={null}
MoESdkStateHelper.enableAdIdTracking(context);
```
Before enabling the Advertising Identifier tracking application should take consent from the user as per the [Google Policy](https://support.google.com/googleplay/android-developer/answer/10144311).
Once tracking is enabled SDK would continue tracking the Advertising Identifier until explicitly opted-out. Use the [disableAdIdTracking()](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]disable-ad-id-tracking.html) method to opt-out of Advertising Identifier tracking.
```Kotlin Kotlin wrap theme={null}
import com.moengage.core.disableAdIdTracking
disableAdIdTracking(context)
```
```Java Java theme={null}
MoESdkStateHelper.disableAdIdTracking(context);
```
For the SDK version below **12.1.00** use the *TrackingOptoutConfig* while initializing the MoEngage SDK.
# Offerings Events Tracking
Source: https://moengage.com/docs/developer-guide/android-sdk/data-tracking/advanced-or-optional/offerings-events-tracking
Track impression and click events for MoEngage Offerings fetched via the Personalize API on Android.
This document outlines the new methods available in the MoEngage Android SDK to report impressions and clicks for Offerings fetched using the [MoEngage Personalize API](https://www.moengage.com/docs/api/experiences/fetch-experience).
# Prerequisites
## SDK version
> You must update your Native Android SDK catalog version to **5.3.1** or higher.
## MoEngage Account Configuration
Ensure your MoEngage workspace is enabled to utilize Offerings. Refer to [this article](https://help.moengage.com/hc/en-us/articles/38661119123732-Offerings) for details on setting up Offerings.
# Reporting Offering Shown events
The SDK provides a helper API to track shown events; please refer to the [API documentation](https://moengage.github.io/android-api-reference/campaigns-core/com.moengage.campaigns.personalize/-mo-e-personalize-helper/offering-shown.html) for more details.
Impressions should be reported when an Offering is visually presented to the user.
To report an impression offering, pass the **offeringContext** as a map.
```Kotlin Kotlin wrap theme={null}
MoEPersonalizeHelper.offeringShown(context, offeringContextMap)
```
```Java Java wrap theme={null}
MoEPersonalizeHelper.INSTANCE.offeringShown(context, offeringContextMap);
```
# Reporting Offering Clicked events
The SDK provides a helper API to track clicked events; refer to the [API documentation](https://moengage.github.io/android-api-reference/campaigns-core/com.moengage.campaigns.personalize/-mo-e-personalize-helper/offering-clicked.html) for more details.
Clicked events should be reported when a user clicks on any offering contained in the response of the Personalize API. To report a click event for a single offering, pass the **offeringContext** of the offering as a map.
When a user clicks on an Offering, we understand that they are also implicitly clicking on the parent Experience. You can now optionally pass the experienceContext to the**offeringClicked**function.
### **What this means**
* **If you pass both contexts,** MoEngage will **automatically** track clicks for **both** the Offering and the Experience. You no longer need to make a second, separate call to track the click event for the parent experience.
* **If you only pass the offeringContext,** the **experienceContext** is optional. If you don't pass it, we will only track the click for the Offering. You would then need to track the experience click separately, if required.
```Kotlin Kotlin wrap theme={null}
MoEPersonalizeHelper.offeringClicked(context, offeringContextMap, experienceContextMap)
```
```Java Java wrap theme={null}
MoEPersonalizeHelper.INSTANCE.offeringClicked(context, offeringContextMap, experienceContextMap);
```
# Personalize Experience Events Tracking
Source: https://moengage.com/docs/developer-guide/android-sdk/data-tracking/advanced-or-optional/personalize-experience-events-tracking
Track impression and click events for personalized experiences from the MoEngage Personalize API on Android.
This document outlines the new methods available in the MoEngage Android SDK to report impressions and clicks for experiences fetched using the [MoEngage Personalize API](https://www.moengage.com/docs/api/experiences/fetch-experience).
# Prerequisites
## SDK version
> You must update your Native Android SDK catalog version to **5.2.0** or higher.
## MoEngage Account Configuration
Ensure your MoEngage workspace is enabled to utilize the Personalize API. Refer to [this article](https://help.moengage.com/hc/en-us/articles/24644175705236-Create-Server-side-Personalization-Experience) for details on setting up Personalize API experiences.
# Reporting Experience Shown events
The SDK provides helper APIs to track shown events; please refer to the [API documentation](https://moengage.github.io/android-api-reference/campaigns-core/com.moengage.campaigns.personalize/-mo-e-personalize-helper/index.html) for more details.
Impressions should be reported when an experience is visually presented to the user.
## Single Experience
To report an impression for a single experience, pass the **experience\_context** of the experience as a map.
**experience\_context** is a JSON object that is returned as part of the [response of the Personalize API request](https://www.moengage.com/docs/api/experiences/fetch-experience).
```Kotlin Kotlin wrap theme={null}
MoEPersonalizeHelper.experienceShown(context, experienceContextMap)
```
```Java Java wrap theme={null}
MoEPersonalizeHelper.INSTANCE.experienceShown(context, experienceContextMap);
```
## Mulitple Experiences
To track the experience shown event for multiple experiences, pass the **list** of **experience\_context** of each experience as a map.
```Kotlin Kotlin wrap theme={null}
MoEPersonalizeHelper.experienceShown(context, experienceContextMapList)
```
```Java Java wrap theme={null}
MoEPersonalizeHelper.INSTANCE.experienceShown(context, experienceContextMapList);
```
# Reporting Experience Clicked events
The SDK provides helper APIs to track clicked events; refer to the [API documentation](https://moengage.github.io/android-api-reference/campaigns-core/com.moengage.campaigns.personalize/-mo-e-personalize-helper/index.html) for more details.
Clicked events should be reported when a user clicks on any element that has been personalized using the response of the Personalize API.
## Single Experience
To report a click event for a single experience, pass the **experience\_context** of the experience as a map.
```Kotlin Kotlin wrap theme={null}
MoEPersonalizeHelper.experienceClicked(context, experienceContextMap)
```
```Java Java wrap theme={null}
MoEPersonalizeHelper.INSTANCE.experienceClicked(context, experienceContextMap);
```
## Mulitple Experiences
To track the experience shown event for multiple experiences, pass the **list** of **experience\_context** of each experience as a map.
```Kotlin Kotlin wrap theme={null}
MoEPersonalizeHelper.experienceClicked(context, experienceContextMapList)
```
```Java Java wrap theme={null}
MoEPersonalizeHelper.INSTANCE.experienceClicked(context, experienceContextMapList);
```
You can optionally include a **b\_id** key in the **experience\_context** object to provide additional context about the click. Its value should describe the specific component or interaction within the experience that was clicked. This is particularly useful for experiences composed of multiple interactive elements, helping to distinguish between clicks on different parts of the same overall experience.
# Tracking Locale
Source: https://moengage.com/docs/developer-guide/android-sdk/data-tracking/advanced-or-optional/tracking-locale
Optionally track the device locale in your Android app using the MoEngage SDK.
**Optional**
This is optional and only required if you wish to track the locale.
SDK by default does not track locales. To track the Locale set for the given JVM instance call [MoEAnalyticsHelper.trackDeviceLocale()](https://moengage.github.io/android-api-reference/core/com.moengage.core.analytics/\[android-jvm]-mo-e-analytics-helper/track-device-locale.html).
```Kotlin Kotlin wrap theme={null}
MoEAnalyticsHelper.trackDeviceLocale(context)
```
```Java Java wrap theme={null}
MoEAnalyticsHelper.INSTANCE.trackDeviceLocale(context);
```
# Enable Advertising Identifier Tracking
Source: https://moengage.com/docs/developer-guide/android-sdk/data-tracking/basic/enable-advertising-identifier-tracking
Enable advertising identifier tracking in the MoEngage Android SDK for accurate device analytics.
For accurate analytics around devices and tracking Re-installs, it is essential to track the Advertising Identifier. For more information, refer to [Android Advertising ID Tracking](https://help.moengage.com/hc/en-us/articles/7457641031828-Android-Advertising-ID-Tracking).
## Add Ad Identifier Library
Add the below dependency in the application-level ***build.gradle*** file.
```groovy Groovy wrap theme={null}
implementation("com.google.android.gms:play-services-ads-identifier:18.0.1")
```
To enable Advertising Identifier tracking use the [enableAdIdTracking()](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]enable-ad-id-tracking.html) method as shown below.
```Kotlin Kotlin wrap theme={null}
import com.moengage.core.enableAdIdTracking
enableAdIdTracking(context)
```
```Java Java wrap theme={null}
MoESdkStateHelper.enableAdIdTracking(context);
```
Please ensure the application is complying with the [Google Play Policy](https://support.google.com/googleplay/android-developer/answer/10144311) regarding Advertising Id tracking.
# Setting Unique Id for SDK versions below 13.6.00
Source: https://moengage.com/docs/developer-guide/android-sdk/data-tracking/basic/setting-unique-id-for-sdk-versions-below-13-6-00
Set a unique user ID for login and logout in MoEngage Android SDK versions below 13.6.00.
# Implementing Login/Logout
* It's important to set the User Attribute Unique ID when a user logs into your app.
* This merges the new user with the existing user, if any exists, and will help prevent the creation of unnecessary/stale users.
* Setting the Unique ID is a critical piece to tie a user across devices and installs/uninstalls as well across all platforms (i.e. iOS, Android, Windows, The Web). Set the **USER\_ATTRIBUTE\_UNIQUE\_ID** attribute as soon as the user is **logged in**. Unique ID can be something like an email ID, a username (unique), or a database ID or any Backend generated ID.
* Do not set this for the user who not logged in.
## Login
```kotlin Kotlin wrap theme={null}
MoEAnalyticsHelper.setUniqueId(context, UNIQUE_ID)
```
```java Java theme={null}
MoEAnalyticsHelper.INSTANCE.setUniqueId(context, UNIQUE_ID);
```
**Note:** The following values are not allowed in the UniqueID field: "unknown", "guest", "null", "0", "1", "true", "false", "user\_attribute\_unique\_id", "(empty)", "na", "n/a", "", "dummy\_seller\_code", "user\_id", "id", "customer\_id", "uid", "userid", "none", "-2", "-1", "2"
**UNIQUE ID chaos**
* When you go live with MoEngage Android SDK for the first time, please ensure that you are setting the Unique ID of the already logged-in user along with other user attributes.
* Kindly make sure that you are not using a single UNIQUE ID for all the users, this can happen if you hardcode the value, instead of fetching it from your servers.
* If you pass 2 different UNIQUE ID information without calling the [logoutUser](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]-mo-e-core-helper/logout-user.html) method in between, the SDK will internally force the logout of the existing user.
## Logout
The application needs to notify the MoEngage SDK whenever the user is logged out of the application. To notify the SDK, call the API whenever the user is logged out of the application.
```Kotlin Kotlin wrap theme={null}
MoECoreHelper.logoutUser(context)
```
```Java Java theme={null}
MoECoreHelper.INSTANCE.logoutUser(context);
```
If the application is registering for a push token, it should pass the new push token to MoEngage SDK after the user logs out. For more information about passing push tokens, refer to [Push Configuration for Android SDK](/android-sdk/push/basic/push-configuration).
## Updating User Attribute Unique Id
Use the method *setAlias()* to update the user attribute unique id instead of *setUniqueId()* with a different value. Using the method *setUniqueId()* with a new value creates unintended users in MoEngage.
```Kotlin Kotlin wrap theme={null}
MoEAnalyticsHelper.setAlias(ALIAS)
```
```Java Java theme={null}
MoEAnalyticsHelper.INSTANCE.setAlias(ALIAS);
```
# Track Events
Source: https://moengage.com/docs/developer-guide/android-sdk/data-tracking/basic/track-events
Track custom user events and their attributes in your Android app using the MoEngage SDK.
SDK adheres to the MoEngage FUP policies. For more information, refer to the [Fair Usage Policy](https://help.moengage.com/hc/en-us/articles/24151864954644-Fair-Usage-Policy-FUP#h_01HQSMZVQWT2KYP0PY1P8GQMRM).
Tracking events is how you record any actions your users perform, along with any properties that describe the action. Every trackEvent call records a single user action. We recommend that you make your event names human-readable so that everyone on your team can know what they mean instantly.
You can track an event using trackEvent with the event name and its characteristics (attributes/properties).
Every event has 2 attributes, action name, and key, value pairs which represent additional information about the action. Add all the additional information which you think would be useful for segmentation while creating campaigns. For eg., the following code tracks a purchase event of a product. We are including attributes like amount, quantity, a category that describes the event we are tracking.
```Kotlin Kotlin wrap theme={null}
val properties = Properties()
properties
// tracking integer
.addAttribute("quantity", 2)
// tracking string
.addAttribute("product", "iPhone")
// tracking date
.addAttribute("purchaseDate", Date())
// tracking double
.addAttribute("price", 5999.99)
// tracking location
.addAttribute("userLocation", GeoLocation(40.77, 73.98))
// tracking JSONArray
.addAttribute("jsonArrayAttr", JSONArray(listOf(1, 2, 3)))
// tracking JSONObject
.addAttribute("jsonObjectAttr", JSONObject().put("name", "value"))
MoEAnalyticsHelper.trackEvent(context, "Purchase", properties)
```
```Java Java wrap theme={null}
Properties properties = new Properties();
properties
// tracking integer
.addAttribute("quantity", 2)
// tracking string
.addAttribute("product", "iPhone")
// tracking Date
.addAttribute("purchaseDate", new Date())
// tracking double
.addAttribute("price", 5999.99)
// tracking location
.addAttribute("userLocation", new Geolocation(40.77, 73.98))
// tracking JSONObject
.addAttribute("jsonObjectAttr", new JSONObject())
// tracking JSONArray
.addAttribute("jsonArrayAttr", new JSONArray());
MoEAnalyticsHelper.INSTANCE.trackEvent(context, "Purchase", properties);
```
context - context instance, change the name accordingly.
Ensure that you are tracking event attributes without changing the data types. For example, in the purchase event, amount and quantity are tracked in numeric form. MoEngage detects the data type automatically unless you explicitly specify it as a String. MoEngage supports the following data types: String, Integer, Long, Double, Float, Boolean, Date, GeoLocation, JSON Object, and JSON Array. If any other data type is passed, MoEngage will reject the payload.
The SDK by default tracks a certain set of commonly used events, make sure you use those events instead of tracking similar events again. Refer to the [documentation](https://help.moengage.com/hc/en-us/articles/360043067671-Default-Android-SDK-#Default-Events-Tracked:) to know more about the default events tracked by the SDK.
Having unique timestamps for events is crucial to maintain accurate and reliable data. Please ensure that events do not share the same timestamp down to the millisecond level.
# Analytics
MoEngage SDK version 9.7.01 and later tracks user session and application traffic source.
User session tracking provides the flexibility to selectively mark events as non-interactive.
## Non-interactive event
Events that do not affect the session duration calculation in MoEngage Analytics are marked as Non-Interactive events.
The following are considered non-interactive events:
* Do not start a new session, even when the app is in the foreground
* Do not extend the session
* Do not have information on source and session
An event is marked as non-interactive using the setNonIteractive() in the PayloadBuilder provided by the SDK to build event attributes.
For example,
```Kotlin Kotlin wrap theme={null}
val properties = Properties()
properties.addAttribute("quantity", 2)
.addAttribute("product", "iPhone")
.addAttribute("purchaseDate", Date())
.addAttribute("price", 5999.99)
.addAttribute("currency", "dollar")
.addAttribute("jsonObjectAttr", JSONObject().put("name", "value"))
.addAttribute("jsonArrayAttr", JSONArray(listOf(1, 2, 3)))
.setNonInteractive()
MoEAnalyticsHelper.trackEvent(context, "Purchase", properties)
```
```Java Java wrap theme={null}
Properties properties = new Properties();
properties.addAttribute("quantity", 2)
.addAttribute("product", "iPhone")
.addAttribute("purchaseDate", new Date())
.addAttribute("price", 5999.99)
.addAttribute("currency", "dollar")
.addAttribute("jsonObjectAttr", new JSONObject())
.addAttribute("jsonArrayAttr", new JSONArray())
.setNonInteractive();
MoEAnalyticsHelper.INSTANCE.trackEvent(context, "Purchase", properties);
```
For more information, refer to [MoEAnalyticsHelper#trackEvent](https://moengage.github.io/android-api-reference/core/com.moengage.core.analytics/\[android-jvm]-mo-e-analytics-helper/track-event.html) and [Properties](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]-properties/index.html).
# Track Custom Event for Exit Intent
MoEngage SDK optionally notifies the application whenever the goes to the background. The application can track the custom event in this callback for exit intent. To get notified implement the [AppBackgroundListener](https://moengage.github.io/android-api-reference/core/com.moengage.core.listeners/-app-background-listener/index.html). Register the listener in the *onCreate()* of your Application class using *MoECallbacks.getInstance().addAppBackgroundListener()*.
You can not use "moe\_" as a prefix while naming events, event attributes, or user attributes. It is a system prefix and using it might result in periodic blacklisting without prior communication.
# Track Install or Update
Source: https://moengage.com/docs/developer-guide/android-sdk/data-tracking/basic/track-install-or-update
Differentiate between app installs and updates in the MoEngage Android SDK using the setAppStatus API.
SDK needs support to enable the update by the user application or install the application. You need to have a logic on the app side to distinguish between app *INSTALL* and *UPDATE*
```Kotlin Kotlin wrap theme={null}
//For Fresh Install of App
MoEAnalyticsHelper.setAppStatus(context, AppStatus.INSTALL)
// For Existing user who has updated the app
MoEAnalyticsHelper.setAppStatus(context, AppStatus.UPDATE)
```
```Java Java theme={null}
//For Fresh Install of App
MoEAnalyticsHelper.INSTANCE.setAppStatus(context, AppStatus.INSTALL);
// For Existing user who has updated the app
MoEAnalyticsHelper.INSTANCE.setAppStatus(context, AppStatus.UPDATE);
```
If you uninstall and reinstall your app again, the SDK considers it as a fresh install.
# Track User Attributes
Source: https://moengage.com/docs/developer-guide/android-sdk/data-tracking/basic/track-user-attributes
Track user attributes and set unique identifiers for user identification in the MoEngage Android SDK.
User Attributes are pieces of information you know about a user. They could be demographics like age or gender, account-specific like plan, or whether a user has seen a particular A/B test variation. User attributes are a customer identity you can reference throughout the customer’s lifetime.
# Identifying Users
For SDK versions below 13.6.00 refer to [this document](/android-sdk/data-tracking/basic/setting-unique-id-for-sdk-versions-below-13-6-00).
Setting identifiers is important to:
* To tie user behavior across platforms, i.e., iOS, Android, Web, etc.
* This is to ensure unnecessary or stale users are not created.
* To identify users across installs/re-installs.
## Single Identifier
Call the API below to pass the identifier on to the MoEngage SDK.
```kotlin Kotlin wrap theme={null}
MoEAnalyticsHelper.identifyUser(context, "identifier")
```
```java Java theme={null}
MoEAnalyticsHelper.INSTANCE.identifyUser(context, "identifier");
```
*Note*: This method is a replacement for the deprecated ***setUniqueId()***. If you are using ***setUniqueId()*** in your application, consider replacing it with ***identifyUser()***
## Multiple Identifiers
If your application has multiple identifiers using which you identify a user you can pass all the identifiers to the SDK using the below API
```kotlin Kotlin wrap theme={null}
MoEAnalyticsHelper.identifyUser(
context,
mapOf("identifierName1" to "identifierValue1", "identifierName2" to "identifierValue2")
)
```
```java Java theme={null}
Map identifiers = new HashMap() {{
put("identifierName1", "identifierValue1");
put("identifierName2", "identifierValue2");
}};
MoEAnalyticsHelper.INSTANCE.identifyUser(context, identifiers);
```
**Updates to SDK functions for User Identification and Session Management**
* **Forced Logout:** The MoEngage SDK no longer automatically logs out the previous user when a new user is detected on the device. Logout should now be explicitly called for workspaces enabled with Identity resolution to avoid data corruption.
* **SetUniqueID:** `identifyUser` function supports multiple identifiers, which replaces the need of using `SetUniqueID` function for user identification. Note that `SetUniqueID` is marked for removal in the future releases of SDK versions - it is important to use `identifyUser` instead especially if you are using Identity resolution in your workspace.
* **SetAlias:** For workspaces with the Identity resolution feature enabled, MoEngage SDK stores the previous identifier values. When `identifyUser` function is used to track the new identifier values, MoEngage SDK detects the change in identifier value and reports accordingly.
If you call the `identifyUser` function without logging out, then the existing logged-in user's ID is updated.
If you call `identifyUser()` multiple times with different identifier names, the SDK will append this identifier to the already set identifiers.
Refer to our help [document](https://help.moengage.com/hc/en-us/articles/24050999467284-User-Identity-Management) to learn more about the feature.
## Logout
The application needs to notify the MoEngage SDK whenever the user is logged out of the application. Call the API whenever the user is logged out of the application to notify the SDK.
```kotlin Kotlin wrap theme={null}
MoECoreHelper.logoutUser(context)
```
```java Java theme={null}
MoECoreHelper.INSTANCE.logoutUser(context);
```
If the application is registering for a push token, it should pass the new push token to MoEngage SDK after the user logs out. For more information about passing push tokens, refer to [Push Configuration for Android SDK](/android-sdk/push/basic/push-configuration).
# Tracking User Attributes
The SDK provides APIs to track commonly tracked user attributes like First Name, Last Name, Email-Id, etc. Please use the provided methods for tracking these attributes.
For more information on supported data types and data tracking policies, please refer to [Data Tracking Policies](https://help.moengage.com/hc/en-us/articles/360037314991#h_01H9QNZ61VNHSMFQC28MAZJXS9).
```kotlin Kotlin wrap theme={null}
MoEAnalyticsHelper.setFirstName()
MoEAnalyticsHelper.setLastName()
MoEAnalyticsHelper.setUserName()
MoEAnalyticsHelper.setLocation()
MoEAnalyticsHelper.setGender()
MoEAnalyticsHelper.setMobileNumber()
MoEAnalyticsHelper.setBirthDate()
MoEAnalyticsHelper.setEmailId()
```
```java Java theme={null}
MoEAnalyticsHelper.INSTANCE.setFirstName();
MoEAnalyticsHelper.INSTANCE.setLastName();
MoEAnalyticsHelper.INSTANCE.setUserName();
MoEAnalyticsHelper.INSTANCE.setLocation();
MoEAnalyticsHelper.INSTANCE.setGender();
MoEAnalyticsHelper.INSTANCE.setMobileNumber();
MoEAnalyticsHelper.INSTANCE.setBirthDate();
MoEAnalyticsHelper.INSTANCE.setEmailId();
```
For setting other User Attributes, use the generic method **setUserAttribute(key, value).** Supported types for attribute value are `String`, `int`, `double`, `num`, `bool`, `List`, `List`, `List` & `List`.
```kotlin Kotlin wrap theme={null}
// Tracking a String Attribute
MoEAnalyticsHelper.setUserAttribute(context,"locality", "SF")
// Tracking a Date Attribute
MoEAnalyticsHelper.setUserAttribute(context,"signedUpOn", Date())
// Tracking a location attribute
MoEAnalyticsHelper.setUserAttribute(context,"lastLocation", GeoLocation(40.77, 73.98))
// Tracking Array Attributes
MoEAnalyticsHelper.setUserAttribute(context,"int_array",arrayOf(1,2,3))
MoEAnalyticsHelper.setUserAttribute(context,"string_array",arrayOf("English","French"))
MoEAnalyticsHelper.setUserAttribute(context,"double_array",arrayOf(40.0,20.0))
MoEAnalyticsHelper.setUserAttribute(context,"json_array", JSONArray(listOf(1, 2, 3)))
MoEAnalyticsHelper.setUserAttribute(context,"json_object", JSONObject().put("key", "value"))
```
```java Java theme={null}
// Tracking a String Attribute
MoEAnalyticsHelper.INSTANCE.setUserAttribute(context,"locality", "SF");
// Tracking a Date Attribute
MoEAnalyticsHelper.INSTANCE.setUserAttribute(context, "signedUpOn", new Date());
// Tracking a location attribute
MoEAnalyticsHelper.INSTANCE.setUserAttribute(context,"lastLocation", new GeoLocation(40.77, 73.98));
// Tracking Array Attributes
MoEAnalyticsHelper.INSTANCE.setUserAttribute(context,"int_array",new int[]{1,2,3});
MoEAnalyticsHelper.INSTANCE.setUserAttribute(context,"string_array",new String[]{"English","French"});
MoEAnalyticsHelper.INSTANCE.setUserAttribute(context,"double_array",new double[]{1.5,2.5});
MoEAnalyticsHelper.INSTANCE.setUserAttribute(context,"json_array", new JSONArray());
MoEAnalyticsHelper.INSTANCE.setUserAttribute(context,"json_object", new JSONObject());
```
For more information about the detailed list of user attributes, refer to the [API reference](https://moengage.github.io/android-api-reference/core/com.moengage.core.analytics/\[android-jvm]-mo-e-analytics-helper/index.html).
## Reserved keywords for User Attributes
Below is the list of keys that should not be used when tracking user attributes.
* `USER_ATTRIBUTE_UNIQUE_ID`
* `USER_ATTRIBUTE_USER_EMAIL`
* `USER_ATTRIBUTE_USER_MOBILE`
* `USER_ATTRIBUTE_USER_NAME`
* `USER_ATTRIBUTE_USER_GENDER`
* `USER_ATTRIBUTE_USER_FIRST_NAME`
* `USER_ATTRIBUTE_USER_LAST_NAME`
* `USER_ATTRIBUTE_USER_BDAY`
* `USER_ATTRIBUTE_NOTIFICATION_PREF`
* `USER_ATTRIBUTE_OLD_ID`
* `MOE_TIME_FORMAT`
* `MOE_TIME_TIMEZONE`
* `USER_ATTRIBUTE_DND_START_TIME`
* `USER_ATTRIBUTE_DND_END_TIME`
* `MOE_GAID`
* `INSTALL`
* `UPDATE`
* `MOE_ISLAT`
* `status`
* `user_id`
You cannot use "moe\_" as a prefix while naming events, event attributes, or user attributes. It is a system prefix and using it might result in periodic blacklisting without prior communication.
# In-App NATIV
Source: https://moengage.com/docs/developer-guide/android-sdk/in-app-messages/in-app-nativ
Display contextual in-app messages to your Android app users using the MoEngage In-App NATIV SDK.
In-App NATIV Campaigns target your users by showing a message while the user is using your app. They are very effective in providing contextual information and help to cross-sell/up-sell on desired screens of your app or/and on desired actions performed by the user in your app.
# SDK Installation
## Installing using BOM
Integration using BOM is the recommended way of integration; refer to the [Install Using BOM](/developer-guide/android-sdk/sdk-integration/basic-integration/Install-Using-BOM) document. Once you have configured the BOM add the dependency in the *app/build.gradle* file as shown below
```groovy build.gradle wrap theme={null}
dependencies {
...
implementation("com.moengage:inapp")
}
```
Once the BOM is configured, include the specific MoEngage modules required for the application. \
Note: Version numbers are not required for these dependencies; the BOM automatically manages them.
### **Requirements for displaying images and GIFs in InApp**
Starting InApp version **7.0.0,** SDK requires [Glide](https://bumptech.github.io/glide/) to show images and GIFs in the in-apps. You need to add the below dependency in your **build.gradle** file.
```groovy Groovy wrap theme={null}
dependencies {
...
implementation("com.github.bumptech.glide:glide:4.16.0")
}
```
# Display InApp
MoEngage can not show the InApp by default, and the app should call the following method in the places where necessary to show the InApps to the user. We recommend adding this method in onStart() of your activity or onResume() of your fragment. [MoEInAppHelper.getInstance().showInApp(context)](https://moengage.github.io/android-api-reference/inapp/com.moengage.inapp/-mo-e-in-app-helper/show-in-app.html)
```Kotlin Kotlin wrap theme={null}
MoEInAppHelper.getInstance().showInApp(context)
```
# Display Nudges
Starting with version \*\*7.0.0,\*\*MoEngage InApp SDK supports displaying Non-Intrusive nudges.
MoEngage can not show the Nudges by default, and the app should call the following method in the places where necessary to show the Nudges to the user. We would recommend you add this method in onStart() of your activity or onResume() of your fragment. [MoEInAppHelper.getInstance().showNudge(context)](https://moengage.github.io/android-api-reference/inapp/com.moengage.inapp/-mo-e-in-app-helper/show-nudge.html)
```Kotlin Kotlin wrap theme={null}
MoEInAppHelper.getInstance().showNudge(context)
```
# Handling Configuration change
Starting SDK version **11.4.00,** in-apps are supported in both portrait and landscape modes. SDK internally handles in-app display on orientation change when the activity restart is handled by the system.
In case your activity is handling the configuration change by itself, you have to notify the SDK by invoking [*MoEInAppHelper.getInstance().onConfigurationChanged()*](https://moengage.github.io/android-api-reference/inapp/com.moengage.inapp/-mo-e-in-app-helper/on-configuration-changed.html) API for SDK to redraw the in-app when the activity receives *onConfigurationChanged()* callback from the framework.
```kotlin Kotlin wrap theme={null}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
MoEInAppHelper.getInstance().onConfigurationChanged()
}
```
```java Java theme={null}
@Override public void onConfigurationChanged(@NonNull Configuration newConfig) {
super.onConfigurationChanged(newConfig);
MoEInAppHelper.getInstance().onConfigurationChanged();
}
```
# Contextual InApp
You can restrict the in-apps based on the user's context in the application, apart from restricting InApp campaigns on a specific screen/activity. To set the user's context in the application, use [*setInAppContext()*](https://moengage.github.io/android-api-reference/inapp/com.moengage.inapp/-mo-e-in-app-helper/set-in-app-context.html) API, as shown below.
## Set Context
Call the below method in the *onStart()* of your *Activity* or *Fragment* before calling *showInApp().*
```kotlin Kotlin wrap theme={null}
MoEInAppHelper.getInstance().setInAppContext(setOf("context1", "context2", "context3"))
```
```java Java theme={null}
Set inAppContext = new HashSet<>();
inAppContext.add("context1");
inAppContext.add("context2");
inAppContext.add("context3");
MoEInAppHelper.getInstance().setInAppContext(inAppContext);
```
The context is not the same context as [Android Context](https://developer.android.com/reference/android/content/Context?hl=en). This user's context in the application flow.
## Reset Context
Once the user is moving out of the context, use the [*restInAppContext()*](https://moengage.github.io/android-api-reference/inapp/com.moengage.inapp/-mo-e-in-app-helper/reset-in-app-context.html) API to reset/clear the existing context.
```kotlin Kotlin wrap theme={null}
MoEInAppHelper.getInstance().resetInAppContext()
```
```java Java theme={null}
MoEInAppHelper.getInstance().resetInAppContext();
```
Code example below:
```kotlin Kotlin wrap theme={null}
// Activity
class MyCustomActivity: Activity() {
override fun onStart() {
super.onStart()
MoEInAppHelper.getInstance().setInAppContext(setOf("context1", "context2"))
MoEInAppHelper.getInstance().showInApp(this)
}
override fun onStop() {
super.onStop()
MoEInAppHelper.getInstance().resetInAppContext()
}
}
// Fragment
class MyCustomFragment: Fragment() {
override fun onStart() {
super.onStart()
// Fragment's onStart code
// context1 and context2 can be changes as per screen/requirement
MoEInAppHelper.getInstance().setInAppContext(setOf("context1", "context2"))
MoEInAppHelper.getInstance().showInApp(this)
}
override fun onStop() {
super.onStop()
// Fragment's onStop code
MoEInAppHelper.getInstance().resetInAppContext()
}
}
```
```java Java theme={null}
// Activity
public class MyCustomActivity extends Activity {
@Override
protected void onStart() {
super.onStart();
// Activity's custom onStart logic here
Set inAppContext = new HashSet<>();
inAppContext.add("context1"); // Change the string name as per your requirement
inAppContext.add("context2"); // Change the string name as per your requirement
MoEInAppHelper.getInstance().setInAppContext(inAppContext);
MoEInAppHelper.getInstance().showInApp(this)
}
@Override
protected void onStop() {
super.onStop();
// Activity's custom onStop logic here
MoEInAppHelper.getInstance().resetInAppContext();
}
}
// Fragment
public class MyCustomFragment extends Fragment {
// Other Fragment code
@Override
public void onStart() {
super.onStart();
// Fragment's onStart code here
Set inAppContext = new HashSet<>();
inAppContext.add("context1");
inAppContext.add("context2");
MoEInAppHelper.getInstance().setInAppContext(inAppContext);
MoEInAppHelper.getInstance().showInApp(this)
}
@Override
public void onStop() {
super.onStop();
MoEInAppHelper.getInstance().resetInAppContext();
}
}
```
# WebView Customization
Starting with In-App SDK version **9.6.0**, the SDK supports customizing the underlying WebView used to render HTML In-App messages. This allows for modifying the WebView settings, adding custom JavaScript interfaces, and implementing other configurations to the WebView used to render HTML In-Apps.
To customize the WebView, you must invoke the `MoEInAppHelper.getInstance().setInAppWebViewCustomizer()` API. Any custom settings defined using this API will override the default MoEngage In-App WebView settings.
```kotlin Kotlin wrap theme={null}
MoEInAppHelper.getInstance().setInAppWebViewCustomizer {
addJavascriptInterface(MyBridge(), "bridge")
settings.mediaPlaybackRequiresUserGesture = false
}
```
```java Java theme={null}
MoEInAppHelper.getInstance().setInAppWebViewCustomizer(
new kotlin.jvm.functions.Function1() {
@Override
public kotlin.Unit invoke(InAppWebView webView) {
WebSettings settings = webView.getSettings();
settings.setMediaPlaybackRequiresUserGesture(false);
webView.addJavascriptInterface(new CustomJavaScriptBridge(), "myBridge");
return kotlin.Unit.INSTANCE;
}
}
);
```
# Self-Handled InApps
Self-handled In-Apps are messages that the SDK delivers to the application, and the application builds the UI using the SDK's delivered payload.
## Single Self-Handled InApps
To get the self-handled in-app, use the below API.
```kotlin Kotlin wrap theme={null}
MoEInAppHelper.getInstance().getSelfHandledInApp(context, listener)
```
```java Java theme={null}
MoEInAppHelper.getInstance().getSelfHandledInApp(context, listener);
```
The **listener** is an instance of [*SelfHandledAvailableListener.*](https://moengage.github.io/android-api-reference/inapp/com.moengage.inapp.listeners/-self-handled-available-listener/index.html)
This method should be called in the *onResume()* of your Fragment or *onStart()* of your activity.\
The above method is asynchronous and does not return the payload immediately, once the payload is available [*onSelfHandledAvailable(), the listener callback*](https://moengage.github.io/android-api-reference/inapp/com.moengage.inapp.listeners/-self-handled-available-listener/on-self-handled-available.html) would be called with the payload.
### Event-Triggered Self Handled InApps
To get a callback for an event triggered, implement *SelfHandledAvailableListener* and register for a listener using [*MoEInAppHelper.getInstance().setSelfHandledListener()*](https://moengage.github.io/android-api-reference/inapp/com.moengage.inapp/-mo-e-in-app-helper/set-self-handled-listener.html). SDK will notify the registered listener once the campaign is available.
We recommend registering this listener in the *onCreate()* of the *Application* class if the trigger event can happen on multiple screens.
## Multiple Self-Handled InApps
* This feature requires a minimum catalog version **4.5.0**
* Event-triggered multiple self-handled inapps are not supported.
Fetch Multiple Self Handled Campaigns using [*getSelfHandledInApps()*](https://moengage.github.io/android-api-reference/inapp/com.moengage.inapp/-mo-e-in-app-helper/index.html#1129437895%2FFunctions%2F434681417). The MoEngage SDK will return up to 5 campaigns(in the order of campaign priority set at the time of campaign creation) in the campaigns available callback method [*onCampaignsAvailable()*](https://moengage.github.io/android-api-reference/inapp/com.moengage.inapp.listeners/-self-handled-campaigns-available-listener/index.html#-1056690682%2FFunctions%2F434681417)**.**
```kotlin Kotlin wrap theme={null}
MoEInAppHelper.getInstance().getSelfHandledInApps(context, listener)
```
```java Java theme={null}
MoEInAppHelper.getInstance().getSelfHandledInApps(context, listener);
```
The *listener* is an instance of [*SelfHandledCampaignsAvailableListener*](https://moengage.github.io/android-api-reference/inapp/com.moengage.inapp.listeners/-self-handled-campaigns-available-listener/index.html)[.](https://moengage.github.io/android-api-reference/inapp/com.moengage.inapp.listeners/-self-handled-available-listener/index.html)
This method should be called in the *onResume()* of your Fragment or *onStart()* of your activity.\
The above method is asynchronous and does not return the payload immediately, once the payload is available [*onCampaignsAvailable() callback*](https://moengage.github.io/android-api-reference/inapp/com.moengage.inapp.listeners/-self-handled-campaigns-available-listener/index.html#-1056690682%2FFunctions%2F434681417) of the listener would be called with the payload.
### Tracking Statistics for Multiple Self-Handled In-Apps
The *onCampaignsAvailable()* callback method returns [*SelfHandledCampaignsData*](https://moengage.github.io/android-api-reference/inapp/com.moengage.inapp.model/-self-handled-campaigns-data/index.html), which contains a list of [*SelfHandledCampaignData*](https://moengage.github.io/android-api-reference/inapp/com.moengage.inapp.model/-self-handled-campaign-data/index.html) objects. The statistics for each *SelfHandledCampaignData* object must be tracked individually below APIs.
### Fetching Contextual Multiple Self-Handled InApps
To fetch contextual multiple self-handled inapps, set the inapp contexts using [*setInAppContext()*](/developer-guide/android-sdk/in-app-messages/in-app-nativ#Set-Context) before calling \*[getSelfHandledInApps()](https://moengage.github.io/android-api-reference/inapp/com.moengage.inapp/-mo-e-in-app-helper/index.html#1129437895%2FFunctions%2F434681417).\*This will return a list of contextual and non-contextual inapps(in the order of campaign priority set at the time of campaign creation).
### Campaign Selection Logic
* **Default Limit**: By default, only 5 campaigns will be fetched.
* **Priority-Based Selection**: Campaigns are delivered based on their priority and last updated time. It checks for priority first and then checks the last updated time on conflicting priorities
* **Exclusion criteria**: Campaigns are only excluded based on specific rules like frequency capping, eligibility criteria, campaign status, or priority limits.
**Example Scenario:** If you have 6 campaigns with different priorities, published time and contexts:
* Context 1: Campaign 1 (P0, T2), Campaign 2 (P1, T3), Campaign 3 (P2, T6)
* Context 2: Campaign 4 (P0, T1), Campaign 5 (P1, T5)
* Context 3: Campaign 6 (P0, T4)
Following campaigns will be delivered in this order: \[Campaign 4, Campaign 1, Campaign 6, Campaign 2, Campaign 5]
**Selection Algorithm:**
1. Filter campaigns by user eligibility and targeting criteria
2. Sort by campaign priority (P0, P1, P2, etc.)
3. For campaigns with same priority, sort by most recent update timestamp
4. Return top 5 campaigns
#### **Best Practices for Campaign Organization for multiple self handled campaigns**
For optimal performance across multiple contexts on a single page, organize your campaigns like this:
* Context 1 (Homepage): Campaign A (P0), Campaign B (P1)
* Context 2 (Product): Campaign C (P0), Campaign D (P1)
* Context 3 (Checkout): Campaign E (P0)
This ensures each context has relevant campaigns without hitting the 5-campaign limit.
Also, make sure that you set the priority of the campaigns you want to fetch accordingly, because the method will fetch all self-handled campaigns regardless of whether they are context-based or not.
## Tracking Statistics for Self-Handled In-Apps
The application must notify MoEngage SDK whenever the In-App messages are displayed, clicked on, or dismissed, as the application controls these actions. The following methods are called to notify the SDK. The data object [*SelfHandledCampaignData*](https://moengage.github.io/android-api-reference/inapp/com.moengage.inapp.model/-self-handled-campaign-data/index.html) provided to the application in the callback for self-handled in-app should be passed as a parameter to the following APIs.
```kotlin Kotlin wrap theme={null}
// call whenever in-app is shown
MoEInAppHelper.getInstance().selfHandledShown(context, data)
// call whenever in-app is clicked
MoEInAppHelper.getInstance().selfHandledClicked(context, data)
// call whenever in-app is dismissed
MoEInAppHelper.getInstance().selfHandledDismissed(context, data)
```
```java Java theme={null}
// call whenever in-app is shown
MoEInAppHelper.getInstance().selfHandledShown(context, data);
// call whenever in-app is clicked
MoEInAppHelper.getInstance().selfHandledClicked(context, data);
// call whenever in-app is dismissed
MoEInAppHelper.getInstance().selfHandledDismissed(context, data);
```
For more information, refer to the [API documentation](https://moengage.github.io/android-api-reference/inapp/com.moengage.inapp/-mo-e-in-app-helper/index.html#-59857046%2FFunctions%2F434681417).
# In-Apps Callback
## Lifecycle callback
To get callbacks whenever an InApp campaign is shown or dismissed, implement the [*InAppLifeCycleListener*](https://moengage.github.io/android-api-reference/inapp/com.moengage.inapp.listeners/-in-app-life-cycle-listener/index.html) and register for the callbacks using [*MoEInAppHelper.getInstance().addInAppLifeCycleListener()*](https://moengage.github.io/android-api-reference/inapp/com.moengage.inapp/-mo-e-in-app-helper/add-in-app-life-cycle-listener.html).
## Click Callback
To handle user navigation or custom action, SDK provides a callback whenever an in-app widget is clicked with either Navigation or Custom action. To get callbacks implement the [*OnClickActionListener*](https://moengage.github.io/android-api-reference/inapp/com.moengage.inapp.listeners/-on-click-action-listener/index.html) interface and register for the callbacks using [*MoEInAppHelper.getInstance().setClickActionListener()*](https://moengage.github.io/android-api-reference/inapp/com.moengage.inapp/-mo-e-in-app-helper/set-click-action-listener.html).
# Blocking InApps on Screens
Additionally, you can block in-app on a specific screen or handle the status bar visibility using the [InAppConfig](https://moengage.github.io/android-api-reference/core/com.moengage.core.config/\[android-jvm]-in-app-config/index.html) object and pass it to the SDK using the [MoEngage.Builder](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]-mo-engage/-builder/index.html) object. Use the [configureInApps()](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]-mo-engage/-builder/configure-in-apps.html) API to pass on the configuration to the SDK.
```kotlin Kotlin wrap theme={null}
// List of activity classes on which in-app should not be shown
val inAppOptOut = mutableListOf()
inAppOptOut.add(SplashActivity::class.java.name)
val moengage = MoEngage.Builder(application, "XXXXXXXX")
.configureInApps(InAppConfig(inAppOptOut,true))
.build()
MoEngage.initialise(moengage)
```
```java Java theme={null}
ArrayList inAppOptOut = new ArrayList<>();
inAppOptOut.add(SplashActivity.class.getName());
MoEngage.Builder builder = new MoEngage.Builder(application, "XXXXXXXXXX")
.configureInApps(new InAppConfig(inAppOptOut,true));
MoEngage.initialise(builder.build());
```
# Testing In-App
Refer to this [link](https://help.moengage.com/hc/en-us/articles/360047789092-Testing-your-In-App-Nativ-Campaigns) to read more about how to create and test in-apps.
# Implementing Embedded Nudges (Deprecated)
Starting InApp version **7.0.0,** embedded nudges are no longer supported.
Nudges are non-disruptive messages which can be placed anywhere in the activity.
Add the following code in the activity/fragment layout file.
```XML XML wrap theme={null}
```
## Using in an Activity
Get an instance of the nudge view in the **onCreate()** and initialize the nudge view in the **onStart()** of the Activity.
## Using in a Fragment
Get an instance of the nudge view in the **onCreateView()** and initialize the nudge view in the **onResume()** of the fragment.
Use the below code to get the instance of the ***NudgeView*** and initialize it.
```kotlin Kotlin wrap theme={null}
// get instance of the view
val nudge = findViewById(R.id.nudge)
// initialize
nudge.initialiseNudgeView(activity)
```
```java Java theme={null}
// get instance of the view
NudgeView nv = (NudgeView)findViewById(R.id.nudge);
// initialize
nv.initialiseNudgeView(getActivity());
```
# FAQs
* For In-App SDK version 9.6.0 and above, refer to the [WebView Customization](https://developers.moengage.com/hc/en-us/articles/4403652537492-In-App-NATIV#h_01KC43AKSVZHQDM57VMX0K35PF).
* If you are using In-App SDK version below 9.6.0, perform the following steps:
* Android's default WebView does not support file inputs. To enable this functionality, trigger a Custom Action from your HTML and handle it natively with an *OnClickActionListener*.\
Within the listener, launch your native file picker or camera logic. Ensure your app requests the required runtime permissions, such as CAMERA and READ\_EXTERNAL\_STORAGE.
Example:
```kotlin Kotlin wrap theme={null}
val listener = OnClickActionListener { clickData ->
if (clickData.action.actionType == ActionType.CUSTOM_ACTION &&
(clickData.action as CustomAction).keyValuePairs["action"] == "uploadPhoto")
{
openImageChooser() // Your native camera/gallery function
true // Indicates the action was handled
} else {
false
}
}
```
* For iOS, file inputs work by default. However, for a consistent cross-platform implementation, we recommend using the same Custom Action approach.
# Migrating from addon-inbox 6.0.2
Source: https://moengage.com/docs/developer-guide/android-sdk/migration/migrating-from-addon-inbox-602
Migrate from addon-inbox 6.0.2 to the updated inbox-core and inbox-ui modules in MoEngage Android SDK.
This migration is required only if you are using *addon-inbox 6.0.2* or below and migrating to *11.2.00* or above version of moe-android-sdk.
Since the early days of MoEngage, we have provided `addon-inbox` artifact for using Notification Center in your application. We have revamped the module and broken down the module into multiple modules to make it more robust, lightweight, and scalable for future improvements/enhancements.
# Updated Artifacts
`inbox-core` - Module contains APIs and helper methods to build an inbox. Provides APIs to fetch messages, track clicks, etc
`inbox-ui` - Module contains the user interface for the inbox module and helper methods for customization of the UI.
# Using SDK Notification Center
If you are using the UI provided by the SDK you need to include the `inbox-ui` module in your application. Key changes you would notice here apart from the artifact name update
* RecyclerView used instead of ListView
* Updated UI
* API updates for customizing the UI
Refer to the updated [MoEngage's default Notification Center](https://developers.moengage.com/hc/en-us/articles/4403878923284) for details on how to use the default UI and possible customization.
# Self handled Notification Center
If you were building your own Notification Center consuming the data from MoEngage we have made the APIs simpler for you and made the SDK lighter. Integrate the `inbox-core` module.
Refer to the [Self Handled Notification Center](https://developers.moengage.com/hc/en-us/articles/4403878923284-Notification-Center-for-MoEngage-SDK-Version-11-2-00-or-later#self-handled-notification-center-0-9) for updated APIs
# Update the packages:
While we have revamped the modules we have tried to maintain some of the classes to avoid re-integration wherever feasible. Though we have not changed the APIs as such we have moved it to a new package for better integration in the future.\
Refer to the below table for updated packages.
| Then | Now |
| -------------------------------------------------------------- | --------------------------------------------------------------- |
| com.moengage.addon.inbox.MoEInboxHelper | com.moengage.inbox.core.MoEInboxHelper |
| com.moengage.addon.inbox.listener. OnMessagesAvailableListener | com.moengage.inbox.core.listener. OnMessagesAvailableListener |
| com.moengage.addon.inbox. InboxMessageClickCallback | com.moengage.inbox.ui.listener. OnMessageClickListener |
| com.moengage.addon.inbox.MoEInboxActivity | com.moengage.inbox.ui.view\.InboxActivity |
| com.moengage.addon.inbox.InboxFragment | com.moengage.inbox.ui.view\.InboxFragment |
| com.moengage.addon.inbox.InboxManager .ViewHolder | com.moengage.inbox.ui.adapter.ViewHolder |
| com.moengage.addon.inbox.InboxManager .InboxAdapter | com.moengage.inbox.ui.adapter.InboxAdapter |
# Migrating from GCM to FCM
Source: https://moengage.com/docs/developer-guide/android-sdk/migration/migrating-from-gcm-to-fcm
Migrate your Android app from Google Cloud Messaging to Firebase Cloud Messaging for MoEngage push.
As of April 10, 2018, Google has deprecated GCM. The GCM server and client APIs are deprecated and will be removed as soon as April 11, 2019. Migrate GCM apps to Firebase Cloud Messaging (FCM), which inherits the reliable and scalable GCM infrastructure, plus many new features.
# Migrate the GCM Client library to FCM Client Library
## Import your GCM project as a Firebase project
1. In the Firebase console, select Add Project.
2. Select your GCM project from the list of existing Google Cloud projects, and select Add Firebase.
3. In the Firebase welcome screen, select Add Firebase to your Android App.
4. Provide your package name and SHA-1, and select Add App. A new google-services.json file for your Firebase app is downloaded.
5. Select Continue and follow the detailed instructions for adding the Google Services plugin in Android Studio.
## Switch to FCM in the app-level build.gradle
Add the latest version of the Firebase SDK.
```Groovy Groovy wrap theme={null}
dependencies {
compile "com.google.firebase:firebase-messaging:15.0.0"
}
```
## Edit your app's manifest
If you have the below declaration in your Manifest remove it.
```XML XML wrap theme={null}
...
```
Refer to the [official migration guide](https://developers.google.com/cloud-messaging/android/android-migrate-fcm) for more details.
# Migrate MoEngage library from GCM to FCM
The [latest version](/developer-guide/release-notes/android-sdk/2023-and-older-1) of the MoEngage SDK ships with the Firebase dependency.
## Using SDK version 8.x.x or above
If you are using SDK version 8.0.00 or above, then you are already using the FCM library of MoEngage, provided you have not removed it as mentioned below.
```Groovy Groovy wrap theme={null}
compile ('com.moengage:moe-android-sdk:8.5.00'){
exclude group: 'com.moengage', module: 'moe-push-firebase'
}
compile 'com.moengage:moe-push-gcm:2.0.04'
```
If you are using something like the above change it as below
```Groovy Groovy wrap theme={null}
dependencies {
compile 'com.moengage:moe-android-sdk:8.5.00'
}
```
# Using SDK version 7.x.x
MoEngage SDK version 7.x.x uses the GCM library by default. To use the FCM library, you need to exclude the GCM library and add the FCM library as mentioned below.
```Groovy Groovy wrap theme={null}
dependencies {
compile ('com.moengage:moe-android-sdk:7.7.16'){
exclude group: 'com.moengage', module: 'moe-push-gcm'
}
compile 'com.moengage:moe-push-firebase:1.1.02'
}
```
# Migrating to Push Amp+ 2.0.00
Source: https://moengage.com/docs/developer-guide/android-sdk/migration/migrating-to-push-amp-plus-2000
Migrate the MoEngage Push Amp+ SDK from version 1.2.00 or below to 2.x with updated configuration.
These migration steps are only required if you are updating the push-amp-plus SDK from 1.2.00 or below to 2.x or higher.
In the advent of making our SDK more configurable and robust, we have some changes or improvements in the SDK. We had to make some breaking changes in the SDK in the process. We request you to refer to the migration steps below and make changes accordingly.
# Update the SDK Version
Update the SDK to the latest version by updating the dependency versions in your `app/build.gradle` file. You would need to update the version for `moe-android-sdk` `push-amp-plus` artifacts.\
Ensure refer to the [Release Notes](https://developers.moengage.com/hc/en-us/articles/4403896795540).
**Version Compatibility**
The *push-amp-plus* artifact should be compatible with the *moe-android-sdk* artifact you have already added. Make sure you check the [version compatibility](https://developers.moengage.com/hc/en-us/articles/4403458168468) and pick the right version for your application
# Configure Push Amp+
To configure Push Amp plus follow these steps as described in [Push AMP Plus Integration](https://developers.moengage.com/hc/en-us/articles/4403458168468):
1. Add Permissions to the Manifest File
2. Add Receiver and Services in Manifest File
3. Add Meta Data
4. Configuring Receviers
If you are unsure how to get the metadata required for the configuration or don't know where to find it, contact your Account Manager or the MoEngage Support team.
# Migration from 4.x to 5.x (One time activity)
Source: https://moengage.com/docs/developer-guide/android-sdk/migration/migration-from-4x-to-5x-one-time-activity
Migrate your MoEngage Android SDK integration from version 4.x to 5.x with updated receivers and APIs.
Follow the installation steps mentioned [here](https://developers.moengage.com/hc/en-us/articles/44622788607892).
Changes required to migrate to 5.x are minimum but some structural changes require you to remove some lines of code. This had to be done to make it loosely coupled and easy to integrate
* No change in Manifest permissions
* Basic integration points remain same
* Changes in receivers & services
* Deprecated few APIs and provided alternatives
* Inbox moved out of Main SDK and added to add-on lib
If using Play Services 7.3 **No Changes in the following receivers**.
```XML XML wrap theme={null}
{/* MOENGAGE RECEIVER FOR RECEIVING GCM BROADCAST MESSAGES */}
{/* MOENGAGE RECEIVER FOR RECEIVING INSTALLATION INTENT */}
```
If using Google Play Services 7.5
```XML XML wrap theme={null}
```
# Remove the following receivers
```Java Java wrap theme={null}
{/* MOENGAGE RECEIVER FOR RECEIVING PACKAGE UPDATED INTENT */}
{/* MOENGAGE SERVICE PROCESSING GCM MESSAGES */}
{/* MOENGAGE RECEIVER FOR INTERNAL PURPOSE */}
{/* MOENGAGE RECEIVER FOR TRIGGERING INTERACTION DATA SYNC */}
```
# Add the following Receivers
```XML XML wrap theme={null}
```
# Add the following Provider
```XML XML wrap theme={null}
```
# Add the \ following tags
```XML XML wrap theme={null}
{/* MANDATORY FIELD: APP ID AS SEEN ON MOENGAGE DASHBOARD APP SETTINGS PAGE */}
{/* MANDATORY FIELD: SENDER ID , i.e. THE PROJECT NUMBER AS MENTIONED ON GOOGLE CLOUD CONSOLE PROJECTS PAGE */}
{/* MANDATORY FIELD: THE NOTIFICATION SMALL ICON WHICH WILL BE USED TO SET TO NOTIFICATIONS POSTED */}
{/* MANDATORY FIELD: THE NOTIFICATION LARGE ICON WHICH WILL BE USED TO SET TO NOTIFICATIONS POSTED */}
{/* OPTIONAL FIELD: THE NOTIFICATION TYPE WHICH WILL BE USED, SINGLE OR MULTIPLE. DEFAULT BEHAVIOR IS SINGLE */}
{/* OPTIONAL FIELD: THE NOTIFICATION TONE THAT WILL BE USED. IF NOT SET WILL PLAY THE DEFAULT SOUND */}
```
# Delete the following code
```Java Java wrap theme={null}
//Delete the INITIALISATION METHOD CALL. THIS IS DEPRECATED AND NOT REQUIRED ANY LONGER
helper.initialize( GCM_SENDER_ID, MOE_APP_ID);
//Delete the REGISTER METHOD CALL. THIS IS DEPRECATED AND NOT REQUIRED ANY LONGER
helper.Register(R.drawable.ic_launcher);
```
# Add the following code (optional)
Add this only if you support the change in orientation.
```Java Java wrap theme={null}
/*
* (non-Javadoc)
*
* @see android.app.Activity#onSaveInstanceState(android.os.Bundle)
*/
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mHelper.onSaveInstanceState(outState);
}
/*
* (non-Javadoc)
*
* @see android.app.Activity#onRestoreInstanceState(android.os.Bundle)
*/
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
mHelper.onRestoreInstanceState(savedInstanceState);
}
```
# Inbox Users
Change the following:
Old declaration
```XML XML wrap theme={null}
{/* MOENGAGE INBOX ACTIVITY DECLARATION */}
```
Change to
```XML XML wrap theme={null}
```
# Add the Install/Update Differentiator
Add the install update differentiator as mentioned [here](https://developers.moengage.com/hc/en-us/articles/4402050819220).
In case you have any issues, please do contact the Custom Success Managers who will help you out
# Migration to 10.x.xx
Source: https://moengage.com/docs/developer-guide/android-sdk/migration/migration-to-10xxx
Migrate to MoEngage Android SDK 10.x.xx with updated APIs, removed GCM support, and behavioral changes.
# Migrating from Manifest based integration
In version SDK version `9.0.00` we introduced a new way of integrating the MoEngage SDK via Java/Kotlin code and deprecated integration using metadata in the Manifest file. Starting version `10.0.00` we are removing support for integration which uses Manifest metadata. Refer to the [documentation](https://developers.moengage.com/hc/en-us/articles/4403898171156) to learn more on the migration to code-based integration.
# Behavioral Changes
* Self-Handled in-app delivered on the Main thread
* Removed support for GCM
* Removed support for Baidu
* For showing gifs in in-apps SDK was dependent on Fresco before SDK version `10.0.00` Starting from SDK version `10.0.00` SDK uses Glide to show gifs. Make sure you add Glide as a dependency in your application if you wish to use gifs.
* "nav\_provier", "nav\_source", will no longer be present in the push payload or deep-link link URL.
* If sender id is provided for while initializing the SDK it will be used for token registration instead of the default sender id in the `google-services.json` file.
* InApp Callbacks - InApp Callbacks listener is now a concrete class rather than an interface.
* InstallReceiver removed from the SDK. If you have added `com.moe.pushlibrary.InstallReceiver` in the manifest please remove.
# Update removed APIs
In version `10.0.00` of the SDK, we have removed many of the APIs which were long deprecated. If you are still using the deprecated APIs you have to update to the new APIs. Below is a table mapping the equivalents of the removed APIs. Some of the APIs might not have an alternate API as the functionality might have been handled internally or no longer supported.
| Then | Now |
| ---------------------------------------------------------------- | --------------------------------------------------------------- |
| MoEngage.Builder#setTrackingOptOut(List) | MoEngage.Builder#optOutActivityTracking(List) |
| MoEngage.Builder#setInAppOptOut(List) | MoEngage.Builder#optOutInAppFromActivity (List) |
| MoEHelper#setFlushInterval(long) | MoEngage.Builder#setFlushInterval(long) |
| MoEHelper#setExistingUser(boolean) | MoEHelper#setAppStatus(AppStatus) |
| MoEHelper#optOutOfAdIdCollection (Context, boolean) | MoEngage.Builder#optOutGAIDCollection() |
| MoEHelper#optOutOfLocationTracking (Context, boolean) | MoEngage.Builder#optOutLocationTracking() |
| MoEHelper#optOutOfGeoFences (Context, boolean) | MoEngage.Builder#optOutGeoFence() |
| MoEHelper#setLogLevel(int) | MoEngage.Builder#setLogLevel(int) |
| MoEHelper#setLogStatus(boolean) | MoEngage.Builder#enableLogsForSignedBuild() |
| MoEHelper#optOutOfAndroidIdCollection(Context, boolean) | MoEngage.Builder#optOutAndroidIdCollection() |
| MoEHelper#optOutOfOperatorNameCollection (Context, boolean) | MoEngage.Builder#optOutCarrier NameCollection() |
| MoEHelper#optOutOfDeviceAttributeCollection (Context, boolean) | MoEngage.Builder#optOutDevice AttributeCollection() |
| MoEHelper#redirectDataToRegion(int) | MoEngage.Builder#redirectDataToRegion (MoEngage.DATA\_REGION) |
| MoEHelper#setPeriodicFlushState(boolean) | MoEngage.Builder#optOutPeriodicFlush() |
| PushManager#optoutBackStackBuilder(Boolean) | MoEngage.Builder#optOutBackStackBuilder() |
| MoEPushCallBacks.OnMoEPushReceiveListener | PushMessageListener#onNotificationReceived() |
| MoEPushCallBacks.OnMoEPushNavigationAction | PushMessageListener#onHandleRedirection() |
| MoEPushCallbacks.OnMoEPushClickListener | PushMessageListener#onHandleRedirection() |
| MoEPushCallBacks.OnMoEPushClearedListener | PushMessageListener#onNotificationCleared() |
| MoEPushCallBacks#setOnMoEPushReceiveListener | MoEPushHelper#setMessageListener\|(PushMessageListener) |
| MoEPushCallBacks#setOnMoEPush NavigationAction | MoEPushHelper#setMessageListener( PushMessageListener) |
| MoEPushCallBacks#setOnMoEPush ClearedListener | MoEPushHelper#setMessageListener (PushMessageListener) |
| MoEHelper#setBirthDate(String) | MoEHelper#setBirthDate(Date) |
| PushManager#optOutMoEngageExtras(boolean) | Not required any more |
| MoEHelper#showInAppIfAny(boolean) | Not required any more |
| MoEHelper#autoIntegrate(Application) | Not required any more |
| MoEHelper#onStart(Activity) | Not required any more |
| MoEHelper#onStop(Activity) | Not required any more |
| MoEHelper#onResume(Activity) | Not required any more |
| MoEHelper#onFragmentStart(Activity, String) | Not required any more |
| MoEHelper#onFragmentStop(Activity, String) | Not required any more |
| MoEHelper#optOutOfIMEICollection (Context, boolean) | Not required any more |
| MoEngage.Builder#optOutMoEngageExtras() | Not required any more |
| MoEngage.Builder#enableInstantApp() | Merged with MoEngage.Builder#setSenderId() |
| MoEngage.Builder#enableBaiduPush(String) | Baidu Push not supported. |
# APIs deprecated in 10.0.00
In version `10.0.00` we have deprecated a few APIs to improve performance and better support in the future. Below is the list of deprecated APIs and their alternatives, please update to the latest methods.
| Then | Now |
| ----------------------------------------- | ----------------------------------------------------- |
| MoEngage.Builder#setNotificationType(int) | MoEngage.Builder#enableMultipleNotificationInDrawer() |
| PayloadBuilder | Properties |
# Migration To Maven Central
Source: https://moengage.com/docs/developer-guide/android-sdk/migration/migration-to-maven-central
Migrate your MoEngage Android SDK dependencies from JCenter to Maven Central.
JFrog recently announced that they are making important changes that will impact users of Bintray, JCenter. We as developers would not be able to publish new packages on Bintray after 31st March 2021 and existing packages wouldn't be available for use after 1st February 2022.\
Checkout out the [blog post](https://jfrog.com/blog/into-the-sunset-bintray-jcenter-gocenter-and-chartcenter/) for more details.
We at MoEngage have been publishing our Android SDK/artifacts to Jcenter for the past few years and have moved to publish artifacts to Maven Central. Going forward all the artifacts would be available via Maven Central only.
# How does it affect you?
Since existing packages are available for download till 1st February 2022 the shutdown will not affect you immediately. Though we strongly recommend you migrate to the version published on maven central(`11.0.04` or above) at the earliest to avoid any issues.
The versions mentioned are the latest version at the time of publishing this document(1st March 2021). Refer to the Release Notes of the respective framework.
# Migration for 11.x.xx
If you are using the 11.x.xx version of the MoEngage SDK you would just need to change the version to `11.0.04` or above to move to maven central Artifacts.\
Make sure you update the other unbundled/dependent MoEngage SDKs or modules(like Push Amp Plus, Push Templates, etc.) to the compatible version.\
Below is the list of compatible versions for `11.0.04`, 1st version on maven central.
| Artifact | Version |
| ----------------- | ------- |
| moe-android-sdk | 11.0.04 |
| addon-inbox | 6.0.2 |
| cards | 2.0.02 |
| hms-pushkit | 2.0.02 |
| push-amp-plus | 3.0.02 |
| rich-notification | 2.0.03 |
| geofence | 1.0.02 |
# Migration for 10.x.xx
Update to the latest SDK version `11.0.04` or above. Since it would be a major version update there might be additional code changes required apart from changing the version number in your gradle file(s). Refer to the [Updating to 11.x.xx](/developer-guide/android-sdk/migration/updating-to-11xxx-from-10xxx) document and [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older-1) for more details.\
Make sure you update the other unbundled/dependent MoEngage SDKs or modules(like Push Amp Plus, Push Templates, etc.) to the compatible version.
In case, you are not able to update to `11.x.xx` due to some technical limitations or bandwidth issues we have uploaded the last `10.x.xx` version along with the add-on modules on Maven Central. You can update to the below versions.
| Artifact | Version |
| ----------------- | ------- |
| moe-android-sdk | 10.6.01 |
| addon-inbox | 5.3.1 |
| cards | 1.2.01 |
| hms-pushkit | 1.2.01 |
| push-amp-plus | 2.2.01 |
| rich-notification | 1.2.02 |
We strongly recommend you update to the latest version instead of 10.6.01 to take advantage of all the latest features/improvements/optimizations we have made.
# Migration for below 10.x.xx
We recommend you update to the latest version, we will not be publishing/moving 9.x.xx or below to maven central. Since you would be updating 2 major versions we recommend you go through the documentation and update accordingly.
# Cross-Platform Frameworks
MoEngage provides support for a number of cross-platform frameworks like React-Native, Flutter, Unity, Cordova, etc. Our Cross-Platform frameworks are dependent on the above-mentioned native(Java/Kotlin) Android SDK and equally affected by the Jcenter shutdown. We have updated our Cross-Platform plugins or packages to use artifacts published on Maven Central instead of Jcenter.\
Below are the latest version of the plugins.
| Framework Name | Version |
| -------------- | ------- |
| React-Native | 7.0.0 |
| Flutter | 3.0.0 |
| Flutter Inbox | 2.0.0 |
| Cordova | 7.0.0 |
| Unity | 2.0.0 |
The above version is built on top of `11.x.xx` and we strongly recommend you to use the above versions or above.
In case, you are not able to update to `11.x.xx` due to some technical limitations or bandwidth issues we have uploaded the last `10.x.xx` version along with the add-on modules on Maven Central. You can update to the below versions. These versions are built on top of `10.6.01` the `10.x.xx` version on Maven Central.
| Framework Name | Version |
| -------------- | ------- |
| React-Native | 6.1.7 |
| Flutter | 2.0.3 |
| Flutter Inbox | 1.0.2 |
| Cordova | 6.1.4 |
| Unity | 1.3.1 |
# Segment Integration
We recommend you migrate to the version published on maven central(`5.1.00` or above) at the earliest to avoid any issues.
# Migration for 5.x.xx
If you are using the 5.x.xx version of the MoEngage SDK you would just need to change the version to `5.1.00` or above to move to maven central Artifacts.\
Make sure you update the other unbundled/dependent MoEngage SDKs or modules(like Push Amp Plus, Push Templates, etc.) to the compatible version.
# Migration for 4.x.xx
Update to the latest SDK version `5.1.00` or above. Since it would be a major version update there might be additional code changes required apart from changing the version number in your gradle file(s). Refer to the [Updating to 11.x.xx](/developer-guide/android-sdk/migration/updating-to-11xxx-from-10xxx) document and [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older-1) for more details.\
Make sure you update the other unbundled/dependent MoEngage SDKs or modules(like Push Amp Plus, Push Templates, etc.) to the compatible version.
In case, you are not able to update to `5.x.xx` due to some technical limitations or bandwidth issues we have uploaded the last `4.x.xx` version along with the add-on modules on Maven Central. You can update to the below versions.
| Artifact | Version |
| ---------------------------- | ------- |
| moengage-segment-integration | 4.3.01 |
| addon-inbox | 5.3.1 |
| cards | 1.2.01 |
| hms-pushkit | 1.2.01 |
| push-amp-plus | 2.2.01 |
| rich-notification | 1.2.02 |
# Moving from Manifest to Code based Integration
Source: https://moengage.com/docs/developer-guide/android-sdk/migration/moving-from-manifest-to-code-based-integration
Migrate your MoEngage Android SDK setup from manifest metadata to code-based initialization.
We have deprecated integration on MoEngage SDK via Manifest configuration/tags.\
In the latest integration, you need to initialize the SDK in the `onCreate()` of the application class of your app. Below are the metadata flags you need to remove and equivalent APIs you need to call in the `onCreate()` of your application class.\
If you are already initializing the SDK via code in your Application class you can ignore this.
# Adding App Id
## Then
```text wrap theme={null}
{/* MANDATORY FIELD: APP ID AS SEEN ON MOENGAGE DASHBOARD APP SETTINGS PAGE */}
```
## Now
```text wrap theme={null}
// this is the instance of the application class and "XXXXXXXXXXX" is the Workspace ID from the dashboard.
MoEngage moEngage = new MoEngage.Builder(this, "XXXXXXXXXXX")
.build();
MoEngage.initialise(moEngage);
```
# Adding Lifecycle Callbacks
## Then
```text wrap theme={null}
MoEHelper.getInstance(getApplicationContext()).autoIntegrate(this);
```
## Now
Remove the above line from your Application class.
# Adding meta tags to manifest for push notifications
## Then
```text wrap theme={null}
{/* MANDATORY FIELD: SENDER ID , i.e. THE PROJECT NUMBER AS MENTIONED ON GOOGLE CLOUD CONSOLE PROJECTS PAGE */}
{/* MANDATORY FIELD: THE NOTIFICATION SMALL ICON WHICH WILL BE USED TO SET TO NOTIFICATIONS POSTED */}
{/* MANDATORY FIELD: THE NOTIFICATION LARGE ICON WHICH WILL BE USED TO SET TO NOTIFICATIONS POSTED */}
```
## Now
```text wrap theme={null}
MoEngage moEngage =
new MoEngage.Builder(this, "XXXXXXXXXX")
.setSenderId("xxxxxxx") // required only if you are using GCM.
.setNotificationSmallIcon(R.drawable.icon)
.setNotificationLargeIcon(R.drawable.ic_launcher)
.build();
MoEngage.initialise(moEngage);
```
# Adding meta tags to Skip GCM Registration
## Then
```text wrap theme={null}
```
## Now
```text wrap theme={null}
new MoEngage.Builder(this, "XXXXXXXXXX")
.setSenderId("xxxxxxx") // required only if you are using GCM.
.setNotificationSmallIcon(R.drawable.icon)
.setNotificationLargeIcon(R.drawable.ic_launcher)
.optOutTokenRegistration()
.build();
MoEngage.initialise(moEngage);
```
# Showing Multiple Notifications at one go
## Then
```text wrap theme={null}
{/* OPTIONAL FIELD: THE NOTIFICATION TYPE WHICH WILL BE USED, SINGLE OR MULTIPLE. DEFAULT BEHAVIOR IS SINGLE */}
```
## Now
```text wrap theme={null}
MoEngage moEngage =
new MoEngage.Builder(this, "XXXXXXXXXX")
.setSenderId("xxxxxxx") // required only if you are using GCM.
.setNotificationSmallIcon(R.drawable.icon)
.setNotificationLargeIcon(R.drawable.ic_launcher)
.setNotificationType(R.integer.notification_type_multiple)
.build();
MoEngage.initialise(moEngage);
```
# Setting notification Color
## Then
```text wrap theme={null}
[hex code of color]
```
## Now
```text wrap theme={null}
MoEngage moEngage =
new MoEngage.Builder(this, "XXXXXXXXXX")
.setSenderId("xxxxxxx") // required only if you are using GCM.
.setNotificationSmallIcon(R.drawable.icon)
.setNotificationLargeIcon(R.drawable.ic_launcher)
.setNotificationColor(R.color.colorAccent)
.build();
MoEngage.initialise(moEngage);
```
# Opt-out BackStack creation for Notification
## Then
```text wrap theme={null}
PushManager.getInstance().optoutBackStackBuilder(true);
```
## Now
```text wrap theme={null}
MoEngage moEngage =
new MoEngage.Builder(this, "XXXXXXXXX")
.optOutBackStackBuilder()
.build();
MoEngage.initialise(moEngage);
```
# Opt-out activity tracking
## Then
```text wrap theme={null}
```
## Now
```text wrap theme={null}
ArrayList trackingOptOut = new ArrayList<>();
trackingOptOut.add(SettingsActivity.class);
MoEngage moEngage =
new MoEngage.Builder(this, "XXXXXXXXXXX")
.setTrackingOptOut(trackingOptOut)
.build();
MoEngage.initialise(moEngage);
```
# Opt-out NavBar
## Then
```text wrap theme={null}
InAppManager.getInstance().optOutNavBar(this,true);
```
## Now
```text wrap theme={null}
MoEngage moEngage =
new MoEngage.Builder(this, "XXXXXXXXXX")
.optOutNavBar()
.build();
MoEngage.initialise(moEngage);
```
# Opt-out Activity from showing InApp
## Then
```text wrap theme={null}
```
## Now
```text wrap theme={null}
ArrayList inAppOptOut = new ArrayList<>();
inAppOptOut.add(MainActivity.class);
MoEngage moEngage =
new MoEngage.Builder(this, "XXXXXXXXXX")
.setInAppOptOut(inAppOptOut)
.build();
MoEngage.initialise(moEngage);
```
# Opt-out of MoEngage extras in Deeplink
## Then
```text wrap theme={null}
PushManager.getInstance().optOutMoEngageExtras(true);
```
## Now
```text wrap theme={null}
MoEngage moEngage =
new MoEngage.Builder(this, "XXXXXXXXXXXX")
.optOutMoEngageExtras()
.build();
MoEngage.initialise(moEngage);
```
# Updating to 11.x.xx from 10.x.xx
Source: https://moengage.com/docs/developer-guide/android-sdk/migration/updating-to-11xxx-from-10xxx
Migrate to MoEngage Android SDK 11.x.xx with updated APIs, Java 8 support, and modular geofence setup.
# Behavioral Changes
* Target SDK version bumped to API level 29
* Starting SDK version `11.0.00` Geofence is not included when `moe-android-sdk` is added in the application. Refer to the [Location triggered Push](https://developers.moengage.com/hc/en-us/articles/4403443036564) documentation to integrate and use the Geofence module.
* SDK has been re-packaged to have clear separation for internal files and exposed classes. Any class with the package name `com.moengage.*.internal.*` should not be used. APIs in these classes can be updated/removed without prior notice and should not be used by integrating applications.
* InApp is no longer shown via Activity lifecycle callbacks. To show in-app `showInApp()` should be called in the Activity or Fragment. Refer to the [In-App NATIV](https://developers.moengage.com/hc/en-us/articles/4403652537492) documentation for more details.
* Source and Target Compatibility Updated to Java 8. Enable Java 8 in your application if not done already.
* In this release, we have updated the hosts used by the SDK. In case you have whitelisted MoEngage endpoints in the network configuration of your application update the endpoints. Refer to the [Network Security Configuration](https://developers.moengage.com/hc/en-us/articles/4401984811796) to know more.
* SDK no longer tracks location by default.
# Update Removed APIs
In version `11.0.00`, we have removed many of the APIs which were long deprecated. If you are still using the deprecated APIs you have to update to the new APIs. Below is a table mapping the equivalents of the removed APIs. Some of the APIs might not have an alternate API as the functionality might have been handled internally or no longer supported.
| Then | Now |
| ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
| PushHandler#handlePushPayload (Context, Bundle) | MoEFireBaseHelper#passPushPayload (Context, Bundle) |
| PushHandler#handlePushPayload (Context, Map) | MoEFireBaseHelper#passPushPayload (Context, Map) |
| MoEFireBaseHelper#setOnNonMoEngage PushReceivedListener (OnNonMoEngagePushReceivedListener) | MoEFireBaseHelper#add EventListener(FirebaseEventListener) |
| PushManager#refreshToken(Context, String) | MoEFireBaseHelper#passPushToken (Context, String) |
| PushManager#setMessageListener(Object) | MoEPushHelper#setMessageListener (PushMessageListener) |
| MoEngageNotificationUtils#isFrom MoEngagePlatform(Context, Bundle) | MoEPushHelper#isFromMoEngagePlatform (Bundle) |
| MoEngageNotificationUtils#isFromMoEngagePlatform (Context, Map) | MoEPushHelper#isFromMoEngagePlatform (Map) |
| PushMessageListener#onCreateNotification(Context, Bundle, ConfigurationProvider) | PushMessageListener#onCreateNotification (Context, NotificationPayload) |
| PushManager#getPushHandler() | NA |
| MoEPushHelper#handlePushPayload (Context, Map) | Use `passPushPayload()` of each push module. |
| MoEPushHelper#handlePushPayload (Context, Bundle) | Use `passPushPayload()` of each push module. |
| MoEngage.Builder#optOutBackgroundSync() | MoEngage.Builder#configureDataSync (DataSyncConfig) |
| MoEngage.Builder.optOutPeriodicFlush() | MoEngage.Builder#configureDataSync (DataSyncConfig) |
| MoEngage.Builder.setFlushInterval(long interval) | MoEngage.Builder#configureDataSync (DataSyncConfig) |
| MoEngage.Builder.optOutLocationTracking() | NA |
| MoEngage.Builder.optOutGeofenceBackgroundSync() | MoEngage.Builder#configureGeofence (GeofenceConfig) |
| MoEngage.Builder.enableBackgroundLocationFetch() | NA |
| MoEngage.Builder.enableLocationServices() | MoEngage.Builder#configureGeofence (GeofenceConfig) |
| MoEngage.Builder.optOutRealTime TriggerBackgroundSync() | MoEngage.Builder#configureRealTimeTrigger (RttConfig) |
| MoEngage.Builder.redirectDataToRegion (DATA\_REGION) | MoEngage.Builder#setDataCenter (DataCenter) |
| MoEngage.Builder#optOutDefaultInAppDisplay() | NA |
| MoEngage.Builder#optOutActivityTracking(List) | MoEngage.Builder#configureTrackingOptOut (TrackingOptOutConfig) |
| MoEngage.Builder#optOutGAIDCollection() | MoEngage.Builder#configureTrackingOptOut (TrackingOptOutConfig) |
| MoEngage.Builder#optOutAndroidIdCollection() | MoEngage.Builder#configureTrackingOptOut (TrackingOptOutConfig) |
| MoEngage.Builder#optOutCarrierNameCollection() | MoEngage.Builder#configureTrackingOptOut (TrackingOptOutConfig) |
| MoEngage.Builder#optOutDeviceAttributeCollection() | MoEngage.Builder#configureTrackingOptOut (TrackingOptOutConfig) |
| MoEngage.Builder.setNotificationType() | MoEngage.Builder#configure NotificationMetaData(NotificationConfig) |
| MoEngage.Builder#setDateFormatForCard (String) | MoEngage.Builder#configureCards (CardConfig) |
| MoEngage.Builder#setEmptyInboxImageForCard (int) | MoEngage.Builder#configureCards (CardConfig) |
| MoEngage.Builder#setPlaceHolderImageForCard (int) | MoEngage.Builder#configureCards (CardConfig) |
| MoEHelper#trackEvent(String) | MoEHelper#trackEvent (String, Properties) |
| MoEHelper#trackEvent(String, JSONObject) | MoEHelper#trackEvent(String, Properties) |
| MoEHelper#trackEvent(String, Map) | MoEHelper#trackEvent(String, Properties) |
| MoEHelper#setUserAttribute(String, String, String) | MoEHelper#setUserAttribute(String, Date) |
| MoEHelper#setGender(String) | MoEHelper#setGender(UserGender) |
| MoEHelper#fetchDeviceTriggersIfRequired() | MoERttHelper#syncTriggers(Context) |
| MoEHelper#registerAppBackgroundListener (OnAppBackgroundListener) | MoECallbacks#addAppBackgroundListener (OnAppBackgroundListener) |
| MoEHelper#unregisterAppBackgroundListener() | MoECallbacks#removeAppBackgroundListener (OnAppBackgroundListener) |
| MoEHelper#setOnLogoutCompleteListener (OnLogoutCompleteListener) | MoECallbacks#addLogoutCompleteListener (OnLogoutCompleteListener) |
| MoEHelper#removeLogoutCompleteListener() | MoECallbacks#removeLogoutListener (OnLogoutCompleteListener) |
# APIs Deprecated in 11.0.00
In version `11.0.00` we have deprecated a few APIs to improve performance and better support in the future. Below is the list of deprecated APIs and their alternatives, please update to the latest methods.
| Then | Now |
| --------------------------------------------------------------- | --------------------------------------------------------------------- |
| MoEngage.Builder #setNotificationLargeIcon(int) | MoEngage.Builder#configureNotificationMetaData (NotificationConfig) |
| MoEngage.Builder#setNotificationSmallIcon(int) | MoEngage.Builder#configureNotificationMetaData (NotificationConfig) |
| MoEngage.Builder#setNotificationColor(int) | MoEngage.Builder#configureNotificationMetaData (NotificationConfig) |
| MoEngage.Builder#setNotificationTone(String) | MoEngage.Builder#configureNotificationMetaData (NotificationConfig) |
| MoEngage.Builder#enableMultiple NotificationInDrawer(boolean) | MoEngage.Builder#configureNotificationMetaData (NotificationConfig) |
| MoEngage.Builder#optOutBackStackBuilder() | MoEngage.Builder#configureNotificationMetaData (NotificationConfig) |
| MoEngage.Builder#optOutNotificationLargeIcon() | MoEngage.Builder#configureNotificationMetaData (NotificationConfig) |
| MoEngage.Builder#enableLogsForSignedBuild() | MoEngage.Builder#configureLogs (LogConfig) |
| MoEngage.Builder#enableLogs(int) | MoEngage.Builder#configureLogs (LogConfig) |
| MoEngage.Builder#enablePushKit TokenRegistration() | MoEngage.Builder#configurePushKit (PushKitConfig) |
| MoEngage.Builder#enableSegmentIntegration() | MoEngage.Builder#enablePartnerIntegration (IntegrationPartner) |
| MoEHelper#setUniqueId(double) | MoEHelper#setUniqueId(String) |
| MoEHelper#setUniqueId(float) | MoEHelper#setUniqueId(String) |
| MoEHelper#setUniqueId(int) | MoEHelper#setUniqueId(String) |
| MoEHelper#setUniqueId(long) | MoEHelper#setUniqueId(String) |
| MoEHelper#setAlias(double) | MoEHelper#setAlias(String) |
| MoEHelper#setAlias(float) | MoEHelper#setAlias(String) |
| MoEHelper#setAlias(int) | MoEHelper#setAlias(String) |
# Updating to 12.x.xx from 11.x.xx
Source: https://moengage.com/docs/developer-guide/android-sdk/migration/updating-to-12xxx-from-11xxx
Migrate to MoEngage Android SDK 12.x.xx with updated build configs and modularized InApp and Push.
# Behavioral Changes
* Build Configuration updated to the following
* compileSdk 30
* minSdk 21
* targetSdk 30
* Starting from SDK version 12.0.00 following features are not integrated by default when adding moe-android-sdk as a dependency. If you are using these features refer to their respective integration document and make update the dependencies.
* [InApp](https://developers.moengage.com/hc/en-us/articles/4403652537492-In-App-NATIV)
* [Push Amplification](https://developers.moengage.com/hc/en-us/articles/4650416409876)
* [Device Trigger](https://developers.moengage.com/hc/en-us/articles/4649815712532)
* APIs to initialize the SDK now throws [*IllegalStateException*](https://developer.android.com/reference/java/lang/IllegalStateException) in case App-id is null or empty.
## External Library Version updates
* androidx.core:core 1.3.1 --> 1.6.0
* androidx.appcompat:appcompat 1.2.0 --> 1.3.1
* androidx.lifecycle:lifecycle-process 2.2.0 --> 2.4.0
* com.google.firebase:firebase-messaging 22.0.0 --> 23.0.0
* Kotlin Standard Library 1.4.20 --> 1.6.0
# Update Removed initialization APIs
| Then | Now |
| --------------------------------------------------------- | --------------------------------------------------------------------- |
| MoEngage.Builder#optOutInAppOnActivity() | MoEngage.Builder#configureInApps (InAppConfig) |
| MoEngage.Builder#optOutNavBar() | MoEngage.Builder#configureInApps (InAppConfig) |
| MoEngage.Builder#optOutBackStackBuilder() | MoEngage.Builder#configureNotificationMetaData (NotificationConfig) |
| MoEngage.Builder#enableMultipleNotificationInDrawer() | MoEngage.Builder#configureNotificationMetaData (NotificationConfig) |
| MoEngage.Builder#setNotificationTone() | MoEngage.Builder#configureNotificationMetaData (NotificationConfig) |
| MoEngage.Builder#setNotificationColor() | MoEngage.Builder#configureNotificationMetaData (NotificationConfig) |
| MoEngage.Builder#setNotificationSmallIcon() | MoEngage.Builder#configureNotificationMetaData (NotificationConfig) |
| MoEngage.Builder#setNotificationLargeIcon() | MoEngage.Builder#configureNotificationMetaData (NotificationConfig) |
| MoEngage.Builder#optOutNotificationLargeIcon() | MoEngage.Builder#configureNotificationMetaData (NotificationConfig) |
| MoEngage.Builder#optOutTokenRegistration() | MoEngage.Builder#configureFcm (FcmConfig) |
| MoEngage.Builder#setSenderId() | Support removed for sender id |
| MoEngage.Builder#configureMiPush(String, String, Boolean) | MoEngage.Builder#configureMiPush (MiPushConfig) |
| MoEngage.Builder#enablePushKitTokenRegistration() | MoEngage.Builder#configurePushKit (PushKitConfig) |
| MoEngage.Builder#enableLogsForSignedBuild() | MoEngage.Builder#configureLogs (LogConfig) |
| MoEngage.Builder#enableLogs() | MoEngage.Builder#configureLogs (LogConfig) |
| MoEngage.Builder#enableSegmentIntegration() | MoEngage.Builder#enablePartnerIntegration (IntegrationPartner) |
# Update removed methods in the core module
| Then | Now |
| ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| MoECallbacks#addLogoutCompleteListener (OnLogoutCompleteListener) | MoECoreHelper#addLogoutCompleteListener (OnLogoutCompleteListener) |
| MoECallbacks#removeLogoutListener (OnLogoutCompleteListener) | MoECoreHelper#removeLogoutListener (OnLogoutCompleteListener) |
| MoECallbacks#addAppBackgroundListener (AppBackgroundListener) | MoECoreHelper#addAppBackgroundListener (AppBackgroundListener) |
| MoECallbacks#removeAppBackgroundListener (AppBackgroundListener) | MoECoreHelper#removeAppBackgroundListener (AppBackgroundListener) |
| MoEHelper#registerActivityLifecycle() | Support Removed |
| MoEHelper#unregisterLifecycleCallbacks() | Support Removed |
| MoEHelper#registerProcessLifecycleObserver() | Support Removed |
| MoEHelper#unRegisterProcessLifecycleObserver() | Support Removed |
| MoEHelper#trackEvent (String, PayloadBuilder) | MoEAnalyticsHelper#trackEvent (String, Properties) |
| MoEHelper#syncInteractionDataNow() | MoECoreHelper#syncInteractionData() |
| MoEHelper#setAppContext (List) | MoEInAppHelper#setInAppContext (Set) |
| MoEngage#enableSdk(Context) | enableSdk(Context) or MoESdkStateHelper#enableSdk(Context) |
| MoEngage#disableSdk(Context) | disableSdk(Context) or MoESdkStateHelper#disableSdk(Context) |
| MoEngage#optOutDataTracking(Context, boolean) | enableDataTracking(Context)/disableDataTracking(Context) or MoESdkStateHelper#enableDataTracking(Context)/ MoESdkStateHelper#disableDataTracking(Context) |
| MoEngage#optOutPushNotification(Context, boolean) | Support Removed |
| MoEngage#optOutInAppNotification(Context, boolean) | Support Removed |
| MoEngage#initialise(MoEngage, Boolean) | MoEngage#initialiseDefaultIstance (MoEngage, SdkState) |
| MoEngage#initialise(MoEngage) | MoEngage#initialiseDefaultIstance (MoEngage) |
# Changes in Push
* Support for Notification tone dropped
* [*NotificationPayload*](https://moengage.github.io/android-api-reference/pushbase/com.moengage.pushbase.model/-notification-payload/index.html)restructured for easier use.
* Methods removed or replaced
| Then | Now |
| -------------------------------------------------------- | ------------------------------------------------------------- |
| PushMessageListener#onHandleRedirection() | PushMessageListener#onNotificationClick() |
| MoEPushHelper#setMessageListener (PushMessageListener) | MoEPushHelper#registerMessageListener (PushMessageListener) |
## Change in Firebase Messaging
*FirebaseEventListener* removed, instead use the following callbacks
* [*TokenAvailableListener*](https://moengage.github.io/android-api-reference/pushbase/com.moengage.pushbase.listener/-token-available-listener/index.html) for getting the push token whenever it is generated.
* [*NonMoEngagePushListener*](https://moengage.github.io/android-api-reference/moe-push-firebase/com.moengage.firebase.listener/-non-mo-engage-push-listener/index.html) for getting the callback whenever a push is received which is not from MoEngage Server.
* Following methods removed are removed *MoEFireHelper*
* setEventListener(FirebaseEventListener)
* addEventListener(FirebaseEventListener)
Instead, use the methods provided for adding TokenAvailableListener and NonMoEngagePushListener.
## Change in HMS Push Kit
*PushKitEventListener* removed, instead use the following callbacks
* [*TokenAvailableListener*](https://moengage.github.io/android-api-reference/pushbase/com.moengage.pushbase.listener/-token-available-listener/index.html) for getting the push token whenever it is generated.
* [*NonMoEngagePushListener*](https://moengage.github.io/android-api-reference/hms-pushkit/com.moengage.hms.pushkit.listener/-non-mo-engage-push-listener/index.html) for getting the callback whenever a push is received which is not from MoEngage Server.
* Following methods removed are removed *MoEPushKitHelper*
* setEventListener(PushKitEventListener)
* addEventListener(PushKitEventListener)
Refer to the [Configuring HMS Push Kit](https://developers.moengage.com/hc/en-us/articles/4403466195732) documentation to know more about how to set the listener.
# Changes in InApp
InAppMessageListener removed instead use the following callbacks
* *OnClickActionListener* for in-app click callback.
* [*SelfHandledAvailableListener*](https://moengage.github.io/android-api-reference/inapp/com.moengage.inapp.listeners/-self-handled-available-listener/index.html) for callbacks when Self handled campaigns are available.
* [*InAppLifeCycleListener*](https://moengage.github.io/android-api-reference/inapp/com.moengage.inapp.listeners/-in-app-life-cycle-listener/index.html) for in-app lifecycle callbacks like shown, dismiss.
Refer to the [InApp](https://developers.moengage.com/hc/en-us/articles/4403652537492) documentation to know more on how to set the listener.
Methods removed from *MoEInAppHelper*
| Then | Now |
| ------------------------------------------- | ------------------------------------------------------------------------- |
| MoEInAppHelper#getSelfHandledInApp(Context) | MoEInAppHelper#getSelfHandledInApp(Context, SelfHandledAvailableListener) |
# Changes in Inbox
Below are method signature changes
| Then | Now |
| --------------------------------------------------------- | -------------------------------------------------------------- |
| OnMessagesAvailableListener#onMessagesAvailable (List) | OnMessagesAvailableListener#onMessagesAvailable (InboxData) |
| UnClickedCountListener#onCountAvailable (Long) | UnClickedCountListener#onCountAvailable (UnClickedCountData) |
| MoEInboxHelper#fetchMessagesByTag() returns List | MoEInboxHelper#fetchMessagesByTag() returns InboxData |
| MoEInboxHelper#fetchAllMessages() returns List | MoEInboxHelper#fetchAllMessages() returns InboxData |
| MoEInboxHelper#getUnClickedMessagesCount() returns Long | MoEInboxHelper#fetchAllMessages() returns UnClickedCountData |
| OnMessageClickListener#onMessageClick (InboxMessage) | OnMessageClickListener#onMessageClick (MessageClickData) |
# Android 12
Source: https://moengage.com/docs/developer-guide/android-sdk/os-updates/android-12
Review Android 12 behavior changes that affect push notifications and deep links in MoEngage campaigns.
Android 12 is a major version update of the Android Operating System, a yearly release cycle. The major release changes are detailed in the [Android Official Release Notes](https://developer.android.com/about/versions/12/release-notes).
The following are the major behavior changes impacting the MoEngage Platform or MoEngage Android SDK.
The changes are divided into two parts. First, that affects all the applications and the second that affect only the applications targeting Android 12.
# Behavior changes: all apps
The following behavior changes apply to all apps running on Android 12, regardless of **targetSdkVersion**.
## Web intent resolution
Android 12 (API level 31) and later, a generic web intent resolves to an activity in your app, only if your app is approved for the specific domain contained in that web intent. If your app is not approved for the domain, the web intent resolves to the user's default browser app instead.
Apps get approval by doing one of the following:
* Verify the domain using the [Android App Links](https://developer.android.com/about/versions/12/web-intent-resolution#android-app-links).
* Manually [associate your app with the domain](https://developer.android.com/about/versions/12/web-intent-resolution#request-user-associate-app-with-domain) in system settings by the user.
For more information, refer to [Android Web Intent documentation](https://developer.android.com/about/versions/12/web-intent-resolution).
## How does it affect you?
If you are using **http(s)** deep links in your campaigns (Push/InApp/Cards) and the links are not configured as [App Links](https://developer.android.com/training/app-links) in your application, users would be navigated to the browser on devices running Android 12.
## How to fix it?
MoEngage recommends that you configure App Links in your application. Alternatively, edit the campaigns to update the links, if you already have app schema deep-links (example **example://gizmos**) configured in your application for the same activities.
# Behavior changes: Apps targeting Android 12
The following behavior changes apply exclusively to apps that are targeting Android 12 or later, that is **targetSdkVersion** is set to API level 31 or above.
## Pending intents mutability
If your app targets Android 12, specify the mutability of each [PendingIntent](https://developer.android.com/reference/android/app/PendingIntent) object that your app creates. The additional requirement improves your app security.
For more information, refer to [Android release notes](https://developer.android.com/about/versions/12/behavior-changes-12#pending-intent-mutability).
## How does it affect you?
If your application **targetSdkVersion** is 31 and not updated to the latest version of MoEngage SDK (**11.4.00** or later), push notifications would not be displayed on Android 12 devices.
## How to fix it?
Update to the latest MoEngage SDK (**11.4.00** or later) along with the update of **targetSdkVersion** to API level 31.
## Custom notifications
Android 12 changes the appearance and behavior of fully [custom notifications](https://developer.android.com/training/notify-user/custom-notification). Previous versions of custom notifications used the entire notification area and provide layouts and styles. This resulted in anti-patterns confusing users or cause layout compatibility issues on different devices.
For apps targeting Android 12, notifications with custom content views will no longer use the full notification area instead, the system defined standard template is applied.
## How does it affect you?
If your application **targetSdkVersion** is 31 and the **rich-notification** version is either **2.2.01** or previous versions, templates are displayed as truncated or broken on Android 12 devices.
## How to fix it?
Update the rich-notification version to the latest version(2.3.00 or later). MoEngage has temporarily disabled templates when the application **targetSdkVersion** is 31 and the device is running Android 12.
MoEngage support for templates with the new specifications for Android 12 will be available in future releases.
# Changes in backup and restore
Backup and restore functionality is changed for apps that run on and target Android 12 (API level 31). Android backup and restore have two forms:
* **Cloud backups:** User data is stored in the Google Drive of the user for restoring data on that device or a new device.
* **Device-to-device (D2D) transfers:** User data is sent directly to the new device of the user from the older device of the user by using a cable.
For more information on how data is backed up and restored, refer to [Back up user data with Auto Backup](https://developer.android.com/guide/topics/data/autobackup) and [Back up key-value pairs with Android Backup Service](https://developer.android.com/guide/topics/data/keyvaluebackup).
## D2D transfer functionality changes
For apps running on and targeting Android 12 and higher:
* Specifying **android:allowBackup:"false"** does disable backups to Google Drive, but doesn’t disable D2D transfers for the app.
* [Specifying include and exclude rules](https://developer.android.com/guide/topics/data/autobackup#IncludingFiles) with the XML configuration mechanism no longer affects D2D transfers, though it still affects Google Drive backups. To specify rules for D2D transfers, you must use the new configuration format.
# New include and exclude format
Apps running on and targeting Android 12 and later use a different XML configuration format. The new format differentiates between Google Drive backup and D2D transfer by specifying include and exclude rules separately for cloud backups and for D2D transfer.
Optionally, you can also use the new format to specify rules for backup, in which case the old configuration is ignored.
```XML XML wrap theme={null}
...
...
...
...
...
...
```
## How does it affect you?
If your application **targetSdkVersion** is 31, the backup includes MoEngage SDK identifiers backed up and restored after re-install. The restoration of the identifier results in your data being corrupted and the user not being reachable using push notifications.
## How to fix it?
Ensure to add the configuration in the updated format. For more information, refer to [Exclude MoEngage Storage File from Auto Backup](/developer-guide/android-sdk/sdk-integration/basic-integration/exclude-moengage-storage-file-from-auto-backup).
While updating the SDK version, please check the compatibility of additional modules and update them accordingly.
# SDK Performance
Source: https://moengage.com/docs/developer-guide/android-sdk/performance/sdk-performance
Review MoEngage Android SDK performance benchmarks for initialization time, memory, and battery impact.
Keeping the SDK performant is of paramount importance to us and we constantly try to improve the performance with each release. Performance includes the time taken to initialize the SDK, within how many milliseconds a method returns, the memory footprint of the SDK when the application is running, battery drainage due to background work, and so on.
# SDK Initialization time
We recommend initializing the SDK on the Main Thread in the [*onCreate()*](https://developer.android.com/reference/android/app/Application#onCreate\(\)) of your Application class, hence it is important for us to keep the initialization simple and fast to ensure it does not affect the application start-up time as start-up time is important for a good user experience.\
The initialization is approximately around 1-5 milliseconds on average. We have tested this on various OEMs and the results seem to be consistent.\
Refer to the below table for more details:
| Device | Device Details | Time (in milliseconds) |
| -------------- | --------------------- | ---------------------- |
| Google Pixel 2 | Android 11 4 GB RAM | 0.878593 |
| Samsung A51 | Android 10 6 GB RAM | 1.95223 |
| One Plus 7 | Android 10 6 GB RAM | 0.365365 |
| Mi Y9 | Android 9 4 GB RAM | 2.658177 |
| Vivo Y51A | Android 7 3 GB RAM | 1.667916 |
| Pixel 4a | Android 12 6 GB RAM | 0.446823 |
| Tab A7 | Andriod 11 3 GB RAM | 0.889791 |
| Mi K20 Pro | Android 10 6 GB RAM | 0.553854 |
# SDK Size Impact
Source: https://moengage.com/docs/developer-guide/android-sdk/performance/sdk-size-impact
Review the APK and App Bundle size impact of each MoEngage Android SDK artifact.
SDK size is one of the important considerations for us as the inclusion of SDKs can significantly influence the final APK / App Bundle size, affecting the user experience and download time. So, we always aim to keep the impact as low as possible on the final APK / App Bundle size.
# MoEngage SDKs
Refer to the below table for details about the impact on APK / App Bundle size due to different MoEngage artifacts.
Version Catalog (used for size impact calculation): ***3.2.2***
| Artifact Id | Version | Size Impact (Approx. Kilobytes) |
| -------------------------------------------------------------- | -------- | ------------------------------- |
| cards-core | 1.6.0 | 33 KB |
| cards-ui | 1.6.1 | 277 KB |
| encrypted-storage | 1.3.0 | 1 KB |
| geofence | 3.4.0 | 27 KB |
| hms-pushkit | 4.7.0 | 129 KB |
| inapp | 7.1.1 | 148 KB |
| inbox-core | 2.6.0 | 7 KB |
| inbox-ui | 2.6.0 | 171 KB |
| integration-verifier | 4.4.0 | 62 KB |
| moe-android-sdk | 12.10.02 | 227 KB |
| moengage-segment-kotlin-destination (includes moe-android-sdk) | 1.5.0 | 227 KB |
| push-amp | 4.6.0 | 6 KB |
| push-amp-plus | 6.6.0 | 7 KB |
| realtime-trigger | 2.6.0 | 26 KB |
| rich-notification | 4.7.2 | 155 KB |
| security | 2.6.0 | 2 KB |
# External SDKs
There are some external dependencies that the Application must include while using the MoEngage SDK. Refer to the below table to get the impact due to the external dependencies.
| Dependency | Version | Size Impact (Approx. Kilobytes) |
| ------------------ | --------- | ------------------------------- |
| Firebase Messaging | 23.1.2 | 158 KB |
| HMS Push SDK | 6.3.0.304 | 443 KB |
| MI Push SDK | 5.1.1 | 222 KB |
# Callbacks and Customisation
Source: https://moengage.com/docs/developer-guide/android-sdk/push/advanced/callbacks-and-customisation
Customize push notification display and behavior in your Android app using the MoEngage PushMessageListener.
**Advanced Customization**
Support for advanced use cases where the application wants to customize or alter the default behavior of the MoEngage SDK.
MoEngage SDK allows the client application to optionally customize the notification display and extend/customize the behavior of the notification. Some of the possible customizations are deciding whether to show a notification or not, and tweaking the *NotificationCompat.Builder* object, etc. To do so you need to extend a class called [PushMessageListener](https://moengage.github.io/android-api-reference/pushbase/com.moengage.pushbase.push/\[android-jvm]-push-message-listener/index.html) provided by the MoEngage SDK and pass on the instance of this class to the MoEngage SDK. Once you have done this you can override the default implementation as per the requirement. Let's look at the above steps in more detail.
# Extending PushMessageListener
The first thing required to customize the notification is creating a class that extends [*PushMessageListener*](https://moengage.github.io/android-api-reference/pushbase/com.moengage.pushbase.push/\[android-jvm]-push-message-listener/index.html). We will call this class **CustomPushMessageListener** (only for illustration purposes you can have any class name you want). The barebones of this class would look something like below.
```kotlin Kotlin wrap theme={null}
class CustomPushMessageListener : PushMessageListener() {
}
```
```java Java theme={null}
public class CustomPushMessageListener extends PushMessageListener {
}
```
# Passing the instance of CustomPushMessageListener to MoEngage SDK
You need to pass on the instance of *CustomPushMessageListener* to the MoEngage SDK in the *onCreate()* of the *Application* class. You need to pass the instance to [MoEPushHelper.getInstance().registerMessageListener()](https://moengage.github.io/android-api-reference/pushbase/com.moengage.pushbase/\[android-jvm]-mo-e-push-helper/register-message-listener.html) API. A sample call is described.
```kotlin Kotlin wrap theme={null}
MoEPushHelper.getInstance().registerMessageListener(CustomPushMessageListener())
```
```java Java wrap theme={null}
MoEPushHelper.getInstance().registerMessageListener(new CustomPushMessageListener());
```
# Optionally control notification display
To control whether a notification is shown to the user or not, you need to override [isNotificationRequired()](https://moengage.github.io/android-api-reference/pushbase/com.moengage.pushbase.push/\[android-jvm]-push-message-listener/is-notification-required.html) in the *CustomPushMessageListener* class created above.\
If you intend to show the notification overridden, the implementation should return **true** or **false**.
The structure for implementation is described as follows:\
If this method returns **false,** this notification is discarded by the SDK; that is, the notification will not be displayed on the device, and the impression will not be tracked.
```kotlin Kotlin wrap theme={null}
class CustomPushMessageListener : PushMessageListener() {
// decide whether notification should be shown or not.
override fun isNotificationRequired(context: Context, payload: Bundle): Boolean {
// app's logic to decide whether to show notification or not.
// for illustration purpose reading notification preference from SharedPreferences and
// deciding whether to show notification or not. Logic can vary from application to
// application.
val preferences = context.getSharedPreferences("demoapp", 0)
return preferences.getBoolean("notification_preference", true)
}
}
```
```java Java wrap theme={null}
public class CustomPushMessageListener extends PushMessageListener {
// decide whether a notification should be shown or not.
@Override public boolean isNotificationRequired(Context context, Bundle payload) {
// app's logic to decide whether to show a notification or not.
//For illustration purposes reading notification preference from SharedPreferences and
// deciding whether to show a notification or not. Logic can vary from application to
// application.
SharedPreferences preferences = context.getSharedPreferences("demoapp", 0);
return preferences.getBoolean("notification_preference", true);
}
}
```
For more information, refer to [API Reference](https://moengage.github.io/android-api-reference/pushbase/com.moengage.pushbase.push/\[android-jvm]-push-message-listener/is-notification-required.html).
# Notification Received Callback
To receive a callback whenever a push is received, override the [onNotificationReceived()](https://moengage.github.io/android-api-reference/pushbase/com.moengage.pushbase.push/\[android-jvm]-push-message-listener/on-notification-received.html) in the *CustomPushMessageListener* class.
```kotlin Kotlin wrap theme={null}
class CustomPushMessageListener : PushMessageListener() {
override fun onNotificationReceived(context: Context, payload: Bundle) {
super.onNotificationReceived(context, payload)
//callback for push notification received.
}
}
```
```java Java wrap theme={null}
public class CustomPushMessageListener extends PushMessageListener {
@Override public void onNotificationReceived(Context context, Bundle payload) {
super.onNotificationReceived(context, payload);
//callback for push notification received.
}
}
```
# Notification Clicked Callback
To receive a callback whenever a push is clicked, override the [onNotificationClicked()](https://moengage.github.io/android-api-reference/pushbase/com.moengage.pushbase.push/\[android-jvm]-push-message-listener/on-notification-click.html) in the *CustomPushMessageListener* class created as described in the Notification Received Callback.\
This method doubles as a callback and can be used for handling redirection. If you want to handle redirection on notification, click the method should return true, or else false.
```kotlin Kotlin wrap theme={null}
class CustomPushMessageListener : PushMessageListener() {
override fun onNotificationClicked(activity: Activity, payload: Bundle) {
// If you want to handle redirection on notification, click the method should return true, or else false.
return false
}
}
```
```java Java wrap theme={null}
public class CustomPushMessageListener extends PushMessageListener {
@Override public void onNotificationClicked(Activity activity, Bundle payload) {
// If you want to handle redirection on notification, click the method should return true, or else false.
return false;
}
}
```
# Notification Cleared Callback
To receive a callback whenever a push is cleared, override the [onNotificationCleared()](https://moengage.github.io/android-api-reference/pushbase/com.moengage.pushbase.push/\[android-jvm]-push-message-listener/on-notification-cleared.html) in the *CustomPushMessageListener* class created above.
```kotlin Kotlin wrap theme={null}
public class CustomPushMessageListener extends PushMessageListener {
@Override public void onNotificationCleared(Context context, Bundle payload) {
super.onNotificationCleared(context, payload);
// callback for notification cleared.
}
}
```
```java Java wrap theme={null}
public class CustomPushMessageListener extends PushMessageListener {
@Override public void onNotificationCleared(Context context, Bundle payload) {
super.onNotificationCleared(context, payload);
// callback for notification cleared.
}
}
```
# Custom Action on Action Button Click
To use a custom action on the Action Button click override the [handleCustomAction()](https://moengage.github.io/android-api-reference/pushbase/com.moengage.pushbase.push/\[android-jvm]-push-message-listener/handle-custom-action.html) in the *CustomPushMessageListener* class created above.
```kotlin Kotlin wrap theme={null}
class CustomPushMessageListener : PushMessageListener() {
override fun handleCustomAction(context: Context, payload: String) {
super.handleCustomAction(context, payload)
// callback for notification custom action
}
}
```
```java Java wrap theme={null}
public class CustomPushMessageListener extends PushMessageListener {
@Override public void handleCustomAction(Context context, String payload) {
super.handleCustomAction(context, payload);
// callback for notification custom action
}
}
```
# Customize Notification
To further customize the notification object, override the [customizeNotification()](https://moengage.github.io/android-api-reference/pushbase/com.moengage.pushbase.push/\[android-jvm]-push-message-listener/customize-notification.html). This allows for additional settings to be added or modified, such as vibration patterns/LED colors, etc. It is important to note that the super method should be called before adding any customizations to ensure that the default settings are applied.
```kotlin Kotlin wrap theme={null}
class CustomPushMessageListener : PushMessageListener() {
override fun customizeNotification(notification: Notification, context: Context, payload: Bundle) {
super.customizeNotification(notification, context, payload)
// You can customize the `notification` object here
}
}
```
```java Java wrap theme={null}
public class CustomPushMessageListener extends PushMessageListener {
@Override public void customizeNotification(Notification notification, Context context, Bundle payload) {
super.customizeNotification(notification, context, payload);
// You can customize the `notification` object here
}
}
```
# Customize Notification Builder
The SDK provides the [customizeNotificationBuilder()](https://moengage.github.io/android-api-reference/pushbase/com.moengage.pushbase.push/\[android-jvm]-push-message-listener/customize-notification-builder.html) callback to customize the notification builder object as needed. This feature allows developers to update various properties of the notification builder, such as the channel ID, the auto-dismiss time, etc. It is important to note that the super method should be called before adding any customizations to ensure that the default settings are applied.
```kotlin Kotlin wrap theme={null}
class CustomPushMessageListener : PushMessageListener() {
override fun customizeNotificationBuilder(notificationBuilder: NotificationCompat.Builder, context: Context, notificationPayload: NotificationPayload) {
super.customizeNotificationBuilder(notificationBuilder, context, notificationPayload)
// You can customize the `notificationBuilder` object here
}
}
```
```java Java wrap theme={null}
public class CustomPushMessageListener extends PushMessageListener {
@Override public void customizeNotificationBuilder(Notification notification, Context context, NotificationPayload notificationPayload) {
super.customizeNotificationBuilder(notification, context, payload);
// You can customize the `notificationBuilder` object here
}
}
```
# Self-handled Notification Received Callback
When you use the SDK callback approach by registering a `PushMessageListener`, the MoEngage SDK provides a dedicated method for self-handled notifications.
**SDK version**: The self-handled notification check is supported starting from Android SDK version **14.06.00**.
**Automatic Impression Tracking:** When using this callback, the MoEngage SDK **automatically tracks notification impressions**. You do not need to call `logNotificationReceived`. You only need to handle the display and manually track clicks if a custom UI is shown.
To receive this callback, override `onSelfHandledNotificationReceived()` in your custom listener class:
```kotlin Kotlin wrap theme={null}
class CustomPushMessageListener : PushMessageListener() {
override fun onSelfHandledNotificationReceived(context: Context, payload: Bundle) {
// Impression is already logged by the SDK automatically
// 1. Logic to handle background data (e.g., sync, logout)
// 2. Logic to build and show a custom notification UI (if required)
}
}
```
```java Java wrap theme={null}
public class CustomPushMessageListener extends PushMessageListener {
@Override
public void onSelfHandledNotificationReceived(@NonNull Context context, @NonNull Bundle payload) {
// Impression is already logged by the SDK automatically
// 1. Logic to handle background data (e.g., sync, logout)
// 2. Logic to build and show a custom notification UI (if required)
}
}
```
For more information on the payload structure received in the `Bundle`, refer to [Background Update Templates](https://help.moengage.com/hc/en-us/articles/4415622460948-Push-Templates#h_01HCM6A9GPQWGQBKTQ7504CZAK).
# Push Display Handled by Application
Source: https://moengage.com/docs/developer-guide/android-sdk/push/advanced/push-display-handled-by-application
Handle push notification display yourself and track impressions and clicks with the MoEngage Android SDK.
This section is only required for very advanced use cases where the application needs to handle the push display on the client side. We believe that the customization provided in [Advanced Push Configuration](/android-sdk/push/advanced/callbacks-and-customisation) should solve most of your use-cases. Refer to this document only if your use-cases cannot be satisfied by the customizations provided in the [Advanced Push Configuration](/android-sdk/push/advanced/callbacks-and-customisation) section.
If the push notification display is handled by the application we need some help from the application to show Push Campaign statistics namely Impressions and Clicks.
# Tracking Notification Impressions
The application needs to notify the SDK if a push from the MoEngage Platform is received via Firebase Cloud Messaging(FCM). SDK provides a helper API [isFromMoEngagePlatform()](https://moengage.github.io/android-api-reference/pushbase/com.moengage.pushbase/-mo-e-push-helper/is-from-mo-engage-platform.html) to check whether push is received from the MoEngage Platform or not. Use this API to check if the received push is from the MoEngage Platform and call [logNotificationReceived()](https://moengage.github.io/android-api-reference/pushbase/com.moengage.pushbase/-mo-e-push-helper/log-notification-received.html) to track notification impressions.
```kotlin Kotlin wrap theme={null}
if (MoEPushHelper.getInstance().isFromMoEngagePlatform(pushPayload)) {
MoEPushHelper.getInstance().logNotificationReceived(context, pushPayload)
}
```
```java Java wrap theme={null}
if (MoEPushHelper.getInstance().isFromMoEngagePlatform(pushPayload)) {
MoEPushHelper.getInstance().logNotificationReceived(context, pushPayload);
}
```
# Tracking Notification Clicks
After the notification is clicked application needs to notify the SDK that a notification is clicked for the SDK to track notification clicks. For SDK to track notification clicks and user sessions accurately, ensure:
* The Push payload received from FCM is added as extras to the Pending intent
* The [logNotificationClick()](https://moengage.github.io/android-api-reference/pushbase/com.moengage.pushbase/-mo-e-push-helper/log-notification-click.html) API is called from **onCreate()** of your Activity which is inflated on notification click.
```kotlin Kotlin wrap theme={null}
MoEPushHelper.getInstance().logNotificationClick(applicationContext, intent)
```
```java Java wrap theme={null}
MoEPushHelper.getInstance().logNotificationClick(getApplicationContext(), getIntent());
```
# Background Update Template (Manual Approach)
* **SDK version**: The self-handled notification check is supported starting from Android SDK version **14.06.00**.
* **Payload information**: For more information on the payload structure and available keys, refer to [Background Update Template](https://help.moengage.com/hc/en-us/articles/4415622460948-Push-Templates#h_01HCM6A9GPQWGQBKTQ7504CZAK).
If you are using a custom `PushMessageListener`,MoEngage recommends using the SDK Callback approach where impressions are tracked automatically. Refer to the [Callback Customization](/android-sdk/push/advanced/callbacks-and-customisation#Self-handled-Notification-Received-Callback) section for more details.
Use this approach if you have a custom Firebase Messaging Service and wish to manually intercept the MoEngage payload. When handling manually, **you must manually track notification impressions**.
```kotlin Kotlin wrap theme={null}
override fun onMessageReceived(remoteMessage: RemoteMessage) {
val payload = remoteMessage.data
// Step 1: Check if the push is from MoEngage platform
if (MoEPushHelper.getInstance().isFromMoEngagePlatform(payload)) {
// Step 2: Check if it's a self-handled notification
if (MoEPushHelper.getInstance().isSelfHandledNotification(payload)) {
// Log impression manually for self-handled pushes
MoEPushHelper.getInstance().logNotificationReceived(applicationContext, payload)
// Handle Display of notification or custom logic here
return
} else {
// For non-self-handled, pass to SDK for default handling
MoEFireBaseHelper.getInstance().passPushPayload(applicationContext, payload)
}
}
}
```
```java Java wrap theme={null}
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Map payload = remoteMessage.getData();
// Step 1: Check if the push is from MoEngage platform
if (MoEPushHelper.getInstance().isFromMoEngagePlatform(payload)) {
// Step 2: Check if it's a self-handled notification
if (MoEPushHelper.getInstance().isSelfHandledNotification(payload)) {
// Log impression manually for self-handled pushes
MoEPushHelper.getInstance().logNotificationReceived(getApplicationContext(), payload);
// Handle Display of notification or custom logic here
return;
} else {
// For non-self-handled, pass to SDK for default handling
MoEFireBaseHelper.getInstance().passPushPayload(getApplicationContext(), payload);
}
}
}
```
# Callback for push delivered by Push Amp
Push-Amp notification is not delivered via FCM, it is delivered directly via MoEngage. You need to set up a callback for receiving payload for messages/campaigns.
### Steps:
1. Setup a callback for notification received. For more information, refer to the [notification received callback documentation](/android-sdk/push/advanced/callbacks-and-customisation).
2. Mark notification as not required. This step is important, if not implemented correctly end-user might end up with two notifications. For more information, refer to the [notification received callback documentation](/android-sdk/push/advanced/callbacks-and-customisation).
In this case, **isNotificationRequired()** should always return false.
# Handling re-direction for push delivered by Push Amp+
Whenever campaigns are delivered using Push Amp+ due to a technical limitation push display cannot be handled by the application. The application gets a callback only once the user clicks on the notification. For more information about how to register for push redirection callback, refer to the [notification clicked callback documentation](/android-sdk/push/advanced/callbacks-and-customisation).
# Related Documents
[MoEngage Andriod Push Handling Samples](https://github.com/moengage/Android-Sample/tree/app_handling_push)
# FCM Authentication
Source: https://moengage.com/docs/developer-guide/android-sdk/push/basic/fcm-authentication
Generate and upload an FCM private key to the MoEngage Dashboard for Android push notification delivery.
FCM Authentication is one of the methods to enable sending Push notifications to your app installed on Android devices. The FCM Authentication token is used to authorize server requests to Firebase services. You must generate the authentication token and upload it to the MoEngage Dashboard to send Push notifications to Android users.
You have an app created on the Firebase console.
# Authorize Server Requests to Firebase Services
You can authorize server requests to Firebase services using the Private key. FCM Private key is a service account JSON file that contains the details of the Private key generated for authenticating the service account.
## Steps to Generate a Private Key
Login to the [Firebase console](https://console.firebase.google.com/) with your credentials.
1. Select your project.
2. In the top left pane, click the settings icon beside **Project Overview**.
3. Select **Project settings**.
4. On the **Project Settings** page, navigate to the **Service accounts** tab.
5. Click **Generate new private key**. The language you select doesn't matter because we just download the JSON file. The language you select provides you a sample code if you are implementing the FCM communication. MoEngage already does this for you, so select any language and generate the key.
6. Confirm the same by clicking **Generate Key**. This will generate a JSON file containing the Private key.
7. Download the JSON file and upload it to the MoEngage Dashboard at **Settings** > **Channel** > **Push** > **App Push** > **Android** > **FCM Authentication** > **Private key file (Recommended)**.
8. After the JSON is configured, enable FCM in the [cloud console](https://console.cloud.google.com/apis/library/fcm.googleapis.com).
# Changes in Sending Speed with Private Key Configuration
The Firebase Cloud Messaging API has a default rate limit of 600,000 requests per minute. For more information, refer [here](https://firebase.google.com/support/faq#fcm-depr-rampup). If your account reaches that limit, FCM may drop those notifications with the following error:
| Error | Description |
| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| FCM Message rate exceeded (Quotaexceededforquotametric…) | Sending speed is exceeding the service capacity for your FCM account. Requests beyond serving capacity are rejected to limit the ingress flow rate. This happens because of multiple campaigns being triggered at the same time at high speeds. Consider spacing out campaigns or reducing request limits in the campaign delivery control. |
With the reduction in default FCM API rate limits to 600,000 RPM, we will be changing the maximum allowed throttle speed for Push notifications to 500,000 RPM to ensure a single campaign does not breach the project limit. This change will apply to new and existing campaigns. You may still see drops because of multiple campaigns being triggered together.
To reduce such errors, you can take one of the following approaches depending on your use case:
* **Reduce the campaign sending speed** If you are seeing 'FCM Message rate exceeded' a lot in one-time and periodic campaigns, you might be exceeding the sending capacity beyond your allotted quota. We recommend reducing the request limits in the campaign delivery control to avoid exceeding the quota.\
Because of the default rate limit of 600,000 requests per minute for FCM, we recommend setting it to a lower limit (\~200,000 requests per minute) to accommodate other parallel requests such as event-triggered, business event-triggered, and flow-triggered campaigns.
* **Space out one-time and periodic campaigns**\
If you are seeing 'FCM Message rate exceeded' a lot in one-time and periodic campaigns, you might be scheduling multiple campaigns that are being sent out at the same time, which is increasing your overall sending speed. Therefore, space out one-time and periodic campaigns.
* **Request a rate limit increase from FCM** To check your current limit, go to [Google Cloud console](https://console.cloud.google.com/) > APIs & Services > Firebase Cloud Messaging API > Quotas & System Limits or directly to [FCM Quotas](https://console.cloud.google.com/apis/api/fcm.googleapis.com/quotas) and see the value for Send requests per minute. To request a rate limit increase beyond 600,000 RPM, [contact Firebase Support](https://firebase.google.com/support).
# FAQs
MoEngage SDKs are already compliant with these changes from FCM. You need not update MoEngage SDK when you switch to the Private key authentication mechanism.\
The Server Key or Auth key is a mechanism to authenticate MoEngage to send requests to FCM on behalf of your account. It works at an account level and not at an end-user level or device level.\
When you switch from Server key to Private key, all requests will be transferred to Auth key mechanism with no impact on the end user or device.
Sending messages (including upstream messages) with the FCM XMPP and HTTP legacy APIs was deprecated on June 20, 2023 and **will be removed on June 21, 2024**. Refer to Deprecation of Legacy HTTP API. We strongly recommend the Private key for any request sent to Firebase services as soon as possible.
The FCM Server key mechanism will be deprecated on June 21, 2024. After that, FCM may continue to accept requests from the Server key auth mechanism and not deliver the notifications to the devices or it may start rejecting the API requests altogether. In both cases, **your users will no longer receive notifications through FCM**.
After you save the settings in the MoEngage dashboard, your account will immediately switch to using the new API to send Android push notifications including ongoing campaigns. You will not see any drops in sending push notifications during the transition.
The updated FCM API introduces several improvements, including the adoption of the HTTP v1 protocol and the implementation of short-lived access tokens following the OAuth2 security model, replacing the Server key authentication from the previous version. These tokens enhance security by limiting their usage to approximately one hour, minimising the risk in case they are exposed.
With the Private key Auth mechanism, the Firebase Cloud Messaging API has eliminated the bulk sending mechanism and has a default rate limit of 600,000 requests per minute. For more information, refer [here](https://firebase.google.com/support/faq#fcm-depr-rampup). If your account reaches that limit, FCM may drop those notifications. Given bulk notifications are no longer supported, you may see a reduction in campaign sending speed for bulk campaigns such as one-time and periodic campaigns.\
MoEngage has proactively reduced the maximum allowed throttle speed for Push notifications to 500,000 RPM to ensure a single campaign does not breach the project limit. This change will apply to new and existing campaigns. You may still see drops because of multiple campaigns being triggered together. To learn more, refer to changes in [Sending Speed with Private Key Configuration](/android-sdk/push/basic/fcm-authentication#Steps-to-Generate-a-Private-Key).
When you set the authentication as a Private key, the changes are accepted immediately and will be used for sending subsequent requests.
# Notification Runtime Permissions
Source: https://moengage.com/docs/developer-guide/android-sdk/push/basic/notification-runtime-permissions
Handle Android 13 notification runtime permissions in your app using the MoEngage SDK.
Android 13 (API level 33) and higher supports [runtime permission](https://developer.android.com/guide/topics/permissions/overview#runtime) for sending [non-exempt](https://developer.android.com/develop/ui/views/notifications/notification-permission#exemptions) (including Foreground Services (FGS)) notifications from an app [POST\_NOTIFICATIONS](https://developer.android.com/reference/android/Manifest.permission#POST_NOTIFICATIONS). This change helps users focus on the notifications that are most important to them.
Refer to the [official documentation](https://developer.android.com/develop/ui/views/notifications/notification-permission) for more details.
The below-mentioned APIs are supported starting MoEngage core Android SDK version **12.3.01**
When an application runs on Android 13 and wants to show notifications to the user, it must request the user's notification permission. You have two options: let MoEngage handle permissions for you or handle the notification permission with your code.
* MoEngage handles Notification permission.
* You just have to call a single line of code mentioned on this page.
* You maintain the notification permission logic.
* Notify MoEngage SDK if permission to push notifications is granted.
We recommend you let MoEngage handle push notification permissions.
## Notify SDK of permission result
Once the application requests the user for notification permission notify the SDK of the user response using the below API. *If you are letting MoEngage SDK handle the notification permissions, you should ignore this step.*
```Kotlin Kotlin wrap theme={null}
MoEPushHelper.getInstance().pushPermissionResponse(applicationContext, isGranted)
```
```Java Java wrap theme={null}
MoEPushHelper.getInstance().pushPermissionResponse(applicationContext, isGranted);
```
## Update the Permission request count(optional)
Once the application requests the user for notification permission, update the SDK of the request attempts.
**Why does the SDK require permission attempt count?**
SDK requires the attempt count to accurately track the number of times the permission request was attempted. If the user denies the permission request twice the application/SDK cannot request permission further i.e. if we request permission it would be automatically denied without the user seeing the request dialog. As an SDK we cannot be sure of the number of times the user has denied the permission we try to optimize the calls to request permission based on the attempt count.
```Kotlin Kotlin wrap theme={null}
MoEPushHelper.getInstance().updatePushPermissionRequestCount(applicationContext, requestCount)
```
```Java Java wrap theme={null}
MoEPushHelper.getInstance().updatePushPermissionRequestCount(applicationContext, requestCount);
```
## Setup Notification Channels
If the application has already taken notification permission from the user call the below API to set up Notification Channels for showing push notifications.
```Kotlin Kotlin wrap theme={null}
MoEPushHelper.getInstance().setUpNotificationChannels(context)
```
```Java Java theme={null}
MoEPushHelper.getInstance().setUpNotificationChannels(context);
```
## Let MoEngage SDK handle Notification permission
MoEngage SDK provides helper APIs to show the permission request to the end-user or navigate the user to the settings screen for enabling notifications.
Use the below API to show the permission request dialog to the user.
When using the below API SDK automatically tracks the response, sets up the required notification channel, etc, mentioned above.
```Kotlin Kotlin wrap theme={null}
MoEPushHelper.getInstance().requestPushPermission(activity)
```
```Java Java theme={null}
MoEPushHelper.getInstance().requestPushPermission(activity);
```
## Navigate to Notification Settings (situational/optional)
Use the below API to show navigate the user to the Notification Settings for the application on the device.
*Note*: Below Android 8(API level 26) the user is directed to the Application Info screen of your application.
```Kotlin Kotlin wrap theme={null}
MoEPushHelper.getInstance().navigateToSettings(activity)
```
```Java Java theme={null}
MoEPushHelper.getInstance().navigateToSettings(activity);
```
# Push Configuration
Source: https://moengage.com/docs/developer-guide/android-sdk/push/basic/push-configuration
Configure push notification metadata, icons, and Firebase settings for the MoEngage Android SDK.
# Configuring your MoEngage Account
* Ensure you have configured the [Firebase](https://firebase.google.com/docs/android/setup) application.
* Configure FCM Authorization on the MoEngage Dashboard. For more information, refer to [FCM Authentication](/android-sdk/push/basic/fcm-authentication).
* Ensure you add the keys in both the Test and Live environments.
## Adding metadata for push notification
Metadata regarding the notification is required to show push notifications where the small icon and large icon drawable are mandatory.
For more information about API reference for all the possible options, refer to [NotificationConfig](https://moengage.github.io/android-api-reference/core/com.moengage.core.config/\[android-jvm]-notification-config/index.html).
Use the [*configureNotificationMetaData()*](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]-mo-engage/-builder/configure-notification-meta-data.html) to transfer the configuration to the SDK.
```Kotlin Kotlin wrap theme={null}
val moEngage = MoEngage.Builder(this, "XXXXXXXX")
.configureNotificationMetaData(NotificationConfig(R.drawable.small_icon, R.drawable.large_icon))
.build()
MoEngage.initialiseDefaultInstance(moEngage)
```
```Java Java wrap theme={null}
MoEngage moEngage = new MoEngage.Builder(this, "XXXXXXXXXX")
.configureNotificationMetaData(new NotificationConfig(R.drawable.small_icon, R.drawable.large_icon))
.build();
MoEngage.initialiseDefaultInstance(moEngage);
```
Ensure that the SDK is initialized with the metadata in the *onCreate()* of the Application class for push notifications to work.
**Notification Icon Guidelines**
* The notification small icon should be flat, pictured face on, and must be white on a transparent background.
* If you do not have the large icon configured for the notification, pass -1 to use the system default.
## Notification Small Icon Density, Size
| Density (dp) | Size (px) |
| ------------ | --------- |
| MDPI | 24x24 |
| HDPI | 36x36 |
| XHDPI | 48x48 |
| XXHDPI | 72x72 |
| XXXHDPI | 96x96 |
**Critical**
Please ensure the small icon is set. If the small icon is not set, notifications will not be displayed.
## Stacking Notifications (optional)
By default, Android replaces an old notification with a new one from your application. If you want to show multiple notifications from your app stacked in the notification drawer, you can enable this feature.
To enable stacked notifications, set `isMultipleNotificationInDrawerEnabled` to `true` in the `NotificationConfig` during the SDK initialization.
Refer to the [notification config](https://moengage.github.io/android-api-reference/core/com.moengage.core.config/\[android-jvm]-notification-config/index.html) for additional options.
```Kotlin Kotlin wrap theme={null}
val moEngage = MoEngage.Builder(this, "XXXXXXXX")
.configureNotificationMetaData(NotificationConfig(R.drawable.small_icon, R.drawable.large_icon, R.color.notiColor, true))
.build()
MoEngage.initialiseDefaultInstance(moEngage)
```
```Java Java wrap theme={null}
MoEngage moEngage = new MoEngage.Builder(this, "XXXXXXXXXX")
.configureNotificationMetaData(new NotificationConfig(R.drawable.small_icon, R.drawable.large_icon, R.color.notiColor, true)
.build();
MoEngage.initialiseDefaultInstance(moEngage);
```
If you do not need to set a specific color for the notification, pass -1 to use the system default.
# Push token registration and Display
Source: https://moengage.com/docs/developer-guide/android-sdk/push/basic/push-token-registration-and-display
Set up push token registration and notification display with FCM in the MoEngage Android SDK.
You must complete two mandatory steps to get push notifications working.
1. Push token registration - Registration for Push and generating push tokens.
2. Push display - Receiving the Push payload from Firebase Cloud Messaging(FCM) service and showing the notification on the device.
We recommend you let MoEngage handle both steps as it eases the integration process also MoEngage SDK has a built-in retry mechanism to handle token registration failure due to FCM downtime or network issues.
The SDK also supports cases where your application manages the token registration and receives the notification payload.
To support both use cases, this article is broken down into two major sections:
* **Push token registration and display by MoEngage SDK** - Integration steps required for MoEngage SDK to handle Push token registration and display.
* **Push token registration and payload received by the Application** - Integration steps required for your application to handle Push token registration and receiving notification payload.
First, we will look at the integration steps needed if **MoEngage SDK** handles Push token registration and display. Refer to [this section](#Push-display-for-Non-MoEngage-Payloads-optional) for the integration steps required if **the app** handles push token registration and receives the notification payload.
# Push token registration and display by MoEngage SDK
**Critical**
* When the SDK handles token registration, use firebase-messaging **23.0.0** or higher.
* At any point, your application manifest file should have only one service with intent filter com.google.firebase.MESSAGING\_EVENT. If there is more than one service, only the first service will receive the callback, and MoEngage SDK might never receive the Push Payload, resulting in poor delivery rates.
Add the following code to the manifest file so that MoEngage SDK will receive the notification:
```xml AndroidManifest.xml wrap theme={null}
```
The following steps are optional; use them only if you have the use cases.
## Token Callback - Access to push token (optional)
You might want to get access to the push token that MoEngage registered on behalf of your application. When MoEngage SDK handles push registration, it optionally provides a callback to the application whenever a new token is registered or refreshed.
To get the token callback, implement the [*TokenAvailableListener*](https://moengage.github.io/android-api-reference/pushbase/com.moengage.pushbase.listener/%5Bandroid-jvm%5D-token-available-listener/index.html?query=fun%20interface%20TokenAvailableListener) and register for the callback using [*MoEFireBaseHelper.getInstance().addTokenListener()*](https://moengage.github.io/android-api-reference/moe-push-firebase/com.moengage.firebase/-mo-e-fire-base-helper/add-token-listener.html)\_.
We recommend you add the callbacks in the ***onCreate()*** of the Application class since these callbacks can be triggered even when the application is in the background.
## Push display for Non-MoEngage Payloads (optional)
Your App might want to handle notifications that aren't from MoEngage. If you use the receiver provided by the SDK in your application's manifest file, the SDK provides a callback in case a push payload is received for any other server apart from the MoEngage Platform.
To get a callback, implement the [*NonMoEngagePushListener*](https://moengage.github.io/android-api-reference/moe-push-firebase/com.moengage.firebase.listener/-non-mo-engage-push-listener/index.html) and register for the callback using [*MoEFireBaseHelper.getInstance().addNonMoEngagePushListener*](https://moengage.github.io/android-api-reference/moe-push-firebase/com.moengage.firebase/-mo-e-fire-base-helper/add-non-mo-engage-push-listener.html).
We recommend you add the callbacks in the ***onCreate()*** of the Application class since these callbacks can be triggered even when the application is in the background.
# Push token registration and payload received by the Application
Skip this section if already letting MoEngage SDK handle push token registration and display.
By default, MoEngage SDK attempts to register for a push token. If your application handles push token registration, you must opt out of MoEngage SDK's token registration.
## How to opt-out of MoEngage Push token registration?
To opt out of MoEngage's token registration mechanism, disable token registration using [*configureFCM()*](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]-mo-engage/-builder/configure-fcm.html) API while configuring FCM in the [*MoEngage.Builder*](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]-mo-engage/-builder/index.html) as described
```Kotlin Kotlin wrap theme={null}
val moEngage = MoEngage.Builder(this, "XXXXXXXX")
.configureNotificationMetaData(NotificationConfig(R.drawable.small_icon, R.drawable.large_icon, R.color.notiColor, null, true, isBuildingBackStackEnabled = false, isLargeIconDisplayEnabled = true))
.configureFcm(FcmConfig(false))
.build()
MoEngage.initialiseDefaultInstance(moEngage)
```
```Java Java theme={null}
MoEngage moEngage = new MoEngage.Builder(this, "XXXXXXXXXX")
.configureNotificationMetaData(new NotificationConfig(R.drawable.small_icon, R.drawable.large_icon, R.color.notiColor, "sound", true, true, true))
.configureFcm(new FcmConfig(false))
.build();
MoEngage.initialiseDefaultInstance(moEngage);
```
## Pass the Push Token To MoEngage SDK
Your application must pass the Push Token received from FCM to the MoEngage SDK for the MoEngage platform to send out push notifications to the device.\
Use the [passPushToken()](https://moengage.github.io/android-api-reference/moe-push-firebase/com.moengage.firebase/-mo-e-fire-base-helper/pass-push-token.html) API to pass the push token to the MoEngage SDK.
```Kotlin Kotlin wrap theme={null}
MoEFireBaseHelper.getInstance().passPushToken(applicationContext,token)
```
```Java Java theme={null}
MoEFireBaseHelper.getInstance().passPushToken(getApplicationContext(), token);
```
Ensure the token is passed to MoEngage SDK whenever the push token is refreshed and updated on the application. Passing the token on the application update is important for migration to the MoEngage Platform.
## Passing the Push payload to the MoEngage SDK
Even though you have your receiver to receive the notification payloads, you must pass messages from MoEngage platform to MoEngage SDK to render push notifications, especially rich push notifications. In that case, pass the payload to MoEngage SDK using the following method.
To pass the push payload to the MoEngage SDK call the [*passPushPayload()*](https://moengage.github.io/android-api-reference/moe-push-firebase/com.moengage.firebase/-mo-e-fire-base-helper/pass-push-payload.html) API from the *onMessageReceived()* in the Firebase receiver.\
Before passing the payload to the MoEngage SDK you should check if the payload is from the MoEngage platform using the [*isFromMoengagePlatfrom()*](https://moengage.github.io/android-api-reference/pushbase/com.moengage.pushbase/\[android-jvm]-mo-e-push-helper/is-from-mo-engage-platform.html) helper API provided by the SDK.
```Kotlin Kotlin wrap theme={null}
if (MoEPushHelper.getInstance().isFromMoEngagePlatform(remoteMessage.data)){
MoEFireBaseHelper.getInstance().passPushPayload(applicationContext, remoteMessage.data)
}else{
// your app's business logic to show notification
}
```
```Java Java theme={null}
if (MoEPushHelper.getInstance().isFromMoEngagePlatform(remoteMessage.getData())) {
MoEFireBaseHelper.Companion.getInstance().passPushPayload(getApplicationContext(), remoteMessage.getData());
}else{
// your app's business logic to show notification
}
```
# Rich Landing
A rich landing page can open a web URL inside the app via a push campaign. Irrespective of who handles the push token registration and display, this step is needed to show rich landing pages using the MoEngage platform.
The XML code mentioned below is included in the new SDK version, but you can still use it to change the parent activity of MoEActivity if needed.
To use a rich landing page, you need to add the below code in the **AndroidManifest.xml**
```XML XML wrap theme={null}
```
| Parameter | Description |
| ------------------------- | ------------------------------------------------------------------- |
| \[ACTIVITY\_NAME] | Replace with the name you want to appear on your rich landing page. |
| \[PARENT\_ACTIVITY\_NAME] | Replace with the parent activity name that you want. |
# Device Triggered
Source: https://moengage.com/docs/developer-guide/android-sdk/push/optional/device-triggered
Install the MoEngage realtime-trigger module to enable device-triggered push notifications on Android.
# SDK Installation
## Installing using BOM
Integration using BOM is the recommended way of integration; refer to the [Install Using BOM](/android-sdk/sdk-integration/basic-integration/Install-Using-BOM) document. Once you have configured the BOM add the dependency in the *app/build.gradle* file as shown below
```Groovy build.gradle wrap theme={null}
dependencies {
...
implementation("com.moengage:realtime-trigger")
}
```
Once the BOM is configured, include the specific MoEngage modules required for the application. \
Note: Version numbers are not required for these dependencies; the BOM automatically manages them.
# Heads Up Notification
Source: https://moengage.com/docs/developer-guide/android-sdk/push/optional/heads-up-notification
Configure heads-up push notifications using Android notification channels in the MoEngage SDK.
## **Overview**
**Notification Channel Setup**
Heads-up notifications are supported only through Android notification channels. Please refer to the official documentation for the creation of the [notification channels](https://developer.android.com/develop/ui/views/notifications/channels). On Android devices using API levels under 26, the configuration won't be applied, as notification channels that need this setting weren't available until API level 26.
The Notification channel should have **IMPORTANCE\_HIGH** for heads-up notifications, and the same channel ID should be configured in the MoEngage dashboard.
## Configuration
In MoEngage Android version **13.06.00**, a new flag **isDirectPostingForHeadsUpEnabled** has been added in the **NotificationConfig**. If you are using HeadsUp Notification, we strongly recommend you pass the **isDirectPostingForHeadsUpEnabled** flag as true while initializing SDK. By default, it will be false.
For more information about API reference for all the possible options, refer to [NotificationConfig](https://moengage.github.io/android-api-reference/core/com.moengage.core.config/\[android-jvm]-notification-config/index.html).
Use the [*configureNotificationMetaData()*](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]-mo-engage/-builder/configure-notification-meta-data.html) to transfer the configuration to the SDK.
```Kotlin Kotlin wrap theme={null}
val moEngage = MoEngage.Builder(this, "XXXXXXXX")
.configureNotificationMetaData(NotificationConfig(smallIcon = R.drawable.small_icon, largeIcon = R.drawable.large_icon, isDirectPostingForHeadsUpEnabled = true))
.build()
MoEngage.initialiseDefaultInstance(moEngage)
```
```Java Java theme={null}
MoEngage moEngage = new MoEngage.Builder(this, "XXXXXXXXXX")
.configureNotificationMetaData(new NotificationConfig(R.drawable.small_icon,R.drawable.large_icon,R.color.notiColor,isMultipleNotificationEnabled,true))
.build();
MoEngage.initialiseDefaultInstance(moEngage);
```
## HeadsUp Notification Behaviour
If **isDirectPostingForHeadsUpEnabled** is true, SDK will use a direct posting mechanism to post Rich content directly if it's a high-priority channel. So the floating heads-up notification view will be shown for 5-8 seconds if it is not interacted with. On Android versions prior to API level 26, the flag will be ignored by default, and it will use the re-posting mechanism by default.
Otherwise, if **isDirectPostingForHeadsUpEnabled** is false, it will use the existing reposting mechanism, where text is posted first, and once media assets are downloaded, rich content is posted. This is to ensure at least some content is shown to the user immediately when the notification is received and to maintain a good impression rate. If this is the case, a heads-up window will get dismissed within few seconds due to reposting.
## Non-Headsup Notification Behaviour
For notifications with channel ID having channel importance other than **IMPORTANCE\_HIGH**, SDK will be using the reposting mechanism by default.
Please refer to the [user guide](https://help.moengage.com/hc/en-us/articles/34998473340948-Heads-Up-Notifications) to understand more about the heads-up notification behavior and OEM limitations.
# Location Triggered
Source: https://moengage.com/docs/developer-guide/android-sdk/push/optional/location-triggered
Set up geofence-based location-triggered push notifications in your Android app with the MoEngage SDK.
# Prerequisites
To use location triggered (Geofence) push, your app must request the following:
* ACCESS\_FINE\_LOCATION
* ACCESS\_BACKGROUND\_LOCATION if your app targets Android 10 (API level 29) or later.
For location triggered push to work, ensure your Application has the following enabled: Location permission, Play Services location library, and device's location.
For more information, refer to [Android Request Geofences](https://developer.android.com/training/location/geofencing#RequestGeofences).
# SDK Installation
## Installing using BOM
Integration using BOM is the recommended way of integration; refer to the [Install Using BOM](/android-sdk/sdk-integration/basic-integration/Install-Using-BOM) document. Once you have configured the BOM add the dependency in the *app/build.gradle* file as shown below
```Groovy build.gradle wrap theme={null}
dependencies {
...
implementation("com.moengage:geofence")
}
```
Once the BOM is configured, include the specific MoEngage modules required for the application. \
Note: Version numbers are not required for these dependencies; the BOM automatically manages them.
# Configure Geofence
By default, the geofence feature is not enabled. To enable the feature, call the below API.
```kotlin Kotlin wrap theme={null}
MoEGeofenceHelper.getInstance().startGeofenceMonitoring(context)
```
```java Java theme={null}
MoEGeofenceHelper.getInstance().startGeofenceMonitoring(context);
```
At any time if you want to stop the geofence monitoring or feature, use the below API. This API will remove the existing geofences.
```kotlin Kotlin wrap theme={null}
MoEGeofenceHelper.getInstance().stopGeofenceMonitoring(context)
```
```java Java theme={null}
MoEGeofenceHelper.getInstance().stopGeofenceMonitoring(context);
```
## Callback
MoEngage SDK optionally notifies the application whenever a Geo-Fence is triggered. If required, the application can consume the trigger and ask the SDK not to process it. Alternatively, the application can just use the callback for logging/analytical purposes and let MoEngage process the trigger.
For more information about implementing callback in the application using [*OnGeofenceHitListener*](https://moengage.github.io/android-api-reference/geofence/com.moengage.geofence.listener/-on-geofence-hit-listener/index.html).
Register the listener in the Application class *onCreate()* using [*MoEGeofenceHelper.getInstance().addListener()*](https://moengage.github.io/android-api-reference/geofence/com.moengage.geofence/-mo-e-geofence-helper/add-listener.html).
# Notification Center
Source: https://moengage.com/docs/developer-guide/android-sdk/push/optional/notification-center
Add a notification center to your Android app to display push notification history using MoEngage SDK.
# Overview
The Notification Center shows your push notification history, allowing you to provide an option for the end-user to scroll back and see what they have missed. MoEngage provides out-of-box inbox support with a fully customizable default UI and also provides an option to build your own Notification Center.
# Using MoEngage's default Notification Center
## SDK Installation
## Installing using BOM
Integration using BOM is the recommended way of integration; refer to the [Install Using BOM](/android-sdk/sdk-integration/basic-integration/Install-Using-BOM) document. Once you have configured the BOM add the dependency in the *app/build.gradle* file as shown below
```Groovy build.gradle wrap theme={null}
dependencies {
...
implementation("com.moengage:inbox-ui")
}
```
Once the BOM is configured, include the specific MoEngage modules required for the application. \
Note: Version numbers are not required for these dependencies; the BOM automatically manages them..
## Adding the default Notification Center to your app
To use the default Notification Center UI you can either launch the [Activity](https://moengage.github.io/android-api-reference/inbox-ui/com.moengage.inbox.ui.view/-inbox-activity/index.html) provided by the SDK or add the [Fragment](https://moengage.github.io/android-api-reference/inbox-ui/com.moengage.inbox.ui.view/-inbox-fragment/index.html) provided by the SDK.
### Use Activity
The activity is already declared in the SDK's manifest file and can be inflated using the below code.
```kotlin Kotlin wrap theme={null}
//launching the default InboxActivity
val intent = Intent(this, InboxActivity::class.java)
startActivity(intent)
```
```java Java theme={null}
Intent intent = new Intent(this, InboxActivity.class);
startActivity(intent);
```
### Use Fragment
You can embed [*InboxFragment*](https://moengage.github.io/android-api-reference/inbox-ui/com.moengage.inbox.ui.view/-inbox-fragment/index.html) provided by the SDK in your app's activity. For information on how to add a Fragment to an Activity, refer to [Google documentation on Fragments](https://developer.android.com/guide/fragments).
# Adding parent Activity to the inbox.
Optionally if you want to define the parent activity for the Inbox then use the below code. Replace ***\[PARENT\_ACTIVITY\_NAME]*** with the name of the parent activity.
```xml XML wrap theme={null}
//launching the default InboxActivity
val intent = Intent(this, InboxActivity::class.java)
startActivity(intent)
```
# Customizing Default Notification Center
SDK provides a certain set of UI customization options. The [InboxActivity](https://moengage.github.io/android-api-reference/inbox-ui/com.moengage.inbox.ui.view/-inbox-activity/index.html) is already in the SDK's manifest file, if a change in label/theme of the default activity is required the activity should be declared again in your app's manifest file and override the attributes.
## Activity Label customization
The default label for the Inbox Activity is ***Notification Inbox***, which you can override by declaring the ***moe\_inbox\_notification\_title*** in the ***strings.xml*** of your application.
```xml strings.xml wrap theme={null}
[LABEL]
```
### Activity theme
To customize the theme, you can either re-declare the activity in your app's manifest and provide the desired theme, or you can override the SDK defaults as described below.
The default theme applied to ***InboxActivity*** is ***MoEInboxTheme.NoActionBar***. You can declare a theme with the same name in the application's ***style.xml*** or ***themes.xml*** or equivalent file.
Below is the definition of the default theme
```xml styles.xml wrap theme={null}
```
To customize the theme, override any of the color attributes by defining the color attributes with the same name in your application's **colors.xml** file.
```xml color.xml wrap theme={null}
{/* Theme customisation */}
#1C64D0@color/moe_black@color/moe_white@color/moe_black
```
For example, if you want to customize the primary dark color define ***moe\_inbox\_color\_primary\_dark*** in your app's **colors.xml** as shown below.
```xml XML wrap theme={null}
[YOUR_COLOR]
```
Similarly, you can customize
* Toolbar Style
* Message Text Appearance
* Header
* Message
* Timestamp
* Scrollbar style
* Empty Notification Center style
You can override the below SDK's default attributes to customize the theme.
```xml XML wrap theme={null}
{/* Toolbar Text Style */}
{/* Header style */}
{/* Message style */}
{/* List Item Separator style */}
{/* Timestamp Style */}
{/* Empty List Style */}
{/* Scrollbar style */}
```
## InboxAdapter Customization
You can override [*InboxAdapter*](https://moengage.github.io/android-api-reference/inbox-ui/com.moengage.inbox.ui.adapter/-inbox-adapter/index.html) to customize the look and feel of the notification Items.
In case of using a custom [*InboxAdapter*](https://moengage.github.io/android-api-reference/inbox-ui/com.moengage.inbox.ui.adapter/-inbox-adapter/index.html), the app should make sure to invoke [*InboxListAdapater.onItemClicked()*](https://moengage.github.io/android-api-reference/inbox-ui/com.moengage.inbox.ui.adapter/-inbox-list-adapter/on-item-clicked.html) on the message item click for the SDK to handle the notification click action; otherwise, the click event will not be tracked, and the on click action will not be executed.
Once your custom InboxAdapter is ready, set the custom Adapter in [MoEInboxUiHelper](https://moengage.github.io/android-api-reference/inbox-ui/com.moengage.inbox.ui/-mo-e-inbox-ui-helper/index.html) before launching the [InboxActivity](https://moengage.github.io/android-api-reference/inbox-ui/com.moengage.inbox.ui.view/-inbox-activity/index.html).
```kotlin Kotlin wrap theme={null}
MoEInboxUiHelper.getInstance().setInboxAdapter(InboxCustomAdapter())
```
## Advanced customization options
1. Deleting Notification from Notification Center\
You can delete a particular notification from Notification Center by calling [deleteItem(](https://moengage.github.io/android-api-reference/inbox-ui/com.moengage.inbox.ui.adapter/-inbox-list-adapter/delete-item.html)**)**.
```kotlin Kotlin wrap theme={null}
public fun onBind(position: Int, inboxMessage: InboxMessage, inboxListAdapter: InboxListAdapter) {
deleteButton.setOnClickListener{
//Call `deleteItem` method to remove Notification
//with item's position and the `InboxMessage` object.
inboxListAdapter.deleteItem(position, inboxMessage)
}
}
```
```java Java theme={null}
public void onBind(int position, InboxMessage inboxMessage, InboxListAdapter inboxListAdapter) {
deleteButton.setOnClickListener(v -> {
//Call `deleteItem` method to remove Notification
//with item's position and the `InboxMessage` object.
inboxListAdapter.deleteItem(position, inboxMessage);
});
}
```
Now, your Notification will get deleted from Notification Center, and Notification Center will get updated.
2. Custom notification item click handling
In case you are using the default Notification Center or using the [*InboxFragment*](https://moengage.github.io/android-api-reference/inbox-ui/com.moengage.inbox.ui.view/-inbox-fragment/index.html) in your app without overriding [*InboxAdapter*](https://moengage.github.io/android-api-reference/inbox-ui/com.moengage.inbox.ui.adapter/-inbox-adapter/index.html), by default, the SDK will handle the notification click action, but you can opt to handle the click action in your app by setting [OnMessageClickListener](https://moengage.github.io/android-api-reference/inbox-ui/com.moengage.inbox.ui.listener/-on-message-click-listener/index.html).
```kotlin Kotlin wrap theme={null}
//set the Message click listener
MoEInboxUiHelper.getInstance().setOnMessageClickListener(listener)
//Remove the Message click listener
MoEInboxUiHelper.getInstance().setOnMessageClickListener(null)
```
```java Java theme={null}
//set the Message click listener
MoEInboxUiHelper.getInstance().setOnMessageClickListener(listener);
//Remove the Message click listener
MoEInboxUiHelper.getInstance().setOnMessageClickListener(null);
```
# Self Handled Notification Center
MoEngage SDK provides helper APIs to fetch the relevant inbox data to display, track events, delete messages, etc. that can be used to build your Notification Centre.

## SDK Installation
### Installing using Catalog
Integration using a Version Catalog is the recommended way of integration. Once you have configured the catalog, add the dependency in the ***app/build.gradle*** file as shown below
```auto build.gradle wrap theme={null}
dependencies {
...
implementation(moengage.inboxCore)
}
```
Alternatively, you can add the dependency using Artifact ID as described in [Installation using Artifact ID](/android-sdk/sdk-integration/advanced-or-optional/installing-sdk-using-artifact-id#In-App). However, installation using Catalog ID is the recommended approach as installing using Artifact ID may lead to version mismatch if mapped incorrectly.
# Build Your Notification Center
The below helper APIs can be used to build your own Notification Center. For more information on available helper APIs refer [here](https://moengage.github.io/android-api-reference/inbox-core/com.moengage.inbox.core/-mo-e-inbox-helper/index.html).
## Get all messages
```kotlin Kotlin wrap theme={null}
// synchronous API should not be called on the main thread
MoEInboxHelper.getInstance().fetchAllMessages(context)
// asynchronous API, where listener is an instance of `OnMessagesAvailableListener`
MoEInboxHelper.getInstance().fetchAllMessagesAsync(applicationContext, listener)
```
```java Java theme={null}
// synchronous API should not be called on the main thread
MoEInboxHelper.getInstance().fetchAllMessages(context);
// asynchronous API, where listener is an instance of `OnMessagesAvailableListener`
MoEInboxHelper.getInstance().fetchAllMessagesAsync(applicationContext, listener);
```
## Get UnClicked Notifications count
```kotlin Kotlin wrap theme={null}
MoEInboxHelper.getInstance().getUnClickedMessagesCount(applicationContext)
```
```java Java theme={null}
MoEInboxHelper.getInstance().getUnClickedMessagesCount(applicationContext)
```
## Track Inbox Notification Clicks
```kotlin Kotlin wrap theme={null}
MoEInboxHelper.getInstance().trackMessageClicked(context, inboxMessage)
```
```java Java theme={null}
MoEInboxHelper.getInstance().trackMessageClicked(context, inboxMessage);
```
## Delete Inbox Message
```kotlin Kotlin wrap theme={null}
MoEInboxHelper.getInstance().deleteMessage(context, inboxMessage)
```
```java Java theme={null}
MoEInboxHelper.getInstance().deleteMessage(context, inboxMessage);
```
## Delete All Inbox Message
This feature requires a minimum catalog version **4.5.0**.
```kotlin Kotlin wrap theme={null}
MoEInboxHelper.getInstance().deleteAllMessages(context)
```
```java Java theme={null}
MoEInboxHelper.getInstance().deleteAllMessages(context);
```
## Check if the notification has a coupon code
```kotlin Kotlin wrap theme={null}
MoEInboxHelper.getInstance().hasCouponCode(inboxMessage)
```
```java Java theme={null}
MoEInboxHelper.getInstance().hasCouponCode(inboxMessage);
```
## Get coupon code
```kotlin Kotlin wrap theme={null}
MoEInboxHelper.getInstance().getCouponCode(inboxMessage);
```
```java Java theme={null}
MoEInboxHelper.getInstance().getCouponCode(inboxMessage);
```
Refer to [API reference](https://moengage.github.io/android-api-reference/inbox-core/com.moengage.inbox.core/-mo-e-inbox-helper/index.html) for more details.
# Configuring HMS Push Kit
Source: https://moengage.com/docs/developer-guide/android-sdk/push/optional/push-amp-plus/configuring-hms-push-kit
Configure Huawei HMS Push Kit in your Android app for MoEngage push notification delivery.
* Ensure that you have configured Push Kit on your application.\
For more information, refer to [HMS Push Kit documentation](https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides/service-introduction-0000001050040060).
* Ensure that you configure MoEngage SDK for receiving push notifications.
# SDK Installation
## Installing Using BOM
Integration using BOM is the recommended way of integration; refer to the [Install Using BOM](/android-sdk/sdk-integration/basic-integration/Install-Using-BOM) document to configure BOM if not done already. Once you have configured the BOM add the dependency in the ***app/build.gradle*** file as shown below
```Groovy build.gradle wrap theme={null}
dependencies {
...
implementation("com.moengage:hms-pushkit")
}
```
Alternatively, you can add the dependency using Artifact ID as described in [Installation using Artifact ID](/android-sdk/sdk-integration/advanced-or-optional/installing-sdk-using-artifact-id#In-App). However, installation using BOM is the recommended approach as installing using Artifact ID may lead to version mismatch if mapped incorrectly.
# Push Token Management
When using MoEngage SDK, you can either register for token and pass it on to the MoEngage SDK or simply let MoEngage SDK register for Push Token.
## Token Registration Handled by Application
If your application is registering for Push Notification, use the below API to pass the Push token to the MoEngage SDK.
```kotlin Kotlin wrap theme={null}
MoEPushKitHelper.getInstance().passPushToken(context, token)
```
```java Java theme={null}
MoEPushKitHelper.getInstance().passPushToken(context, token);
```
## Token Registration Handled by MoEngage
By default, the MoEngage SDK does not register for push tokens. You can enable the token registration using the [configurePushKit()](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]-mo-engage/-builder/configure-push-kit.html) API in the [MoEngage.Builder](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]-mo-engage/-builder/index.html) while initializing the SDK
```kotlin Kotlin wrap theme={null}
val moEngage = MoEngage.Builder(this, "XXXXXXXX")
.configurePushKit(PushKitConfig(true))
.build()
MoEngage.initialiseDefaultInstance(moEngage)
```
```java Java theme={null}
MoEngage moEngage = new MoEngage.Builder(this, "XXXXXXXXXX")
.configurePushKit(new PushKitConfig(true))
.build();
MoEngage.initialiseDefaultInstance(moEngage);
```
Add the below Service in your application's Manifest file.
```xml AndroidManifest.xml wrap theme={null}
>
```
When MoEngage SDK handles push registration, it optionally provides a callback to the Application whenever a new token is registered, or the token is refreshed.\
An application can get this callback by implementing the [TokenAvailableListener](https://moengage.github.io/android-api-reference/pushbase/com.moengage.pushbase.listener/-token-available-listener/index.html) interface and registering the listener using [MoEPushKitHelper.getInstance().addTokenListener()](https://moengage.github.io/android-api-reference/hms-pushkit/com.moengage.hms.pushkit/-mo-e-push-kit-helper/add-token-listener.html) API.
To use Push Kit, you need to update the *moe-android-sdk* to 10.3.00 or above.
# Configure Your Account on MoEngage
Now you have set up Huawei Push on MoEngage SDK. Proceed to [configuring Huawei Push on MoEngage dashboard](/android-sdk/push/optional/push-amp-plus/configuring-huawei-push-on-mo-engage).
# Configuring Huawei Push on MoEngage
Source: https://moengage.com/docs/developer-guide/android-sdk/push/optional/push-amp-plus/configuring-huawei-push-on-mo-engage
Set up Huawei Push Kit callback URLs and HTTPS certificates on the MoEngage Dashboard.
# Developer Guide
Please make sure that you have set up Push Kit on your application. To configure, use the following:
* [Introduction to HMS Push Kit](https://developer.huawei.com/consumer/en/doc/development/HMS-Guides/push-introduction).
* [Push Receipt](https://developer.huawei.com/consumer/en/doc/development/HMS-Guides/push-receipt#receiptright).
# MoEngage Callback URL
| New DataCenter | New Callback URL | Old Callback URL |
| -------------- | ---------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
| Data Center 1 | [https://api-01.moengage.com/hmspush/dlr](https://api-01.moengage.com/hmspush/dlr) | [https://smsapi.moengage.com/hmspush/dlr](https://smsapi.moengage.com/hmspush/dlr) |
| Data Center 2 | [https://api-02.moengage.com/hmspush/dlr](https://api-02.moengage.com/hmspush/dlr) | [https://smsapi.moengage.com/hmspush/dlr](https://smsapi.moengage.com/hmspush/dlr) |
| Data Center 3 | [https://api-03.moengage.com/hmspush/dlr](https://api-03.moengage.com/hmspush/dlr) | [https://smsapi.moengage.com/hmspush/dlr](https://smsapi.moengage.com/hmspush/dlr) |
| Data Center 4 | [https://api-04.moengage.com/hmspush/dlr](https://api-04.moengage.com/hmspush/dlr) | NA |
Update the URL in the callback address while enabling the recipient.
## HTTPS Certificate for MoEngage callback URL
* Select data storage other than the China region when enabling callback receipt.
* Use the following script to generate the HTTPS certificate while enabling the recipient. For more information, refer to [Push Receipt](https://developer.huawei.com/consumer/en/doc/development/HMS-Guides/push-receipt#receiptright).
```python HTTPS certificate generation using Python wrap theme={null}
import ssl
print(ssl.get_server_certificate(('dashboard-01.moengage.com', 443)))
```
# Configuring Huawei Push
To configure Huawei on the MoEngage dashboard:
1. Navigate to **Settings > Channels > Push > App Push > Huawei (Push Amp+)**.
2. Select Huawei (Push Amp+) in the Platforms available on the menu at the top.
## App ID
Get the App ID from the [Huawei Developer Console](https://developer.huawei.com/) by navigating to\
**Login > AppGallery Connect > My Apps > Select Your App > Distribute > App Information**
## App Secret
Get the App ID from the [Huawei Developer Console](https://developer.huawei.com/) by navigating to\
**Login > AppGallery Connect > My Apps > Select Your App > Distribute > App Information**
## Package Name
The package name for an application is the unique identifier through which the play store recognizes the application. You can find the package of your application in the **build.gradle** file of your application module.
If you have different package names for debug build and signed build configure the package names accordingly in the Test/Live Environment.
## Small Icon Path
As an important part of a notification message, a notification icon is used to identify the content and type of the message. To ensure a consistent user experience, *HUAWEI Push Kit notification icons* inherit the styles of native Android notification icons.
In other words, a notification icon on the notification bar is displayed in a solid color and the notification icon on the status bar is displayed in black or white. The status bar and notification bar share the same resources. For more information, refer to the [guideline document](https://developer.huawei.com/consumer/en/doc/development/HMS-Guides/push-icon-spec).
The icon file must be stored in the /res/raw directory of an app. For example, the value **/raw/ic\_launcher** indicates the local icon file **ic\_launcher.xxx** stored in **/res/raw**. Currently, supported file formats include PNG and JPG.
# Push AMP Plus Integration
Source: https://moengage.com/docs/developer-guide/android-sdk/push/optional/push-amp-plus/push-amp-plus-integration
Integrate MoEngage Push Amp+ to improve push notification delivery rates on Android OEM devices.
Almost 25-30% of notifications are not delivered because of OEM-related reasons. With Push Amplification+, you can reach these customers and see an immediate uplift in retention rates.\
So, we focused on solving the problem of delivery rates on OEMs and have partnered with OEMs to solve this problem.
To ensure we do not add additional bloat into your application we have made different SDKs for each OEM. You can integrate the relevant SDK based on the device share your application has.
Refer to the respective OEM-specific services documentation below and integrate the relevant ones in your application.
Integration supported are:
* [Configuring HMS Push Kit](/android-sdk/push/optional/push-amp-plus/configuring-hms-push-kit)
# Steps to Remove Mi SDK Dependency
Source: https://moengage.com/docs/developer-guide/android-sdk/push/optional/push-amp-plus/steps-to-remove-mi-sdk-dependency
Remove the discontinued Xiaomi Mi Push SDK dependency from your MoEngage Android integration.
Due to operational concerns, Xiaomi Corporation has recently notified users about the discontinuation of the Mi Push service beyond Mainland China. You might have already received correspondence regarding this matter.
In this regard, we suggest that our customers remove Mi Push SDK from their apps. The steps to do so are enumerated in this article.
## Step 1: Remove Mi aar
1. Navigate to app --> libs
2. Delete MiPush\_SDK\_Client\*.aar
## Step 2: Remove the Mi receiver from the manifest file
Remove the following code from the manifest file.
```xml Remove Mi receiver from the manifest file wrap theme={null}
```
## Step 3: Remove initialization code
Remove the following initialization code from the application.
```kotlin Code to be removed from the application wrap theme={null}
MiPushHelper.initialiseMiPush([context], [appKey], [appId], [region])
```
## Step 4: Delete the helper files
Delete the following helper files:
1. MiPushHelper.kt
2. MiPushReceiver.kt
## Step 5: Remove MoEngage dependency
Remove the MoEngage dependency from the dependencies block of the build.gradle as described:
1. MoEngage Catalog - If you are using the MoEngage catalog remove the following dependency:
```kotlin MoEngage Catalog wrap theme={null}
implementation(moengage.pushAmpPlus)
```
2. Artifact ID - If you have added the artifact id remove the following dependency:
```kotlin Artifact ID wrap theme={null}
implementation("com.moengage:push-amp:")
```
# Push Amplification
Source: https://moengage.com/docs/developer-guide/android-sdk/push/optional/push-amplification
Install the MoEngage push-amp module to improve push notification delivery rates on Android.
# SDK Installation
## Installing using BOM
Integration using BOM is the recommended way of integration; refer to the [Install Using BOM](/android-sdk/sdk-integration/basic-integration/Install-Using-BOM) document. Once you have configured the BOM add the dependency in the *app/build.gradle* file as shown below
```Groovy build.gradle wrap theme={null}
dependencies {
...
implementation("com.moengage:push-amp")
}
```
Once the BOM is configured, include the specific MoEngage modules required for the application. \
Note: Version numbers are not required for these dependencies; the BOM automatically manages them.
# Push Templates
Source: https://moengage.com/docs/developer-guide/android-sdk/push/optional/push-templates
Add rich push notification templates with timers and progress bars to your Android app using MoEngage.
# SDK Installation
## Installing using BOM
Integration using BOM is the recommended way of integration; refer to the [Install Using BOM](/android-sdk/sdk-integration/basic-integration/Install-Using-BOM) document. Once you have configured the BOM add the dependency in the *app/build.gradle* file as shown below
```Groovy build.gradle wrap theme={null}
dependencies {
...
implementation("com.moengage:rich-notification")
}
```
Once the BOM is configured, include the specific MoEngage modules required for the application. \
Note: Version numbers are not required for these dependencies; the BOM automatically manages them.
# Timer with Progress Bar
## Schedule Exact Alarm Permission
The SDK uses Alarms to periodically update the progress in the progress bar. Starting Android 12, additional permission is required to use exact alarms. Refer to the [documentation](https://developer.android.com/training/scheduling/alarms#exact) for more details. To support the Timer with Progress Bar template on Android 12 and above devices, add the following permission in your manifest file.
```xml AndroidManifest.xml wrap theme={null}
```
Starting Android 14, the Alarm permission is off by default. So you need to ask for explicit Alarm permission if you want to show Timer notifications apart from adding the previous line in your manifest file. Verify if the permission is already granted and accordingly call the following line to get the Alarm permission from the customer.
```Java Java wrap theme={null}
startActivity(Intent(ACTION_REQUEST_SCHEDULE_EXACT_ALARM))
```
If the application does not have the permission above, the Timer with Progress Bar template will not be shown to the user; instead, a backup template will be displayed to the user which will have the Timer but not the progress bar.
## Customization
The SDK defines the default color values for the progress bar's background and progress color. These can be customized to suit the application's theme by overriding the values for the below SDK-defined color attributes.
To set the custom color in light and dark mode, override the values in **res/values/colors.xml** and **res/values-night/colors.xml**, respectively.
```xml colors.xml wrap theme={null}
[YOUR_COLOR][YOUR_COLOR]
```
# Android Sample App
Source: https://moengage.com/docs/developer-guide/android-sdk/sample-app/android-sample-app
Explore the MoEngage Android sample app on GitHub as a reference for your SDK integration.
**Sample App**
The [MoEngage Android Sample application](https://github.com/moengage/Android-Sample) offers a useful reference point for integrating MoEngage into your Android app.
## Next Steps
* [SDK Installation](/developer-guide/android-sdk/sdk-integration/basic-integration/Install-Using-BOM)
* [Release Checklist](/developer-guide/android-sdk/checklist/release-checklist)
# Add-On Security
Source: https://moengage.com/docs/developer-guide/android-sdk/sdk-integration/advanced-or-optional/add-on-security
Encrypt data stored by the MoEngage Android SDK on device using the encrypted storage module.
# Encrypted Storage
By default, all the data stored by the SDK on the device is inside the application sandbox. This prevents other applications from accessing the data(both read and write). Though due to compliance standards or any other use cases, you might want additionally encrypt the data stored on the SDK.
To enable this encryption you need to
* Add the below-listed dependencies in your ***app/build.gradle*** file.
* Call the [configureStorageSecurity()](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]-mo-engage/-builder/configure-storage-security.html) to enable the encryption on the [MoEngage.Builder](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]-mo-engage/-builder/index.html) object while initializing the SDK
## SDK Installation
### Installing using BOM
Integration using BOM is the recommended way of integration; refer to the [Install Using BOM](/android-sdk/sdk-integration/basic-integration/Install-Using-BOM) document to configure if not done already. Once you have configured the BOM, add the dependency in the ***app/build.gradle*** file as shown below.
```Groovy build.gradle wrap theme={null}
dependencies {
...
implementation("com.moengage.security")
}
```
Alternatively, you can add the dependency using Artifact ID as described in [Installation using Artifact ID](/android-sdk/sdk-integration/advanced-or-optional/installing-sdk-using-artifact-id#EncryptedStorage). However, installation using BOM is the recommended approach, as installing using Artifact ID may lead to version mismatch if mapped incorrectly.
## Enabling Encryption
You can enable the storage encryption using the [configureStorageSecurity()](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]-mo-engage/-builder/configure-storage-security.html) API in the [*MoEngage.Builder*](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]-mo-engage/-builder/index.html) while initializing the SDK.
```kotlin Kotlin wrap theme={null}
val moEngage = MoEngage.Builder(this, "YOUR_Workspace_ID")
.configureStorageSecurity(StorageSecurityConfig(StorageEncryptionConfig(true)))
.build()
MoEngage.initialise(moEngage)
```
```java Java theme={null}
MoEngage moEngage = new MoEngage.Builder(this, "YOUR_Workspace_ID")
.configureStorageSecurity(new StorageSecurityConfig(new StorageEncryptionConfig(true)))
.build();
MoEngage.initialise(moEngage);
```
Note:
* If storage encryption is enabled in the initialization without adding the above-mentioned dependencies, SDK wouldn't function i.e. no events/user attributes would be tracked, push notifications would not be shown, etc.
* Once storage encryption is enabled and a build is released to production(Play Store or other equivalent stores), you should not disable encryption. Disabling the encryption after the build is released will result in a new user being created in the MoEngage system when the user updates the application.
# Encrypted Network Communication
By default, we use HTTPS protocol for all requests made from the SDK; HTTPS encrypts the requests by default. MoEngage SDK optionally adds another layer of encryption apart from the encryption done by HTTPS.\
To enable this additional encryption, you need to
* Add the below-listed dependencies in your***app/build.gradle*** file.
* Call the [configureNetworkRequest()](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]-mo-engage/-builder/configure-network-request.html) on the [MoEngage.Builder](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]-mo-engage/-builder/index.html) object while initializing the SDK
## SDK Installation
***If you have enabled Storage encryption, you can skip the installation step and jump to the Enabling Encryption step.***
### Installing using BOM
Integration using BOM is the recommended way of integration, refer to the [Install Using BOM](/android-sdk/sdk-integration/basic-integration/Install-Using-BOM) document to configure BOM if not done already. Once you have configured the BOM add the dependency in the ***app/build.gradle*** file as shown below
```Groovy build.gradle wrap theme={null}
dependencies {
...
implementation("com.moengage.security")
}
```
Alternatively, you can add the dependency using Artifact ID as described in [Installation using Artifact ID](/android-sdk/sdk-integration/advanced-or-optional/installing-sdk-using-artifact-id#Push-Templates). However, installation using BOM is the recommended approach, as installing using Artifact ID may lead to version mismatch if mapped incorrectly.
## Enabling Encryption
You can enable the network encryption using the [configureNetworkRequest()](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]-mo-engage/-builder/configure-network-request.html) API in the [*MoEngage.Builder*](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]-mo-engage/-builder/index.html) while initializing the SDK.
### Fetch the keys
The key is available on the dashboard. Go to **Settings -> APIs -> API Keys and** copy the **SDK encryption key** for the Test and Live environments (Note: Test and Live environments have separate keys and only the key of the current selected environment will be accessible).
### Configure Network Request
```kotlin Kotlin wrap theme={null}
val moEngage = MoEngage.Builder(this, "YOUR_Workspace_ID")
.configureNetworkRequest(NetworkRequestConfig(NetworkDataSecurityConfig(true, "YOUR_TEST_ENVIRONMENT_ENCRYPTION_KEY", "YOUR_LIVE_ENVIRONMENT_ENCRYPTION_KEY")))
.build()
MoEngage.initialise(moEngage)
```
```java Java theme={null}
MoEngage moEngage = new MoEngage.Builder(this, "YOUR_Workspace_ID")
.configureNetworkRequest(new NetworkRequestConfig(new NetworkDataSecurityConfig(true, "YOUR_TEST_ENVIRONMENT_ENCRYPTION_KEY", "YOUR_LIVE_ENVIRONMENT_ENCRYPTION_KEY")))
.build();
MoEngage.initialise(moEngage);
```
***Note:*** When using encrypted network communication, we strongly recommend you enable Storage encryption as well.
# Network Request Authorization
To enable the network request authorization you need to
* Add the below-listed dependencies in your***app/build.gradle*** file.
* Call the [configureNetworkRequest()](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]-mo-engage/-builder/configure-network-request.html) to enable the authorization on the [MoEngage.Builder](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]-mo-engage/-builder/index.html) object while initializing the SDK
## SDK Installation
***If you have enabled Storage encryption or Encrypted Network Communication, you can skip the installation step and jump to the Enabling Authorization step.***
### Installing using BOM
Integration using BOM is the recommended way of integration, refer to the [Install Using BOM](/android-sdk/sdk-integration/basic-integration/Install-Using-BOM) document to configure BOM if not done already. Once you have configured the BOM add the dependency in the ***app/build.gradle*** file as shown below
```Groovy build.gradle wrap theme={null}
dependencies {
...
implementation("com.moengage.security")
}
```
Alternatively, you can add the dependency using Artifact ID as described in [Installation using Artifact ID](/android-sdk/sdk-integration/advanced-or-optional/installing-sdk-using-artifact-id#Device-Triggered). However, installation using BOM is the recommended approach, as installing using Artifact ID may lead to version mismatch if mapped incorrectly.
## Enabling Authorization
You can enable the network authorization using the [configureNetworkRequest()](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]-mo-engage/-builder/configure-network-request.html) API in the [*MoEngage.Builder*](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]-mo-engage/-builder/index.html) while initializing the SDK.
```kotlin Kotlin wrap theme={null}
val moEngage = MoEngage.Builder(this, "YOUR_Workspace_ID", )
.configureNetworkRequest(NetworkRequestConfig(NetworkAuthorizationConfig(true)))
.build()
MoEngage.initialise(moEngage)
```
```java Java theme={null}
MoEngage moEngage = new MoEngage.Builder(this, "YOUR_Workspace_ID", )
.configureNetworkRequest(new NetworkRequestConfig(new NetworkAuthorizationConfig(true)))
.build();
MoEngage.initialise(moEngage);
```
Adding the above dependency and enabling the flag isn't enough for this feature to work; there is some additional configuration required on our side to enable this feature completely. In case you want to use this feature, reach out to your account manager or the MoEngage Support team.
# Custom Proxy Domain - Android
Source: https://moengage.com/docs/developer-guide/android-sdk/sdk-integration/advanced-or-optional/custom-proxy-domain-android
Route MoEngage SDK traffic through your own subdomain to bypass ad blockers on Android.
In today's privacy-focused digital landscape, many users employ ad blockers or private DNS services. These tools often block network requests to known third-party domains, including analytics and engagement platforms. When these requests are blocked, you lose critical data visibility, and your users may not receive in-app messages or push notifications.
To ensure reliable campaign delivery, MoEngage offers the **Custom Proxy Domain** feature. This allows you to route MoEngage SDK traffic through a subdomain of your own primary domain (e.g., `data.yourcompany.com`). Because the traffic appears as first-party communication, it bypasses common ad-blocking lists.
## Onboarding Process
Setting up a Custom Proxy Domain requires a one-time DNS delegation process between your team and MoEngage.
Before updating your SDK code, you must complete the DNS delegation setup. For a detailed guide on picking a domain and configuring NS records, refer to [DNS Delegation](https://help.moengage.com/hc/en-us/articles/45199793953300-DNS-Delegation-for-Custom-Subdomains).
### Step 1: Choose a Subdomain
Select a subdomain that is short and does not contain keywords typically flagged by filters (for example, avoid "tracking", "ads", or "moengage").
### Step 2: Request DNS Delegation
Reach out to your MoEngage Customer Success Manager (CSM) or [raise a support ticket](https://help.moengage.com) to initiate the request. Provide your chosen subdomain.
### Step 3: Configure NS Records
MoEngage will provide you with four Name Server (NS) records. You must add these records to your DNS provider's configuration for the chosen subdomain.
## Implementation
Once the DNS delegation is verified, update your SDK initialization logic. The SDK will dynamically rewrite all MoEngage endpoints (API calls and CDN assets) to use your custom proxy domain.
### Update MoEngage Configuration
```kotlin Kotlin wrap theme={null}
import com.moengage.core.DataCenter
import com.moengage.core.MoEngage
import com.moengage.core.config.DomainConfig
import com.moengage.core.config.NetworkRequestConfig
val moEngage = MoEngage.Builder(application, "YOUR_Workspace_ID", DataCenter.DATA_CENTER_X)
.configureNetworkRequest(
NetworkRequestConfig(DomainConfig("CUSTOM_DOMAIN"))
)
.build()
MoEngage.initialiseDefaultInstance(moEngage)
```
```java Java theme={null}
import com.moengage.core.DataCenter;
import com.moengage.core.MoEngage;
import com.moengage.core.config.DomainConfig;
import com.moengage.core.config.NetworkRequestConfig;
MoEngage moEngage = new MoEngage.Builder(this, "YOUR_Workspace_ID", DataCenter.DATA_CENTER_X)
.configureNetworkRequest(new NetworkRequestConfig(new DomainConfig("CUSTOM_DOMAIN")))
.build();
MoEngage.initialiseDefaultInstance(moEngage);
```
## Best Practices and Validation
1. **Domain Selection:** Keep your subdomain string short (5-8 characters).
2. **Network Logs:** Verify that requests start with your custom subdomain (e.g., `sdk-01.data.example.com`).
3. **Asset Loading:** Ensure images in campaigns load correctly.
# Installing SDK using Artifact Id
Source: https://moengage.com/docs/developer-guide/android-sdk/sdk-integration/advanced-or-optional/installing-sdk-using-artifact-id
Install MoEngage Android SDK modules individually using their Maven Central artifact IDs.
We recommend integrating the MoEngage BOM for easier dependency management. Refer to the [documentation](/sdk-integration/basic-integration/Install-Using-BOM) to know more.
# SDK Versions
| Artifact Name | Artifact Id | Version |
| -------------------------------- | ----------------- | ------- |
| Core | moe-android-sdk | |
| Self-Handled Cards | cards-core | |
| Default Cards | cards-ui | |
| Encrypted Storage | encrypted-storage | |
| Geofence | geofence | |
| HMS Pushkit | hms-pushkit | |
| InApp | inapp | |
| Self-Handled Notification Center | inbox-core | |
| Default Notification Center | inbox-ui | |
| PushAmp | push-amp | |
| PushAmpPlus | push-amp-plus | |
| Device Triggered | realtime-trigger | |
| Push Templates | rich-notification | |
| Security | security | |
# SDK Installation
Add the following dependency in the ***app/build.gradle(.kts)*** file to integrate the required modules. Make sure to replace **\$sdkVersion** with the appropriate SDK version
## Core
```Kotlin build.gradle(.kts) wrap theme={null}
dependencies {
...
implementation("com.moengage:moe-android-sdk:$sdkVersion")
}
```
## Self-Handled Cards
```Kotlin build.gradle(.kts) wrap theme={null}
dependencies {
...
implementation("com.moengage:cards-core:$sdkVersion")
}
```
## MoEngage's Default Cards
```Kotlin build.gradle(.kts) wrap theme={null}
dependencies {
...
implementation("com.moengage:cards-ui:$sdkVersion")
}
```
## Encrypted Storage
```Kotlin build.gradle(.kts) wrap theme={null}
dependencies {
...
implementation("com.moengage:encrypted-storage:$sdkVersion")
}
```
## Geofence
```Kotlin build.gradle(.kts) wrap theme={null}
dependencies {
...
implementation("com.moengage:geofence:$sdkVersion")
}
```
## HMS Pushkit
```Kotlin build.gradle(.kts) wrap theme={null}
dependencies {
...
implementation("com.moengage:hms-pushkit:$sdkVersion")
}
```
## InApp
```Kotlin build.gradle(.kts) wrap theme={null}
dependencies {
...
implementation("com.moengage:inapp:$sdkVersion")
}
```
## Self-Handled Notification Center
```Kotlin build.gradle(.kts) wrap theme={null}
dependencies {
...
implementation("com.moengage:inbox-core:$sdkVersion")
}
```
## MoEngage's default Notification Center
```Kotlin build.gradle(.kts) wrap theme={null}
dependencies {
...
implementation("com.moengage:inbox-ui:$sdkVersion")
}
```
## Push Amplification
```Kotlin build.gradle(.kts) wrap theme={null}
dependencies {
...
implementation("com.moengage:push-amp:$sdkVersion")
}
```
## PushAmpPlus
```Kotlin build.gradle(.kts) wrap theme={null}
dependencies {
...
implementation("com.moengage:push-amp-plus:$sdkVersion")
}
```
## Device Triggered
```Kotlin build.gradle(.kts) wrap theme={null}
dependencies {
...
implementation("com.moengage:realtime-trigger:$sdkVersion")
}
```
## Push Templates
```Kotlin build.gradle(.kts) wrap theme={null}
dependencies {
...
implementation("com.moengage:rich-notification:$sdkVersion")
}
```
## Security
```Kotlin build.gradle(.kts) wrap theme={null}
dependencies {
...
implementation("com.moengage:security:$sdkVersion")
}
```
# JWT Authentication
Source: https://moengage.com/docs/developer-guide/android-sdk/sdk-integration/advanced-or-optional/jwt-authentication
Secure your MoEngage data collection by implementing JWT authentication in your Android app.
## Overview
JWT (JSON Web Token) authentication is a standard method for securely verifying user identity. By implementing JWT authentication, you add a critical layer of security to your data collection process with MoEngage.
The feature ensures that the data sent on behalf of your identified users is authentic and is not tampered with. This security is achieved by requiring a token that is cryptographically signed by your own server, which prevents unauthorized users from impersonating your legitimate users.
Before you begin the implementation, ensure you meet the following requirements:
* Your application must use the MoEngage Android SDK version **14.04.00** or higher to access the JWT authentication feature.
* You must have access to your MoEngage dashboard to manage public keys and configure the feature's enforcement settings.
The following diagram illustrates the interaction between your application, your server, the MoEngage SDK, and the MoEngage server:
## Integration
Perform the following to integrate JWT authentication into your Android application:
### Step 1: Enable JWT Authentication
You can enable JWT authentication during [SDK initialization](/android-sdk/sdk-integration/basic-integration/sdk-initialization) by configuring the ***NetworkAuthorizationConfig*** property on the ***MoEngage.Builder*** object.
```kotlin Kotlin wrap theme={null}
val builder = MoEngage.Builder(application, , )
.configureNetworkRequest(NetworkRequestConfig(networkAuthorizationConfig = NetworkAuthorizationConfig(isJwtEnabled = true)))
MoEngage.initialiseDefaultInstance(builder.build())
```
```java Java theme={null}
MoEngage.Builder builder = new MoEngage.Builder(application, , )
.configureNetworkRequest(new NetworkRequestConfig(new NetworkAuthorizationConfig(true)));
MoEngage.initialiseDefaultInstance(builder.build());
```
### Step 2: Pass the JWT to the SDK
Your application is responsible for managing the JWT lifecycle. The recommended flow is to fetch a token upon user login and pass the token to the SDK. You should also check if the token has expired on subsequent app launches and fetch a new one if necessary.
Use the [***MoECoreHelper.passAuthenticationDetails()***](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]-mo-e-core-helper/pass-authentication-details.html) to provide the token to the SDK.
```kotlin Kotlin wrap theme={null}
val data = AuthenticationData.Jwt(, )
MoECoreHelper.passAuthenticationDetails(context, data)
```
```java Java theme={null}
AuthenticationData data = new AuthenticationData.Jwt(, );
MoECoreHelper.INSTANCE.passAuthenticationDetails(application.getApplicationContext(), data);
```
### Step 3: Handle Authentication Errors
To handle token validation errors that the MoEngage server returns, you must register an error listener. The SDK invokes this listener when an authentication error occurs, which allows your application to fetch and provide a new token.
```kotlin Kotlin wrap theme={null}
val authErrorListener = OnAuthenticationError { error -
when (error.data) {
is ErrorData.Jwt - {
// Handle JWT authentication error
val errorData = error.data as ErrorData.Jwt
val jwtError = errorData.code
val message = errorData.message
// Take appropriate action based on the jwtError
}
}
}
// Register listener after SDK initialization
MoECoreHelper.registerAuthenticationListener(authErrorListener)
```
```java Java theme={null}
OnAuthenticationError errorListener = new OnAuthenticationError() {
@Override
public void onError(@NonNull AuthenticationError error) {
switch (error.getType()) {
case JWT:
ErrorData.Jwt jwtError = (ErrorData.Jwt) error.getData();
// Handle JWT error
JwtError jwtErrorType = jwtError.getCode();
String message = jwtError.getMessage();
// Take action based on jwtErrorType
break;
}
}
};
// Register listener after SDK initialization
MoECoreHelper.INSTANCE.registerAuthenticationListener(errorListener);
```
### Step 4: Handle Authentication Errors
Register the [***OnAuthenticationError***](https://moengage.github.io/android-api-reference/core/com.moengage.core.model.authentication/\[android-jvm]-on-authentication-error/index.html) listener in a global scope, such as the ***onCreate()*** of your Application class, to ensure your application always receives callbacks.
```kotlin Kotlin wrap theme={null}
MoECoreHelper.registerAuthenticationListener(authErrorListener)
```
```java Java theme={null}
MoECoreHelper.INSTANCE.registerAuthenticationListener(errorListener);
```
* If an API request fails due to an authentication error, the SDK will not retry the request until your application provides a new token.
* After 10 consecutive authentication failures in a single session, the SDK will stop attempting to sync data until the next session begins. This counter resets after any successful sync.
* Upon user logout, if a data sync fails due to a JWT error, the pending data will be deleted, and no retry will be attempted.
# Network Security Configuration
Source: https://moengage.com/docs/developer-guide/android-sdk/sdk-integration/advanced-or-optional/network-security-configuration
Whitelist MoEngage SDK domains in your custom Android network security configuration.
This section is only required if you have a custom Network Security Configuration in your application.
If your application has a network security configuration that whitelists domains to which your application can send data to whitelist the below domains based on the MoEngage Data Center you have selected while integrating the SDK.
| Data Center | Host |
| --------------- | ------------------- |
| DATA\_CENTER\_1 | sdk-01.moengage.com |
| DATA\_CENTER\_2 | sdk-02.moengage.com |
| DATA\_CENTER\_3 | sdk-03.moengage.com |
| DATA\_CENTER\_4 | sdk-04.moengage.com |
| DATA\_CENTER\_5 | sdk-05.moengage.com |
| DATA\_CENTER\_6 | sdk-06.moengage.com |
By default, the SDK sends the data to *DATA\_CENTER\_1*. In case, you have not configured any data center while initializing the SDK whitelist the host corresponding to *DATA\_CENTER\_1*
# SDK Configuration
Source: https://moengage.com/docs/developer-guide/android-sdk/sdk-integration/advanced-or-optional/sdk-configuration
Review the MoEngage Android SDK build configuration requirements and supported API levels.
Android SDK configuration uses the build configuration and library dependencies.
# Build Configuration
| Configuration | API Level |
| ----------------------------- | --------- |
| Target SDK Version | 35 |
| Compile SDK Version | 35 |
| Minimum SDK Version | 23 |
| Kotlin Version | 1.9.23 |
| Android Gradle Plugin Version | 8.7.3 |
Refer to the [API level to code name mapping](https://source.android.com/setup/start/build-numbers) to get the version name.
# Library Dependency
The SDK is complied using the described version but the versions are modified by the application at runtime.
SDK is compiled with the following libraries:
```groovy Groovy wrap theme={null}
androidx.core:core:1.15.0
androidx.appcompat:appcompat:1.7.0
androidx.lifecycle:lifecycle-process:2.8.7
```
The build configuration is available only for the current SDK version. If you are using an older version of the SDK and want to know the build configuration, contact MoEngage support or contact your Account Manager.
# Install Using BOM
Source: https://moengage.com/docs/developer-guide/android-sdk/sdk-integration/basic-integration/Install-Using-BOM
Use the MoEngage Bill of Materials to manage compatible Android SDK module versions.
**Information**
You can now get notified whenever MoEngage releases a new version of the Android Native SDK. For more information, refer to [Subscribe to MoEngage SDK Releases](/release-notes/subscribe-to-moengage-sdk-releases/subscribe-to-mo-engage-sdk-releases).
## Overview
Starting from Android SDK core version [14.04.03](/release-notes/android-sdk/2025-1#11th-December-2025) and later, MoEngage recommends using the Bill of Materials (BOM) to integrate the Android SDK. By defining a single BOM version, you ensure that all MoEngage modules, such as Push Kit, Rich Media, and Geofence, automatically use compatible versions. BOM simplifies dependency management, prevents version conflicts, and eliminates the need to manually track version numbers for each individual artifact.
## Add the BOM to your application
To integrate the BOM, add the `android-bom` dependency to the application-level `build.gradle` file. The version number is specified only in this dependency.
```kotlin build.gradle.kts (Kotlin) wrap theme={null}
dependencies {
// Import the MoEngage BOM
implementation(platform("com.moengage:android-bom:"))
}
```
Replace the `` with the relevant version number. For more information on BOM versions, refer to the [Android SDK release notes](/release-notes/android-sdk/).
## Add MoEngage Modules
Once the BOM is configured, include the specific MoEngage modules required for the application.\
**Note:** Version numbers are not required for these dependencies; the BOM automatically manages them.
```kotlin build.gradle.kts (Kotlin) wrap theme={null}
dependencies {
// -------------------------------------------------
// OPTIONAL MODULES (Add based on required features)
// -------------------------------------------------
// Cards Core - Required if using Cards Core APIs directly
implementation("com.moengage:cards-core")
// Cards UI - Required for Cards (feed) UI
implementation("com.moengage:cards-ui")
// Geofence - Required for Geofence-based campaigns
implementation("com.moengage:geofence")
// HMS Push Kit - Required for Huawei Push Notifications
implementation("com.moengage:hms-pushkit")
// InApp - Required for In-App Messaging
implementation("com.moengage:inapp")
// Inbox Core - Required if using Inbox Core APIs directly
implementation("com.moengage:inbox-core")
// Inbox UI - Required for Notification Center (Inbox) UI
implementation("com.moengage:inbox-ui")
// Push Amp - Required for Push Amplification
implementation("com.moengage:push-amp")
// Real Time Trigger - Required for device-triggered campaigns
implementation("com.moengage:realtime-trigger")
// Rich Notification - Required for Push Templates
implementation("com.moengage:rich-notification")
// Security - Required for Security features, for example; storage encryption
implementation("com.moengage:security")
}
```
**Info**
While MoEngage strongly recommends using the BOM for seamless dependency management, you can opt to manually configure versions for each artifact. If you choose this approach, you must ensure that the versions of all integrated modules are compatible with one another.
To find the latest versions and compatible artifact combinations, please refer to the [Installing SDK using Artifact Id](/android-sdk/sdk-integration/advanced-or-optional/installing-sdk-using-artifact-id).
## Add Androidx Libraries
The SDK depends on a few Androidx libraries for its functioning. Add the below Androidx libraries in your application if not done already.
```groovy Groovy wrap theme={null}
implementation("androidx.core:core:1.15.0")
implementation("androidx.appcompat:appcompat:1.7.1")
implementation("androidx.lifecycle:lifecycle-process:2.8.7")
```
The MoEngage SDK depends on the **lifecycle-process** library for a few key features to work and the latest version of **lifecycle-process** depends on the **androidx.startup:startup-runtime** library. Hence do not remove the **InitializationProvider** component from the manifest. When adding other Initializers using the **startup-runtime** ensure the Initializer for **lifecycle-process** library is also added. Refer to the [documentation](https://developer.android.com/jetpack/androidx/releases/lifecycle#2.4.0) to know how to add the Initializer.
## Impact of using BOM
Using the BOM does not increase the application size. It functions strictly as a version manager to ensure compatibility. Only the specific modules included in the `dependencies` block (e.g., `push-kit`, `android-sdk`) are bundled into the application.
## Why use BOM?
* **Simplified Versioning:** Eliminates the need to manage individual artifact versions. Updating the BOM version updates the entire integration.
* **Compatibility:** The BOM ensures that all integrated modules work efficiently together, preventing runtime crashes caused by mismatched library versions.
* **Cleaner Configuration:** Maintains a clean `build.gradle` file with a single source of truth for the SDK version.
# Configuring Build Settings
Source: https://moengage.com/docs/developer-guide/android-sdk/sdk-integration/basic-integration/configuring-build-settings
Configure your Android project build settings by adding the Maven repository and enabling Java 8.
## Add Maven Repository
Add `mavenCentral()` repository in the project-level `build.gradle` file.
```Groovy Groovy wrap theme={null}
buildscript {
repositories {
mavenCentral()
}
}
allprojects {
repositories {
mavenCentral()
}
}
```
## Enable Java 8
The SDK is target and source compatible with version 8 of the Java Programming Language. Enable Java 8 in the application `build.gradle(.kts)` if not done already.
```Groovy build.gradle wrap theme={null}
android {
...
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
```
```Kotlin build.gradle.kts theme={null}
android {
...
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
}
```
For more information about samples, refer to the [Android Sample](https://github.com/moengage/Android-Sample).
# Data Center
Source: https://moengage.com/docs/developer-guide/android-sdk/sdk-integration/basic-integration/data-center
Configure data center redirection in the MoEngage Android SDK to comply with your data policies.
# Data Redirection
If your app needs to redirect data to a specific zone due to a data regulation policy, please configure the zone in the MoEngage initializer object. Use the [*setDataCenter()*](https://moengage.github.io/android-api-reference/core/com.moengage.core/-mo-engage/-builder/set-data-center.html) in the [*MoEngage.Builder*](https://moengage.github.io/android-api-reference/core/com.moengage.core/-mo-engage/-builder/index.html) to specify the data center.
```kotlin Kotlin wrap theme={null}
// this is the instance of the application class and "XXXXXXXXXXX" is the APP ID from the dashboard.
val moEngage = MoEngage.Builder(this, "XXXXXXXXXXX")
.setDataCenter([YOUR_DATA_CENTER])
.build()
MoEngage.initialiseDefaultInstance(moEngage)
```
```java Java theme={null}
// this is the instance of the application class and "XXXXXXXXXXX" is the APP ID from the dashboard.
MoEngage moEngage = new MoEngage.Builder(this, "XXXXXXXXXXX")
.setDataCenter([YOUR_DATA_CENTER])
.build();
MoEngage.initialiseDefaultInstance(moEngage);
```
The following details the different data centers and dashboard hosts
| Data Center | Dashboard host |
| --------------- | ------------------------- |
| DATA\_CENTER\_1 | dashboard-01.moengage.com |
| DATA\_CENTER\_2 | dashboard-02.moengage.com |
| DATA\_CENTER\_3 | dashboard-03.moengage.com |
| DATA\_CENTER\_4 | dashboard-04.moengage.com |
| DATA\_CENTER\_5 | dashboard-05.moengage.com |
**Important**
The dashboard host URL provides the Data Center information of your account. Ensure that you contact your account manager or [raise a support ticket](https://help.moengage.com/hc/en-us/articles/19708702327572-Raise-a-Support-Ticket-Through-MoEngage-Dashboard) to know the data center before you change the data center in the Android SDK.
# Exclude MoEngage Storage File from Auto-Backup
Source: https://moengage.com/docs/developer-guide/android-sdk/sdk-integration/basic-integration/exclude-mo-engage-storage-file-from-auto-backup
Exclude MoEngage storage files from Android auto-backup to prevent data corruption after restore.
Mandatory integration step to prevent data corruption.
Auto backup service of Android periodically backs up the Shared Preference file, Database files, and so on.
For more information, refer to [Auto Backup](https://developer.android.com/guide/topics/data/autobackup).
The backup results in MoEngage SDK identifiers to be backed up and restored after re-install. The restoration of the identifier results in your data being corrupted and the user not being reachable using push notifications.
To ensure data is not corrupted after a backup is restored, opt-out of MoEngage SDK storage files.
# Add a backup descriptor in the *application* tag of the Manifest file.
The backup descriptor should be assigned to *fullBackupContent* attribute of the *application* tag.
```xml AndroidManifest.xml wrap theme={null}
```
# Exclude MoEngage Files in the descriptor file.
Exclude the following database file and shared preference file in the descriptor to ensure these files are ***not*** backed up.
```xml XML wrap theme={null}
```
If you only want to exclude files only from MoEngage SDK instead of creating a new file you can directly add the backup descriptor file provided by the SDK to the manifest file as shown below.
```xml AndroidManifest.xml wrap theme={null}
```
For applications with **targetSdkVersion** 31 or above exclusion has to be done in the new format as well.
# Exclusion for API level 31 or above
## Add manifest flag
Declare the new configuration file in the manifest file as shown below.
```xml XML wrap theme={null}
```
# Exclude MoEngage Files in the configuration file.
You can exclude MoEngage files from the configuration as shown below
```xml XML wrap theme={null}
...
...
...
```
If you only want to exclude files only from MoEngage SDK, instead of creating a new file, you can directly add the backup descriptor file and data extraction rules file provided by the SDK to the manifest file, as shown below.
```xml AndroidManifest.xml wrap theme={null}
```
# SDK Initialization
Source: https://moengage.com/docs/developer-guide/android-sdk/sdk-integration/basic-integration/sdk-initialization
Initialize the MoEngage Android SDK in your Application class using your Workspace ID and data center.
# SDK Configuration
Get the Workspace ID from the Settings Page of the dashboard **Dashboard** --> **Settings** --> **App** --> **General** on the MoEngage dashboard and initialize the MoEngage SDK in the Application class `onCreate()`.
**Note** Initialize the SDK on the main thread inside `onCreate()` and not create a worker thread and initialize the SDK on that thread.
```kotlin Kotlin wrap theme={null}
import com.moengage.core.DataCenter
import com.moengage.core.MoEngage
val moEngage = MoEngage.Builder(this, "YOUR_Workspace_ID", DataCenter.DATA_CENTER_X)
.build()
//replace X with your data center number
MoEngage.initialiseDefaultInstance(moEngage)
```
```java Java theme={null}
import com.moengage.core.DataCenter;
import com.moengage.core.MoEngage;
MoEngage moEngage = new MoEngage.Builder(this, "YOUR_Workspace_ID", DataCenter.DATA_CENTER_X)
.build();
MoEngage.initialiseDefaultInstance(moEngage);
```
In your MoEngage account, if your [portfolio](https://help.moengage.com/hc/en-us/articles/40394603054100-Portfolio) is configured with multiple projects, use the methods as shown below.
```kotlin Kotlin wrap theme={null}
val moEngageBuilder = MoEngage.Builder(this, "YOUR_MOENGAGE_APP_ID", DataCenter.DATA_CENTER_1)
.configureProject(ProjectConfig(""))
//replace with your ProjectID
```
```java Java theme={null}
MoEngage.Builder moEngageBuilder = new MoEngage.Builder(this, "YOUR_MOENGAGE_APP_ID", DataCenter.DATA_CENTER_1)
.configureProject(new ProjectConfig(""));
//replace with your ProjectID
```
Following details of the different data centers you need to set based on the dashboard hosts:
| Data Center | Dashboard host |
| :------------------------- | :------------------------ |
| `DataCenter.DATA_CENTER_1` | dashboard-01.moengage.com |
| `DataCenter.DATA_CENTER_2` | dashboard-02.moengage.com |
| `DataCenter.DATA_CENTER_3` | dashboard-03.moengage.com |
| `DataCenter.DATA_CENTER_4` | dashboard-04.moengage.com |
| `DataCenter.DATA_CENTER_5` | dashboard-05.moengage.com |
| `DataCenter.DATA_CENTER_6` | dashboard-06.moengage.com |
For more information about the detailed list of possible configurations, refer to the [API reference](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]-mo-engage/-builder/index.html).
**Critical** All the configurations are added to the builder before initialization. If you are calling initialize at multiple places, ensure that all the required flags and configurations are set each time you initialize to maintain consistency in behavior.
# Data Flow
SDK detects the build type of the installed application and the basis that it decides whether data should be sent to the Test/Live Environment of the MoEngage Platform.
* UnSigned/Debug Build — Data flows to Test environment
* Signed/Live Build — Data flows to Live environment.
# How to fix Token Drop?
Source: https://moengage.com/docs/developer-guide/android-sdk/troubleshooting-and-faqs/how-to-fix-token-drop
Learn why push token drops occur in your Android app and how to fix them for reliable delivery.
# What is a token drop?
Token drop is a situation or case where the MoEngage Platform does not have push tokens for all the users of your application.\
Say your application is installed by 100 new users every day but there are tokens for only 60 users on the MoEngage Platform, this is regarded as a token drop.
# Why is it important to fix it?
To send out a push notification to your end-users push token is required, without a token push cannot be sent. Hence to keep your users engaged it is very important to fix the token drop.
# Why does token drop occur?
Token drop can happen because of various reasons:
* Poor/No Internet connectivity which results in Firebase SDK not generating the token.
* Play services version mismatch, play services version on the device isn't compatible with the Firebase version used in the application
* Application has some internal check/flag based on which they decide whether to pass the token to the MoEngage SDK and during the token generation that flag is disabled hence token isn't passed to MoEngage SDK.
* Integration Error, push token is not being passed to the MoEngage SDK.
# How to fix it?
* If the token is not available on App-Open, deploy a retry mechanism where the application periodically attempts to generate a token till a token is successfully generated.
* If you have any check before passing the token to MoEngage SDK please remove it or keep the flag enabled by default to ensure tokens are passed on the first app open itself.
* Revisit the [Push Notification](/developer-guide/android-sdk/push/basic/push-configuration) to check if the implementation for the passing token is properly done.
# Suggestions for retry Mechanism
We recommend the application attempts to generate a push token on every App-Open and pass it to the MoEngage SDK. In case the app does not get the token from the Firebase API for any reason, the should attempt to register for push again periodically till the registration is successful or till the application is foreground.\
You can refer to this [library](https://github.com/umang91/fcm-client-lib) as an example of how to set up a retry mechanism. Alternatively, you can use this library instead of setting the mechanism yourself.
* This is not an official library from MoEngage; this library is built by one of the developers at MoEngage.
* MoEngage SDK already has a retry mechanism built to reduce token drop. We recommend you use MoEngage SDK's token registration to ensure no or minimal token drop(less than 2%). Refer to the [Push Notification](/developer-guide/android-sdk/push/basic/push-configuration) documentation to learn more about how you let MoEngage SDK handle your Push token.
# How to share Android MoEngage SDK logs
Source: https://moengage.com/docs/developer-guide/android-sdk/troubleshooting-and-faqs/how-to-share-android-moengage-sdk-logs
Enable and share verbose MoEngage Android SDK logs with the support team to resolve issues faster.
Sometimes, our support team will ask for logs as the first step to resolve the issue faster. Logs can help us and in some cases you quickly identify the issue and share the exact solution to a problem.
In this document, we list a few steps that you can execute to share the MoEngage SDK logs with the MoEngage support team.
## Enable debug logs
MoEngage SDK logs are best read in verbose format, which prints almost all the steps the SDK takes at any given time. You must first enable verbose-level logging by following this documentation and changing the initialization code a bit.
```Kotlin Kotlin wrap theme={null}
val moEngage = MoEngage.Builder(this, "YOUR_Workspace_ID")
.configureLogs(LogConfig(LogLevel.VERBOSE, true))
.build()
```
```Java Java theme={null}
MoEngage moEngage = new MoEngage.Builder(this, "YOUR_Workspace_ID")
.configureLogs(new LogConfig(LogLevel.VERBOSE, true))
.build();
```
```ReactNative ReactNative theme={null}
MoEngage moEngage = new MoEngage.Builder(this, "YOUR_Workspace_ID")
.configureLogs(new LogConfig(LogLevel.VERBOSE, true))
```
```Flutter Flutter theme={null}
MoEngage moEngage = new MoEngage.Builder(this, "YOUR_Workspace_ID")
.configureLogs(new LogConfig(LogLevel.VERBOSE, true))
```
Ensure to remove the above lines before the application is pushed to production.
## Android Studio
We will list the steps for sharing logs in Android Studio here, but similar steps apply to other IDEs.
1. First, connect your device to your laptop/PC.
2. Open Android Studio and click on Logcat.
3. Type MoE in the search field to filter only MoEngage logs(Please make sure the device is showing in device details and the correct device is shown).
4. MoEnage SDK-related logs should look like something shown in the picture below.
5. Copy the required lines or all lines in the Logcat, paste them on a text file, and share the file with MoEngage support team.
## Essential Logs
When browsing the logs, you can search for a few keywords to understand what is happening with the various services that MoEngage offers. Please note that verbose logs for MoEngage SDK has to be enabled for keywords to show up.
### Data tracking
**Search string** - sdk/report
**Occurrence** - You can see this string multiple times, and this log gets printed when the app is gone to the background and killed state. There are other cases when this log can be printed, but we will stick to these two conditions for now as we can easily perform background or kill actions. This line is seen 3 seconds after the app goes into the background or killed state.
**Description**
This log line indicates that the API call has been made to MoEngage servers and has succeeded. This API call is dependent on the proper integration of the lifecycle process. You might not see this line when the app goes into the background or killed state if the lifecycle observer isn't properly registered. Troubleshooting article - [How to debug lifecycle issues](/developer-guide/android-sdk/troubleshooting-and-faqs/troubleshooting-and-faqs#Why-is-lifecycle-process-library-important?).
### Push Token
**Search string** - push\_id
**Occurrence** - This string **push\_id** can be seen in sdk/report API call as part of the params. There are other cases when push\_id is sent to MoEngage servers, but since we can easily take the app to background state, we are mentioning only this case here.
**Description**
If this parameter is present and not empty, it indicates that the push token was properly acquired by MoEngage SDK and synced with MoEngage backend servers. You might not see push\_id or empty value if there are problems with your FCM project setup. Please go through the [push integration](/developer-guide/android-sdk/push/basic/push-configuration) steps properly.
### InApps - Sync
**Search string** - inapp/live and find get the line that has getResponse()
**Occurrence** - When the app is opened from the killed state. There are other cases when this API call is made, but we can easily kill the app and open it to see this call, so we are mentioning only this case here.
**Description**
This log line indicates that MoEngage SDK has made an API call to its backend servers to fetch the valid InApps or Nudges for the user. This API call is essential for InApps or Nudges to work as expected and depends on properly registering the lifecycle process. If you don't see this call once you open the app from killed state, go through the troubleshooting article here - [How to debug lifecycle issues.](/developer-guide/android-sdk/troubleshooting-and-faqs/troubleshooting-and-faqs#Why-is-lifecycle-process-library-important?)
### InApps - display not shown
**Search string** - Cannot show
**Occurrence** - This string can be seen when the MoEngage SDK can't show the InApp.
**Description**
This log line indicates that Inpps aren't shown to the user, and the reason for not showing the InApp is also mentioned at the end of the log line.
### Exceptions
While browsing through MoEngage SDK logs, you might encounter error/exception logs, as shown in the above image. It's important to ensure no such logs for smoother integration of MoEngage SDK. Kindly contact our team via support tickets to identify the fix for these issues. We are also listing some common exceptions and their fixes [here](/developer-guide/android-sdk/troubleshooting-and-faqs/troubleshooting-exceptions).
# How To Use the MoEngage SDK Logger?
Source: https://moengage.com/docs/developer-guide/android-sdk/troubleshooting-and-faqs/how-to-use-the-moengage-sdk-logger
Use the MoEngage SDK logger from your dashboard to debug implementation issues without sharing builds.
### Instructions:
Perform the following steps:
1. Log in to your MoEngage dashboard.
2. Go to the **Test and Debug** section.
3. Select the **SDK logger** tab, and a QR code will appear.
By default, the logger session remains active for two hours. You can extend it from your test mobile device.
The MoEngage SDK logger is supported from the following SDK versions:
* Android SDK 13.04.00
* React Native SDK 10.3.0
* Flutter SDK 9.0.0
* Capacitor SDK 5.0.0
* Cordova SDK 9.0.0
4. To start the logger, scan the QR code with your mobile device. A pop-up will appear with a link.
5. Open the link and click the **Click here** button. The link will either open the app or display a list of applications integrated with the MoEngage SDK.
6. Select the application you want to debug. A page displaying logger information will load.
7. Close and reopen the app. Perform the steps to replicate the issue.
8. Return to the dashboard and click **Refresh** to view a list of all active sessions.
9. Select the latest session identified by your device model.
10. If the logs do not appear, click **Refresh** again. Once the logs appear, click **Copy Session ID** and share the ID with the MoEngage support team for debugging.
A developer could check the logs for any errors or exceptions. You can also use the search field to find specific logs.
# Troubleshooting and FAQs
Source: https://moengage.com/docs/developer-guide/android-sdk/troubleshooting-and-faqs/troubleshooting-and-faqs
Find answers to common MoEngage Android SDK questions about debugging, logging, and integration.
In this article, we will address some common questions and some troubleshooting steps.
## How To Use the MoEngage SDK Logger?
SDKLogger will help you debug the MoEngage Android SDK implementation issues. You don't have to share the builds with our support team. You can just replicate the issue with the SDKlogger switched on, and share the session id with us for further help. We estimate that this logger will help us reduce the resolution times by about 2 days on an average.
The MoEngage SDK logger is supported from the following SDK versions:
* Android SDK 13.04.00
* React Native SDK 10.3.0
* Flutter SDK 9.0.0
* Capacitor SDK 5.0.0
* Cordova SDK 9.0.0
To use the MoEngage SDK logger, refer to [How To Use the MoEngage SDK Logger?](/developer-guide/android-sdk/troubleshooting-and-faqs/how-to-use-the-mo-engage-sdk-logger)
## How to enable MoEngage SDK to debug logs for signed/unsigned builds?
In order to see the verbose level logs, kindly add verbose log config in the initilisation.
```Kotlin Kotlin wrap theme={null}
val moEngage = MoEngage.Builder(this, "YOUR_APP_ID")
.configureLogs(LogConfig(LogLevel.VERBOSE, true))
.build()
```
```Java Java theme={null}
MoEngage moEngage = new MoEngage.Builder(this, "YOUR_APP_ID")
.configureLogs(new LogConfig(LogLevel.VERBOSE, true))
.build();
```
```Java ReactNative theme={null}
MoEngage moEngage = new MoEngage.Builder(this, "YOUR_APP_ID")
.configureLogs(LogConfig(LogLevel.VERBOSE, true))
```
```Java Flutter theme={null}
MoEngage moEngage = new MoEngage.Builder(this, "YOUR_APP_ID")
.configureLogs(LogConfig(LogLevel.VERBOSE, true))
```
Ensure to remove the above lines before the application is pushed to production.
## Why can't I see data on the dashboard?
If you don't see data on the dashboard check if you have implemented the below steps correctly
* Initialize the SDK correctly. For more information about initialization verification, refer to [SDK Initialization](/developer-guide/android-sdk/sdk-integration/basic-integration/sdk-initialization).
* Verify if you checking in the right environment.
Test/Debug Build --> Data flows to Test environment\
Signed/Live Build --> Data flows to Live environment.
## How to use Contextual InApps in React Nativ?
## How to use Contextual InApps for specific screens in the Flutter application?
## Why are events visible on test environment but not on the live environment?
If the data is visible on the Test environment and not in the Live environment, most likely you are using a test/debug build.\
The SDK detects whether the build is a debug/test build or a signed build. Based on the type of build data is sent to the respective environment.
Test/Debug Build --> Data flows to Test environment\
Signed/Live Build --> Data flows to Live environment.
## How does the SDK decide whether data should be sent to Test/Live Environment?
SDK detects the build type of the installed application and the basis that it decides whether data should be sent to the Test/Live Environment of the MoEngage Platform.
| Build Type | Environment |
| ---------- | ----------- |
| Debug | Test |
| Signed | Live |
## Why is lifecycle-process library important?
MoEngage SDK relies on lifecycle-process library for some key features like data syncing, inapps etc. Refer to [this](/developer-guide/android-sdk/sdk-integration/basic-integration/Install-Using-BOM) document to add the androidx libraries needed for lifecyle-process. If the features like in apps or data tracking aren't working as expected there are couple of troubleshooting steps we need to perform.
1. Check the MoEngage SDK logs and confirm that there is no exception related to the lifecycle process library.
2. Check your manifest file and ensure you aren't removing the Initialisation provider. You can read more here to properly handle the initialization provider [here](https://developer.android.com/jetpack/androidx/releases/lifecycle#2.4.0)
## Why is my App receiving the blank Push Notifications?
Blank push notifications can come up because of the following reasons :
1. Push from multiple servers not handled: Blank push notification if you don't handle push received from different servers correctly. Make sure the app does not try to show a notification if the notification is from MoEngage. For more information, refer to [Push Notification](/developer-guide/android-sdk/push/basic/push-configuration).
2. Custom Handling of notification: In case the app is doing some custom handling of notification make sure that silent push(used for uninstall ) is handled by the app.
## How to delete a notification from your inbox?
To delete a notification from Inbox, refer to [Notification Center](/developer-guide/android-sdk/push/optional/notification-center).
## Why are multiple notifications shown for one campaign?
Multiple Notifications can show up only if both the App and MoEngage SDK try to display the notification. If the payload is from MoEngage the App should pass the payload to the MoEngage SDK and not take any other action on it.\
For more information, refer to [Push Notification](developer-guide/android-sdk/push/basic/push-configuration).
## How to fix multiple receivers?
Multiple receivers are the scenario where the manifest contains multiple services with the intent filters: **com.google.firebase.MESSAGING\_EVENT**\
Ideally, your manifest file should contain only one service with the above intent filter. For more information, refer to [Push Notification](developer-guide/android-sdk/push/basic/push-configuration).
## Why does sending push fail?
Sending push can fail because of the following reasons :
1. No Active device token - Push token not passed to MoEngage SDK or refresh token not passed. For more information about how to pass push tokens, refer to [Push Notification](developer-guide/android-sdk/push/basic/push-configuration).
2. Not Registered - The application has been uninstalled hence cannot send push. Please re-install the application and try.
3. Mismatch Sender Id - The sender id and Server key provided are from different GCM/FCM projects. Please check the sender id and Server key. In the case of an FCM project sender-id is part of the `google-services.json` file.
4. Invalid Registration - The format of the push token passed is not correct. Please check the token passing logic.
## Why push is not visible even after it was successfully sent?
The following are the possible reasons for the push not being shown even after it was successfully sent :
* Push Payload not passed to MoEngage - This can happen when the app has its own push receiver and has not passed the payload to the MoEngage SDK. For more information, refer to [Push Notification](developer-guide/android-sdk/push/basic/push-configuration).
* Internet Connectivity - Please check your internet connectivity on the device. We would recommend you to toggle the network connection once and try.
* Device-Specific Issue - Some of the OEMs force stop the app when the application is removed from the recent/overview screen. Please ensure the application is running in the background.
* Build does not belong to the correct environment - The SDK detects whether the build is a debug/test build or a signed build. Based on the type of build data is sent to the respective environment.
* Small icon not added - To post a notification small icon is mandatory. Please make sure you have added the meta-data required for push notification. For more information, refer to [Push Notification](developer-guide/android-sdk/push/basic/push-configuration).
Test/Debug Build --> Use Test Environment to send notifications to your device.\
Signed/Live Build --> Use Live Environment to send notifications to your device.
## Why push is visible but clicks are not recorded?
The following are the reasons for click events not being recorded with MoEngage :
1. Push Payload not passed to SDK - The push payload is consumed by the application and the application takes care of showing push. This is based on the type of library you are using to pass the payload to MoEngage SDK.
2. Data not synced to MoEngage Server - Click attribution data would be sent to the MoEngage server only when the application is sent to the background. Please make sure that the application is sent to the background and wait for a couple of minutes.
## Why do we recommend letting MoEngage SDK handle push registration?
Push token registration is very important for sending push notifications.\
Push registration consists of two things - Token Registration and Refreshing Token\
Token registration can fail due to poor internet connection or null returned by the registration API. In such cases, one should retry registering for a push after an exponential backoff time rather than waiting for the next app to open.\
Refresh Token can be missed out because of some OEM level customizations. Many Chinese OEMs force stops the app once it is removed from the recent. This results in missing token refresh callbacks.\
MoEngage SDK has fallbacks to overcome the above issue. Hence, we suggest using MoEngage's Push Registration mechanism.\
MoEngage SDK provides a callback using which the app can get the push token. For more information, refer to [Push Registration by MoEngage](developer-guide/android-sdk/push/basic/push-configuration).
## Android Vitals says MoEAlarmReceiver is causing excessive wake-ups. Why is MoEngage using Alarms and waking up devices?
Android Vitals report all alarms used by the app. Generally, alarms are used to trigger background tasks like downloading/uploading data to the server, which wakes up the CPU if the device is in an idle state and causes battery drain.\
MoEngage SDK MoEAlarmReceiver is used to send tracked events and attributes to the MoEngage Server. This alarm is triggered within 3-5 seconds after the application goes to the background. Since the CPU does not sleep so quickly no additional battery drain is done here. Our SDK intentionally delays this sync by 3-5 seconds to ensure data accuracy due to certain customizations done by OEMs without the delay data accuracy becomes a problem.
## How can you get extras after redirection?
All the extra parameters passed along while campaign creation will be a part of the bundle extras if the activity is inflated via the activity name. If the activity is inflated using a deep link URL all extras will be a part of the query params of the URL.
## What is a token drop and how to fix it?
For more information, refer to the [How to fix Token Drop?](/developer-guide/android-sdk/troubleshooting-and-faqs/how-to-fix-token-drop)
## Failed resolution of: Landroidx/lifecycle/ProcessLifecycleOwner
```Java Java wrap theme={null}
java.lang.NoClassDefFoundError: Failed resolution of: Landroidx/lifecycle/ProcessLifecycleOwner;
at com.moe.pushlibrary.MoEHelper.r(:1005)
at com.moengage.core.MoEngage.a(:210)
```
If you are seeing the above stack trace you have missed out on adding the `androidx.lifecycle:lifecycle-process` dependency in your application.\
Add the `androidx.lifecycle:lifecycle-process` and the issue should be fixed. You can refer to the [SDK Integration](/developer-guide/android-sdk/sdk-integration/basic-integration/Install-Using-BOM) documentation to know more about the dependencies required by the SDK.
## Why are some of the components marked as `export=true` in the case of Xiaomi Push? Is it a security concern?
The following components need the flag export=true, otherwise, it will affect the basic push function:
`com.xiaomi.mipush.sdk.PushMessageHandler`
* On clicking the notification in the notification bar, before jumping to the app UI interface, the SDK first parses the intent content through PushMessageHandler and execute startActivity() to jump;
* The intent content is encrypted, and the forged intent cannot penetrate the decryption link, and there is no security problem;
`com.xiaomi.push.service.receivers.NetworkStatusReceiver`
* Receives system network change broadcast, notify and change the long connection status; because it is a system broadcast, there is no need to worry about the broadcast being forged;
`com.moengage.mi.MoEMiPushReceiver`
* Receives the result callback of registration, set an alias, subscribe, and other interfaces;
* Added permission protection, intent encryption protection, forged intents cannot penetrate the decryption link, and there is no security problem.
## Will initializing the SDK on the main thread affect my application start-up time?
No, the initialization API is The initialization approximately around 10-15 milliseconds on average. Refer to the [SDK Performance](/developer-guide/android-sdk/performance/sdk-performance) document for more details.
## Why MoEngage SDK is using setAllowFileAccess(true) in WebView settings?
MoEngage SDK uses WebView to load and display HTML InApps. Whenever ***MoEInAppHelper.getInstance().showInApp(context)*** is called, SDK downloads the dynamic Images, CSS & Other files used in the HTML InApps and stores them in the internal app storage, to load these assets into WebView from local storage setAllFileAccess(true) is needed.
## How can we disable/enable JavaScript in WebView?
By default, JavaScript usage is enabled in WebView.
```Kotlin Kotlin wrap theme={null}
configureJavascriptUsage(JavaScriptConfig(isJavaScriptEnabled))
```
```Java Java theme={null}
import static com.moengage.core.MoESdkStateHelper.configureJavascriptUsage;
configureJavascriptUsage(new JavaScriptConfig(isJavaScriptEnabled));
```
If you disable the JavaScript usage in WebView then RichLanding URLs & Html InApp may not render correctly on the device.
## Why SDK initialization should be done on the main thread inside the onCreate() of the Application class?
In general, any SDK should be initialized before any API/method of the SDK is called. MoEngage SDK is no different, before calling any API of the MoEngage SDK it is important that the SDK is initialized. If the SDK is not initialized Any data passed is the called API would be rejected by the SDK or if any API is expected to return data it would return ***null*** or default values(like false or -1).
For ease of implementation, we recommend the application initializes the MoEngage SDK in the ***onCreate()*** of the Application class. When we say in the onCreate() on the main thread we suggest synchronously not inside any callback etc. By initializing the SDK this way you can always ensure the SDK is initialized and ready for use anywhere in the application irrespective of the previous state. The Android system invokes \*\*\*onCreate()\*\*\*as one of the first few things on process creation. Hence initializing it in the \*\*\*onCreate()\*\*\*ensures SDK is always initialized and ready to process any events or campaigns.
This is especially important for cases when the application is in the killed state and a Push Campaign is sent to the user(the battery optimizations done by the OS and OEMs apps are killed within an hour or so of non-usage).
We understand that application start-up time is very important and if the SDK takes time to initialize it could affect the application experience. The initialization time of the SDK is minimum, refer to the [performance matrix](/developer-guide/android-sdk/performance/sdk-performance) to know more. We are continuously working on improving this further.
#### Alternatively,
Given any constraints, you cannot initialize the SDK in the \*\*\*onCreate()\*\*\*please ensure the SDK is initialized before any SDK API is called example, \*\*\*passPushPayload(), trackEvent(), etc.
If the SDK is not initialised method call would not be processed resulting in data being discarded or lower campaign delivery. SDK provides an API [isSdkInitialised()](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]is-sdk-initialised.html?query=fun%20isSdkInitialised\(\):%20Boolean) to check whether the SDK is initialized or not, use the API to check if the initialization is done and initialize if required.
If you are not initializing the SDK in the \*\*\*onCreate()\*\*\*of the Application class please ensure implementing the [IntentPreProcessingListener](https://moengage.github.io/android-api-reference/core/com.moengage.core.listeners/\[android-jvm]-intent-pre-processing-listener/index.html) and registering this listener using the [registerPreProcessingListener](https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]-mo-e-core-helper/register-pre-processing-listener.html) in the ***onCreate()*** and initialize the SDK in the ***onIntentRecieved()*** of the interface. This is important to process notification clicks when the application is in the killed state.
## How can I stack the notifications?
By default, Android replaces your old notification with a new one. If you want to show stacked notifications to the user, you can enable isMultipleNotificationInDrawerEnabled = true in the notification config during SDK initialization. Please refer to the [notification config](https://moengage.github.io/android-api-reference/core/com.moengage.core.config/\[android-jvm]-notification-config/index.html) for additional options.
## Should I stop GeoFencing once the app goes to the background?
MoEngage uses system triggers to detect the location of the user and when the user exits or enters the geofence. So, it's not advised to call to stop the geofence monitoring method when the app goes in the background. But if your business doesn't want to monitor in specific cases the geofence changes, then you can call to stop geofence monitoring. MoEngage doesn't additionally poll to detect the location changes of the user, so the battery isn't affected if you don't stop geofence monitoring on the App.
## Why is Timer Notification not working?
Ensure that you have added rich notification dependency and more importantly you need to add the following line in the manifest file. Please check the documentation [here](/developer-guide/android-sdk/push/optional/push-templates#Schedule-Exact-Alarm-Permission).
```markdown wrap theme={null}
```
Starting Android 14, you need to get explicit alarm permission from the customer, read more about it [here](https://developers.moengage.com/hc/en-us/articles/4403408116884-Push-Templates#h_01GC889AZ05PXD9A06VNC7N1EB).
## How can I add custom sound for push notifications?
From Android O, you can create a notification channel to which a custom sound can be added. However, you must do three things before you can get custom sounds for your notifications.
1. Add a custom channel to your app.
2. Add a sound to this custom channel.
3. Add the channel name in the MoEngage dashboard and use it while sending notifications.
We are providing the code for creating a custom channel and adding sound here.
```Kotlin Kotlin wrap theme={null}
private fun createCustomNotificationChannel(channelName: String) {
val channel = NotificationChannel(channelName, channelName, NotificationManager.IMPORTANCE_HIGH)
val soundUri = Uri.parse("android.resource://" + App.application?.packageName + "/" + R.raw.sound_file)
// sound_file will be added in the App's code
soundUri?.let {
val audioAttributes = AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_ALARM)
.build()
channel.setSound(soundUri, audioAttributes)
}
val manager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
manager.createNotificationChannel(channel)
}
```
## FAQs on the GAID policy changes.
### Which of the MoEngage SDK versions comply with the GAID policy changes?
| Android | ReactNative | Flutter | Cordova | Unity | Capacitor | Segment |
| --------------- | ----------- | ------- | ------- | ----- | --------- | ------- |
| 11.6.2 & >12.2+ | 7.4.1 | 4.2.0 | 7.3.3 | 2.3.0 | 1.0.2 | 6.2.0 |
### What is the GAID policy?
For information on the GAID policy, refer [here](https://help.moengage.com/hc/en-us/articles/7457641031828-Android-Advertising-ID-Tracking#what-is-the-policy--0-1).
### As a MoEngage client, how does the GAID policy impact me?
Please go through “**How does it affect my app?**” [here](https://help.moengage.com/hc/en-us/articles/7457641031828-Android-Advertising-ID-Tracking#what-is-the-policy--0-1).
### How do I track GAID?
Firstly, update the MoEngage SDK to a corresponding version of your framework. Note that you will need explicit consent from the user on GAID tracking.
### Can I be on a version \<11.6 if I am not tracking GAID?
No. When you try updating your app in the play store, Google flags your application for non compliance of the MoEngage SDK version. We recommend an update to the latest version of MoEngage SDK.
### Can I be on \<11.6 if I am not updating my app in the play store?
For now you can be on \<11.6.2. However, If and when Google starts scanning all the apps for invalid versions of SDK, they might flag your application for non compliance of the SDK version.
### What are the reasons for rejection and what should I do If my application gets rejected/warned by the Google Play store at the time of publishing?
We encourage developers (and others more broadly) to make sure they've addressed non-production tracks as well. Developers who receive a notification should ensure all active versions of the app in either track, production or non-production (Internal / Closed / Open testing), have moved off the non-aligned SDK version or removed the SDK. Developers can also resolve the issue by deactivating any tracks that contain an active version of the app that has not addressed the issue during new submission.
Share these standard step-by-step instructions to update a non-compliant version of an APK with developers.
1. Navigate to your Play Console.
2. Select the app.
3. Navigate to App bundle explorer.
4. Select the violating APK/app bundle's App version at the top right dropdown menu, and make a note of which releases they are under.
5. Go to the track with the violation.\
It will be one of these: Internal / Closed / Open testing or Production.
6. Click Create new release near the top right of the page(You may need to click Manage track first).\
If the release with the violating APK is in a draft state, discard the release.
7. Add the new version of app bundles or APKs.\
Make sure the non-compliant version of app bundles or APKs is under the Not included section of the current release.
8. Click Save. This saves changes made to your release.
9. When you've finished preparing your release, select Review release, and then proceed to roll out the release to 100%.
10. If the violating APK is released to multiple tracks, repeat steps 5-9 in each track.
For a more comprehensive overview, publishers can check out [this page](https://support.google.com/googleplay/android-developer/answer/9859348?hl=en\&ref_topic=7072031) for detailed guidance on how to prepare and roll out a release.
# Troubleshooting Exceptions
Source: https://moengage.com/docs/developer-guide/android-sdk/troubleshooting-and-faqs/troubleshooting-exceptions
Fix common MoEngage Android SDK exceptions related to in-app messages, lifecycle, and compatibility.
In this article, we will provide a fix for common exceptions.
# InApps
```text wrap theme={null}
java.lang.UnsupportedOperationException: Library support not found: Image and gif require Glide library.
```
Fix - Ensure you add the glide library dependencies mentioned in [this document](/developer-guide/android-sdk/troubleshooting-and-faqs/troubleshooting-in-app#In-Apps-aren't-rendering-on-the-screen-name-selected).
```text wrap theme={null}
InAppFileManager downloadAndSaveFiles() : java.io.FileNotFoundException: https://campaign-assets-01.moengage.com/inbound/inapp/html_inapp/campaigns/tbsa_02_uat_sit/1712731832516233_r0mai9/17127318325182123_2m2mil/#
```
Fix - HTML template is having some errors related to href links, Fix the template without any errors and you shouldn't see the above error in the logs.
# Lifecycle-process
```text wrap theme={null}
java.lang.NoSuchFieldError: No field Companion of type Landroidx/lifecycle/ProcessLifecycleOwner$Companion; in class Landroidx/lifecycle/ProcessLifecycleOwner; or its superclasses (declaration of 'androidx.lifecycle.ProcessLifecycleOwner' appears in /data/app/~~iQ1qllgGR8saPZQwzjFrZg==)
```
Fix - Ensure that Android core and lifecycle process libraries are compatible. You can find the right lifecycle process library version in the change log for your sdk. - For example - [React SDK changelog](/developer-guide/release-notes/react-native-sdk/changelog)
# Troubleshooting Images
Source: https://moengage.com/docs/developer-guide/android-sdk/troubleshooting-and-faqs/troubleshooting-images
Troubleshoot common image rendering issues in Android push notifications including icon problems.
In this article, we will address common questions on image rendering in Android push notifications and how to fix them.
## Why is the small icon not rendering properly in notifications?
The small notification icon may appear as a box or circle in some cases, as in the following image.
To render the small notification icon properly, ensure that the small notification icon is:
* flat
* pictured face-on
* of white color on a transparent background.
For more information, refer to [Small Notification Icon Guidelines](/developer-guide/android-sdk/push/basic/push-configuration) and [Android Notification Guidelines](https://m2.material.io/design/platform-guidance/android-notifications.html#anatomy-of-a-notification).
## Large Icon not rendering in Push Notifications
The large icon is not displayed in push notifications if
* The notification large icon is not in the initialization of the SDK. Please look at the [Push Configuration](/developer-guide/android-sdk/push/basic/push-configuration) documentation to check how to set the large icon.
* The download for the large icon configured in the campaign failed.
* You have explicitly disabled the large icon display in the notification configuration while integrating the SDK. Check if you have set the value of ***isLargeIconDisplayEnabled*** as false in the *NotificationConfig* object while initializing the SDK. Ensure the value is not set to false, else the large icon will not be displayed.
* The large icon display was disabled in the template settings for the campaign. Please check your campaign.
* The template does not support large icon. Please check the campaign preview.
# Troubleshooting In-App
Source: https://moengage.com/docs/developer-guide/android-sdk/troubleshooting-and-faqs/troubleshooting-in-app
Troubleshoot issues with MoEngage in-app messages not rendering or displaying correctly on Android.
This article will look at some of the most frequent problems encountered while using In-Apps and how to solve them.
## In-Apps aren't rendering as expected.
There are could be multiple reasons for InApps not rendering.
1. MoEngage SDK doesn't show the In-App by default, like push notifications. When you want to show the in-app, you must call the following line of code to show inapp for app open and screen based inapps. The only exception is custom event in-Apps; you need not call the following method for custom event in-Apps.\
[*MoEInAppHelper.getInstance().showInApp(context)*](https://moengage.github.io/android-api-reference/inapp/com.moengage.inapp/-mo-e-in-app-helper/show-in-app.html)
2. InApps are not shown when delivery controls aren't met or when some activities are opted out of the in-app optout config while initialising MoEngage SDK. If you have SDK logs enabled, you can see the reason in them.
3. Inapps are synced to the device because of life cycle library integration problems. Use the steps given [here](/developer-guide/android-sdk/troubleshooting-and-faqs/troubleshooting-and-faqs) to troubleshoot them.
4. Inapps couldn't be synced to the device because of the exception in some other library functionality of MoEngage, please check the error logs if you find anything here.
## In-Apps aren't rendering as expected on app open
When you create an In-app campaign with trigger criteria as **on App open**, you also need to ensure that the following code is called on the app's first screen open. You need to call this code in onResume() of the fragment or onStart() of the Activity.
[*MoEInAppHelper.getInstance().showInApp(context)*](https://moengage.github.io/android-api-reference/inapp/com.moengage.inapp/-mo-e-in-app-helper/show-in-app.html)
## In-Apps aren't rendering on the screen name selected
When you create an In-app campaign with trigger criteria as **on specific screen**, you also need to ensure that the following code is called on the screen name you selected. You need to call this code in onStart() of the Activity or onResume() of the fragment.
[*MoEInAppHelper.getInstance().showInApp(context)*](https://moengage.github.io/android-api-reference/inapp/com.moengage.inapp/-mo-e-in-app-helper/show-in-app.html)
## Test In-Apps showing "Something went wrong" error
There could be multiple reasons for this error.
* Glide dependency missing
To fix this error please ensure you are adding the glide libraries and also use MoEngage inapp version >= 7.1.4
### **Requirements for displaying images and GIFs in InApp**
Starting InApp version **7.0.0,** SDK requires [Glide](https://bumptech.github.io/glide/) to show images and GIFs in the in-apps. You need to add the below dependency in your **build.gradle** file.
```Groovy Groovy wrap theme={null}
dependencies {
...
implementation("com.github.bumptech.glide:glide:4.16.0")
}
```
# Troubleshooting Push Redirection
Source: https://moengage.com/docs/developer-guide/android-sdk/troubleshooting-and-faqs/troubleshooting-push-redirection
Resolve common issues with deep linking, push CTA buttons, and rich landing page redirection on Android.
This article will discuss the common issues faced during deep linking and clicking on push notifications.
## Deeplink Redirection isn't working
This could happen because you haven't configured an Activity in your manifest to handle the given deep link. Verify if the deep link is properly and is redirecting to the expected screen using the below adb command.
```text wrap theme={null}
adb shell am start
-W -a android.intent.action.VIEW
-d
```
If the navigation is not working as expected with the above command there is something wrong in the way the deep link is configured. Please refer to this [official documentation](https://developer.android.com/training/app-links/deep-linking) to configure deep links in your application.
## Click on the push notification CTA button isn't working
This can happen when you have a custom push listener apart from the default MoEngage handler. You would most likely be handling the default click on the push notification but did not implement the handling for clicking on the CTA button. Please add the CTA button click handling to ensure the behavior meets expectations.
## The rich landing page doesn't render the webpage / URL
As per Android official documentation, - WebView objects allow you to display web content as part of your activity layout but lack some of the features of fully-developed browsers.
Webview is used to load rich landing pages within the app, and since webview doesn't support all the features that a normal browser supports, there is a chance that your website isn't loading in the rich landing redirection.
To handle this case, kindly either make your web page compatible with Webview or redirect the user to the device browser using a custom push listener code.
## Click call backs aren't received on react-native, Flutter, Cordava
This can happen in hybrid frameworks implementation, and you have missed adding the initialization code.
MoEInitializer.initializeDefaultInstance(applicationContext, moEngage)
Kindly ensure the above line is in your code per the initialization instructions.
## Clicks on deep link open the app in Android 11 and the browser in Android 12
Starting in Android 12 (API level 31), a generic web intent resolves to an activity in your application only if your application is approved for the specific domain in that web intent. If your application isn't approved for the domain, the web intent resolves to the device's default browser. Please refer to the [official Google documentation](https://developer.android.com/training/app-links/verify-android-applinks) to know more on how to approve/verify your application for your domain.
# What Are the Scenarios Where the SDK Logger Is Not Usable?
Source: https://moengage.com/docs/developer-guide/android-sdk/troubleshooting-and-faqs/what-are-the-scenarios-where-the-sdk-logger-is-not-usable
Learn about scenarios where the MoEngage SDK logger cannot help, such as integration and UI issues.
The SDK logger may not function correctly in the following scenarios:
* **Basic integration issues**:
* **Improper SDK integration**: This occurs when the SDK is not integrated correctly.
* **Outdated SDK versions**: The SDK version is older than the following:
* Android SDK: Native 13.4.00
* React Native: 10.3.00
* Flutter: 9.0.0
* Cordova: 9.0.0
* Capacitor: 5.0.0
* **Integration misses**: The plugin is not being initialized in the locations (as per the requirement).
* **Data tracking**
* **Push notifications**:
* **Visibility or UI problems**: Push notifications are not rendering correctly on devices.
* **Image loading failures**: Images are not displayed in push notifications due to exceptions or unsupported image formats (for example, WebP Image file format).
* **PushAmp cases**: Situations where the system renders the push notification rather than the SDK rendering the same.
* **In-app messages**:
* **Display anomalies**: In-app messages or In-app nudges appear too small or large and do not match the dashboard specifications.
* **Behavioral conflicts**: In-app messages interfering with app functionality.
* **Context setting in hybrid apps**: Lack of screen tracking in hybrid frameworks as we only track Native screens.
* **Self-Handled In-app messages**: Integration validation through a call might be required to ensure accurate statistics tracking. The developer might not have integrated the required methods to track events and statistics.
* **Cards**:
* **Self-handled cards**: There could be potential integration oversights.
# Delete User From MoEngage Server
Source: https://moengage.com/docs/developer-guide/capacitor-sdk/data-tracking/delete-user-from-moengage-server
Delete the current user from the MoEngage server using the Capacitor SDK on Android.
This API is supported from **capacitor-moengage-core** version **3.1.0** and is only available for the Android platform and is a no-operation for other platforms.
To delete the current user from the MoEngage server use ***deleteUser()*** method as shown below
```javascript TypeScript theme={null}
import { MoECapacitorCore } from 'capacitor-moengage-core'
MoECapacitorCore.deleteUser({appId: "YOUR_WORKSPACE_ID"}, (userDeletionData) = {
// add your code to handle the callback.
console.log(this.tag + " deleteUser(): workspaceId: " + userDeletionData.accountMeta.appId + " isSuccess=" + userDeletionData.isSuccess)
})
```
# Enable Advertising Identifier Tracking
Source: https://moengage.com/docs/developer-guide/capacitor-sdk/data-tracking/enable-advertising-identifier-tracking
Enable advertising identifier tracking in your Capacitor app for accurate device analytics.
For accurate analytics around devices and tracking Re-installs, it is essential to track the Advertising Identifier.
## Add Ad Identifier Library
Add the below dependency in the application-level ***build.gradle*** file.
```groovy Groovy theme={null}
implementation("com.google.android.gms:play-services-ads-identifier:18.0.1")
```
To enable Advertising Identifier tracking use the *enableAdIdTracking()* method as shown below.
```javascript TypeScript theme={null}
import { MoECapacitorCore } from 'capacitor-moengage-core'
MoECapacitorCore.enableAdIdTracking({ appId: "YOUR_WORKSPACE_ID" });
```
Before you enable Advertising ID tracking please ensure the application is complying with the [Google Play Policy](https://support.google.com/googleplay/android-developer/answer/10144311) regarding Advertising ID tracking. Refer to our [help document](https://help.moengage.com/hc/en-us/articles/7457641031828) for more information on the policy.
In case, you need to disable advertising-id after enabling tracking use the following method.
```javascript TypeScript theme={null}
import { MoECapacitorCore } from 'capacitor-moengage-core'
MoECapacitorCore.disableAdIdTracking({ appId: "YOUR_WORKSPACE_ID" });
```
The above APIs are available only starting plugin version 1.0.2. In the older versions, Advertising Identifier tracking is enabled by default.
# Install/Update Differentiation
Source: https://moengage.com/docs/developer-guide/capacitor-sdk/data-tracking/install-update-differentiation
Set the app status as install or update in the MoEngage Capacitor SDK for migration tracking.
This is solely required for migration to the MoEngage Platform. We need your help to tell the SDK whether the user is a new user of your app or an existing user who has updated to the latest version. If the user was already using your application and has just updated to a new version which has MoEngage SDK it is an updated , call the below API.
```javascript TypeScript theme={null}
import { MoECapacitorCore, MoEAppStatus } from 'capacitor-moengage-core'
// For Existing user who has updated the app
MoECapacitorCore.setAppStatus({ appStatus: MoEAppStatus.UPDATE, appId: "YOUR_WORKSPACE_ID" });
```
In case it is a fresh install call the below API
```javascript TypeScript theme={null}
import { MoECapacitorCore, MoEAppStatus } from 'capacitor-moengage-core'
//For Fresh Install of App
MoECapacitorCore.setAppStatus({ appStatus: MoEAppStatus.INSTALL, appId: "YOUR_WORKSPACE_ID" });
```
# Tracking Events
Source: https://moengage.com/docs/developer-guide/capacitor-sdk/data-tracking/tracking-events
Track user actions and event properties using the MoEngage Capacitor SDK for segmentation and campaigns.
SDK adheres to the MoEngage FUP policies. For more information, refer to the [Fair Usage Policy](https://help.moengage.com/hc/en-us/articles/24151864954644-Fair-Usage-Policy-FUP#h_01HQSMZVQWT2KYP0PY1P8GQMRM).
Tracking events is how you record any actions your users perform, along with any properties that describe the action. Every trackEvent call records a single user action. We recommend that you make your event names human-readable so that everyone on your team can know what they mean instantly.
Every **trackEvent()** method call expects 3 parameters. They are the event name, event attributes and an account identifier. Event attributes use **MoEProperties** as an instance that represents attributes of the event. Add all the additional information which you think would be useful for segmentation while creating campaigns.\
For example, the following code tracks an **Purchase** event of a product. We are including attributes like price, quantity, purchase date, and store location which describe the event we are tracking.
```javascript TypeScript theme={null}
import { MoECapacitorCore, MoEProperties } from 'capacitor-moengage-core'
const properties: MoEProperties = {
generalAttributes: [
{ name: "quantity", value: 1 },
{ name: "product", value: "iPhone" },
{ name: "currency", value: "dollar" }
{ name: "price", value: 699 }
{ name: "new_item", value: "iPhone" }
],
dateTimeAttributes: [
{ name: "purchase_date", value: "2020-06-10T12:42:10Z" }
],
locationAttributes: [
{ name: "store_location", value: { latitude: 90.00001, longitude: 180.00001} }
]
};
MoECapacitorCore.trackEvent({ eventName: "Purchase", eventAttributes: properties, appId: "YOUR_WORKSPACE_ID"});
```
* Event names should not contain any special characters other than "\_". It can contain just spaces and underscore. Also, it should not contain “between”, “greater”, “less”, “in\_the\_last”, “in\_the\_next”, “equal”, “contains”, “starts”, or “is\_not".
* You can not use "moe\_" as a prefix while naming events, event attributes, or user attributes. It is a system prefix and using it might result in periodic blacklisting without prior communication.
# Analytics
MoEngage SDK has started tracking user sessions and application traffic source. Refer to the [Sessions in MoEngage Analytics](https://help.moengage.com/hc/en-us/articles/35724347745812-Session-and-Source-Overview) and [Source Analysis in MoEngage Analytics](https://help.moengage.com/hc/en-us/articles/35724347745812-Session-and-Source-Overview) to learn more about how user session and application traffic source tracking works.
With user session tracking we have introduced the flexibility to selectively mark events as non-interactive.
## What is a non-interactive event?
Events that do not affect the session calculation in anyways are called non-interactive events. Non-interactive events have the following properties
* Do not start a new session.
* Do not extend the session.
* Do not have information related to a user session.
## How to mark an event as non-interactive?
To mark an event as a non-interactive set **isNonInteractive** property of the **MoEProperties** to **true** as shown below:
```javascript TypeScript theme={null}
import { MoECapacitorCore, MoEProperties } from 'capacitor-moengage-core'
const properties: MoEProperties = {
generalAttributes: [
{ name: "quantity", value: 1 },
{ name: "product", value: "iPhone" },
{ name: "currency", value: "dollar" }
{ name: "price", value: 699 }
{ name: "new_item", value: "iPhone" }
],
dateTimeAttributes: [
{ name: "purchase_date", value: "2020-06-10T12:42:10Z" }
],
locationAttributes: [
{ name: "store_location", value: { latitude: 90.00001, longitude: 180.00001} }
],
isNonInteractive: true
};
MoECapacitorCore.trackEvent({ eventName: "Purchase", eventAttributes: properties, appId: "YOUR_WORKSPACE_ID" });
```
# Tracking User Attributes
Source: https://moengage.com/docs/developer-guide/capacitor-sdk/data-tracking/tracking-user-attributes
Track user attributes and manage login and logout states using the MoEngage Capacitor SDK.
User Attributes are pieces of information you know about a user which could be demographics like age or gender, account-specific like plan, or even things like whether a user has seen a particular A/B test variation. It's up to you! It is basically a customer identity that you can reference across the customer’s whole lifetime.
# Implementing Login/Logout
* It's important to set the User Attribute Unique ID when a user logs into your app.
* This is to merge the new user with the existing user, if any exists, and will help prevent creation of unnecessary/stale users.
* Setting the Unique ID is a critical piece to tie a user across devices and installs/uninstalls as well across all platforms (i.e. iOS, Android, Windows, The Web). Set the **USER\_ATTRIBUTE\_UNIQUE\_ID** attribute as soon as the user is **logged in**. Unique ID can be something like an email ID, a username (unique), or a database ID or any Backend generated ID.
* Do not set this for the user who not logged in.
## Login
```javascript TypeScript theme={null}
import { MoECapacitorCore } from 'capacitor-moengage-core'
MoECapacitorCore.setUniqueId({ uniqueId: "abc@xyz.com", appId: "YOUR_WORKSPACE_ID"});
```
**Note:** The following values are not allowed in the UniqueID field: "unknown", "guest", "null", "0", "1", "true", "false", "user\_attribute\_unique\_id", "(empty)", "na", "n/a", "", "dummy\_seller\_code", "user\_id", "id", "customer\_id", "uid", "userid", "none", "-2", "-1", "2"
## Logout
The application needs to notify the MoEngage SDK whenever the user is logged out of the application. To notify the SDK, call the API whenever the user is logged out of the application.
```javascript TypeScript theme={null}
import { MoECapacitorCore } from 'capacitor-moengage-core'
MoECapacitorCore.logoutUser({ appId: "YOUR_WORKSPACE_ID"});
```
In case the application is registering for push token it should pass the new push token to MoEngage SDK after user logout. For more information about passing push tokens, refer to [Push Configuration for Android SDK](/developer-guide/android-sdk/push/basic/push-configuration).
## Updating User Attribute Unique Id
Use the method *setAlias()* to update the user attribute unique id instead of *setUniqueId()* with a different value. Using the method *setUniqueId()* with a new value creates unintended users in MoEngage.
You can not use "moe\_" as a prefix while naming events, event attributes, or user attributes. It is a system prefix and using it might result in periodic blacklisting without prior communication.
Use the following helper methods to set User attributes like Name, Email, Mobile, Gender, etc.
```javascript TypeScript theme={null}
import { MoECapacitorCore, MoEProperties, MoEUserGender, MoEAppStatus } from 'capacitor-moengage-core'
MoECapacitorCore.setUserName({ userName: "John Doe", appId: "YOUR_WORKSPACE_ID" });
MoECapacitorCore.setFirstName({ firstName: "John", appId: "YOUR_WORKSPACE_ID" });
MoECapacitorCore.setLastName({ lastName: "Doe", appId: "YOUR_WORKSPACE_ID" });
MoECapacitorCore.setEmailId({ emailId: "johndoef@xyz.com", appId: "YOUR_WORKSPACE_ID" });
MoECapacitorCore.setMobileNumber({ mobileNumber: "1234567890", appId: "YOUR_WORKSPACE_ID" });
MoECapacitorCore.setGender({ gender: MoEUserGender.FEMALE, appId: "YOUR_WORKSPACE_ID" });
MoECapacitorCore.setBirthDate({ birthdate: "1970-01-01T12:00:00Z", appId: "YOUR_WORKSPACE_ID" });
MoECapacitorCore.setUserLocation({ location: { latitude: 25.2311, longitude: 73.1023 }, appId: "YOUR_WORKSPACE_ID" });
```
For setting other User Attributes you can use the generic method **setUserAttribute(key, value)**
To set custom user attributes, you will have to provide the attribute name as shown below:
```javascript TypeScript theme={null}
import { MoECapacitorCore } from 'capacitor-moengage-core'
// For generic user attributes
MoECapacitorCore.setUserAttribute({ name: "Attribute Name", value: "AttributeValue", appId: "YOUR_WORKSPACE_ID" });
// For Time attribute use ISO-8601 format
MoECapacitorCore.setUserAttributeDate({ name: "Date Attribute Name", value: "1970-01-01T12:00:00Z", appId: "YOUR_WORKSPACE_ID" });
// For Location, use MoEGeoLocation instance
MoECapacitorCore.setUserAttributeLocation({ name: "Location Attribute Name", location: { latitude: 25.23, longitude: 73.23 }, appId: "YOUR_WORKSPACE_ID" });
```
## Custom Boolean User Attribute
### iOS
Starting from version **5.x.x** of **capacitor-moengage-core**, the default tracking for the custom boolean attribute will be changed to boolean from double. To configure this, use ***MoEAnalyticsConfig*** and pass true to track the boolean as double or pass false to track it as a boolean.
Refer to the initialization code snippet below.
```javascript TypeScript theme={null}
import { MoECapacitorCore, MoEAnalyticsConfig, MoEInitConfig} from ‘capacitor-moengage-core’
const analyticsConfig: MoEAnalyticsConfig = {shouldTrackUserAttributeBooleanAsNumber: false};
const initConfig: MoEInitConfig = {analyticsConfig: analyticsConfig};
MoECapacitorCore.initialize({ appId: “YOUR_WORKSPACE_ID”, initConfig: initConfig });
```
Refer to the example code below for tracking the boolean user attribute.
```javascript TypeScript theme={null}
// If shouldTrackUserAttributeBooleanAsNumber is passed as ‘true’ in MoEAnalyticsConfig then ‘Boolean Attribute True’ will be tracked as 1 else true
MoECapacitorCore.setUserAttribute({ name: "Boolean Attribute True", value: true, appId: "YOUR_WORKSPACE_ID" });
// If shouldTrackUserAttributeBooleanAsNumber is passed as ‘false’ in MoEAnalyticsConfig then ‘Boolean Attribute False’ will be tracked as false.
MoECapacitorCore.setUserAttribute({ name: "Boolean Attribute False", value: false, appId: "YOUR_WORKSPACE_ID" });
```
# Tracking User Attributes
The SDK provides APIs to track commonly tracked user attributes like First Name, Last Name, Email-Id, etc. Please use the provided methods for tracking these attributes.
## Reserved keywords for User Attributes
Below is the list of keys that should not be used when tracking user attributes.
* USER\_ATTRIBUTE\_UNIQUE\_ID
* USER\_ATTRIBUTE\_USER\_EMAIL
* USER\_ATTRIBUTE\_USER\_MOBILE
* USER\_ATTRIBUTE\_USER\_NAME
* USER\_ATTRIBUTE\_USER\_GENDER
* USER\_ATTRIBUTE\_USER\_FIRST\_NAME
* USER\_ATTRIBUTE\_USER\_LAST\_NAME
* USER\_ATTRIBUTE\_USER\_BDAY
* USER\_ATTRIBUTE\_NOTIFICATION\_PREF
* USER\_ATTRIBUTE\_OLD\_ID
* MOE\_TIME\_FORMAT
* MOE\_TIME\_TIMEZONE
* USER\_ATTRIBUTE\_DND\_START\_TIME
* USER\_ATTRIBUTE\_DND\_END\_TIME
* MOE\_GAID
* INSTALL
* UPDATE
* MOE\_ISLAT
* status
* user\_id
You can not use "moe\_" as a prefix while naming events, event attributes, or user attributes. It is a system prefix and using it might result in periodic blacklisting without prior communication.
# InApp NATIV
Source: https://moengage.com/docs/developer-guide/capacitor-sdk/in-app-messages/inapp-nativ
Set up MoEngage in-app NATIV campaigns in your Capacitor app to show contextual messages to users.
InApp NATIV Campaigns target your users by showing a message while the user is using your app. They are very effective in providing contextual information and help to cross-sell/up-sell on desired screens of your app or/and on desired actions performed by the user in your app.
## Install Android Dependency
## Install using BOM
Integration using BOM is the recommended way of integration; refer to the[ Install Using BOM document](/developer-guide/android-sdk/sdk-integration/basic-integration/Install-Using-BOM) . Once you have configured the BOM add the dependency in the *app/build.gradle* file as shown below:
```json build.gradle wrap theme={null}
dependencies {
...
implementation("com.moengage:inapp")
}
```
Once the BOM is configured, include the specific MoEngage modules required for the application. \
Note: Version numbers are not required for these dependencies; the BOM automatically manages them.
### **Requirements for displaying images and GIFs in InApp**
Starting InApp version **7.0.0,** SDK requires [Glide](https://bumptech.github.io/glide/) to show images and GIFs in the in-apps. You need to add the below dependency in your **build.gradle** file.
```Code Groovy theme={null}
dependencies {
...
implementation("com.github.bumptech.glide:glide:4.16.0")
}
```
# Display InApp
Call the **showInApp()** wherever InApp has to be shown in the app as shown below:
```javascript TypeScript theme={null}
import { MoECapacitorCore } from 'capacitor-moengage-core';
MoECapacitorCore.showInApp({ appId: "YOUR_WORKSPACE_ID" });
```
# Display Nudges
Starting with ***capacitor-moengage-core***version **6**\*\*.0.0,\*\*MoEngage InApp SDK supports displaying Non-Intrusive nudges.
To show a Nudge InApp Campaign call `showNudge()`
```javascript TypeScript theme={null}
import { MoECapacitorCore } from 'capacitor-moengage-core';
// Display Nudge on the any available position
MoECapacitorCore.showNudge({position: MoENudgePosition.Any, appId: "YOUR_WORKSPACE_ID" });
// Display Nudge on the specific position
MoECapacitorCore.showNudge({position: MoENudgePosition.Top, appId: "YOUR_WORKSPACE_ID" });
```
# InApp/Nudge Redirection default behavior
On clicking an Inapp or Nudge, MoEngage SDKs will handle **only rich landing navigation** redirection.
For the screen name and deep link redirection, your app code should redirect the user to the right screen or deep link. To handle the screen name and deep link redirection, you must implement inapp click callback methods. MoEngage SDK will just pass the inapp payload to this call back code. Implementation steps are mentioned in the InApp callback section of the Integration.
# Self-Handled InApps
Self-handled In Apps are messages which are delivered by the SDK but displaying it has to be handled by the App.\
To get self-handled In-App call the below method.
```javascript TypeScript theme={null}
import { MoECapacitorCore } from 'capacitor-moengage-core';
MoECapacitorCore.getSelfHandledInApp({ appId: "YOUR_WORKSPACE_ID" });
```
The payload for self-handled in-app is returned via a callback. Register a callback as shown below.
```javascript TypeScript theme={null}
import { MoECapacitorCore, MoEInAppSelfHandledCampaignData } from 'capacitor-moengage-core';
MoECapacitorCore.addListener("inAppCampaignSelfHandled", (data: MoEInAppSelfHandledCampaignData) => {
console.log(" Received callback 'inAppCampaignSelfHandled', data: " + JSON.stringify(data))
});
```
# Tracking Statistics
Since display, click, and dismiss for Self-Handled InApp is controlled by the application we need you to notify the SDK whenever the In-App is Shown, Clicked, or Dismissed. Below are the methods you need to call to notify the SDK. The campaign object provided to the application in the callback for self-handled in-app should be passed in as a parameter to the below APIs.
```javascript TypeScript theme={null}
import { MoECapacitorCore, MoEInAppSelfHandledCampaignData } from 'capacitor-moengage-core';
//Track self handled shown
MoECapacitorCore.selfHandledShown(selfHandledCampaignData)
//Track self handled widget clicked
MoECapacitorCore.selfHandledClicked(selfHandledCampaignData)
//Track self handled dismissed
MoECapacitorCore.selfHandledDismissed(selfHandledCampaignData)
```
# InApp Callbacks
The callbacks must be registered before inapps are displayed either via show methods or triggered events. Make sure you are calling `initialize()` the method of the plugin after you set up these callbacks. Refer [doc](/developer-guide/react-native-sdk/sdk-integration/react-native/sdk-initialization/manual-initialization/framework-initialization) for more info.
We provide callbacks whenever an InApp campaign is shown, dismissed, or clicked you can register for the same as shown below. Use this call both Intrusive InApps and Non-Intrusive Nudge InApps to handle action.
```javascript TypeScript theme={null}
import { MoECapacitorCore, MoEInAppLifecycleData, MoEInAppNavigationData, MoEInAppCustomActionData } from 'capacitor-moengage-core';
MoECapacitorCore.addListener("inAppCampaignShown", (data: MoEInAppLifecycleData) => {
console.log(" Received callback 'inAppCampaignShown', data: " + JSON.stringify(data))
});
MoECapacitorCore.addListener("inAppCampaignDismissed", (data: MoEInAppLifecycleData) => {
console.log(" Received callback 'inAppCampaignDismissed', data: " + JSON.stringify(data))
});
MoECapacitorCore.addListener("inAppCampaignClicked", (data: MoEInAppNavigationData) => {
console.log(" Received callback 'inAppCampaignClicked', data: " + JSON.stringify(data))
});
MoECapacitorCore.addListener("inAppCampaignCustomAction", (data: MoEInAppCustomActionData) => {
console.log(" Received callback 'inAppCampaignCustomAction', data: " + JSON.stringify(data))
});
```
| Event Type | Event Name |
| -------------------------------- | ------------------------- |
| InApp Shown | inAppCampaignShown |
| InApp Clicked | inAppCampaignClicked |
| InApp Dismissed | inAppCampaignDismissed |
| InApp Clicked with Custom Action | inAppCampaignCustomAction |
# Contextual InApp
You can restrict the in-apps based on the user's context in the application apart from restricting InApp campaigns on a specific screen/activity. To set the user's context in the application use **setInAppContext()** API as shown below.
## Set Context
Call the below method to set the context, before calling **showInApp().**
```javascript JavaScript theme={null}
import { MoECapacitorCore } from 'capacitor-moengage-core';
// replace array elements with actual values.
MoECapacitorCore.setInAppContext({ contexts: ["c1","c2"] , appId: YOUR Workspace ID });
```
## Reset Context
Once the user is moving out of the context use the **resetInAppContext()** API to reset/clear the existing context.
```javascript JavaScript theme={null}
import { MoECapacitorCore } from 'capacitor-moengage-core';
MoECapacitorCore.resetInAppContext({ appId: YOUR Workspace ID });
```
# Payload Structure
```typescript TypeScript theme={null}
/**
* In-App lifecycle event camapaign data
*/
export interface MoEInAppLifecycleData {
/**
* Account information
*/
accountMeta: MoEAccountMeta;
/**
* In-App Campaign data
*/
campaignData: MoEInAppCampaignData;
/**
* Platform information
*/
platform: MoEPlatform;
}
/**
* Campaign data.
*/
export interface MoEInAppCampaignData {
/**
* Unique Identifier for the campaign
*/
campaignId: string;
/**
* Name given to the campaign while creation on the MoEngage Dashboard.
*/
campaignName: string;
/**
* Additional Meta data related to the campaign.
*/
campaignContext: MoEInAppCampaignContext;
}
/**
* In-App navigation event campaign data
*/
export interface MoEInAppNavigationData {
/**
* Account information
*/
accountMeta: MoEAccountMeta;
/**
* In-App Campaign data
*/
campaignData: MoEInAppCampaignData;
/**
* Navigation action data
*/
navigation: MoEInAppNavigation;
/**
* Platform Data
*/
platform: MoEPlatform;
}
/**
* In-App navigation action data
*/
export interface MoEInAppNavigation {
/**
* InApp Action type
*/
actionType: MoEInAppActionType;
/**
* Type of Navigation.
*/
navigationType: string;
/**
* Navigation URL
*/
navigationUrl: string;
/**
* Key-Value Pair entered on the MoEngage Platform during campaign creation.
*/
kvPair: Map;
}
/**
* In-App custom event campaign data
*/
export interface MoEInAppCustomActionData {
/**
* Account information
*/
accountMeta: MoEAccountMeta;
/**
* In-App Campaign data
*/
campaignData: MoEInAppCampaignData;
/**
* Custom Action data
*/
customAction: MoEInAppCustomAction;
/**
* Platform information
*/
platform: MoEPlatform;
}
/**
* InApp Action type
*/
export declare enum MoEInAppActionType {
NAVIGATION = "navigation",
CUSTOM = "custom"
}
/**
* In-App custom action data
*/
export interface MoEInAppCustomAction {
/**
* InApp Action type
*/
actionType: MoEInAppActionType;
/**
* Key-Value Pair entered on the MoEngage Platform during campaign creation.
*/
kvPair: Map;
}
/**
* Data for self handled campaign.
*/
export interface MoEInAppSelfHandledCampaignData {
/**
* Account information
*/
accountMeta: MoEAccountMeta;
/**
* In-App Campaign data
*/
campaignData: MoEInAppCampaignData;
/**
* SelfHandled data
*/
selfHandled: MoEInAppSelfHandledCampaign;
}
/**
* Self Handled campaign object
*/
export interface MoEInAppSelfHandledCampaign {
/**
* Self handled campaign payload.
*/
payload: string;
/**
* Interval after which in-app should be dismissed, unit - Seconds
*/
dismissInterval: number;
/**
* Should the campaign be dismissed by pressing the back button or using the back gesture.
* if the value is true campaign should be dismissed on back press.
*/
isCancellable: boolean;
}
```
# Handling Orientation Change
This is only for the Android platform
MoEngage SDK has to be notified when the device orientation changes for SDK to handle in-app display.
There are two ways to do it:
1. Add the API call in the Android native part of your app
2. Call MoEngage plugin's **onOrientationChanged()**
## Add the API call in the Android native part of your app
Notify the SDK when **onConfigurationChanged()** API callback is received in your App's Activity class.
```auto Java theme={null}
import android.content.res.Configuration;
import android.os.Bundle;
import com.getcapacitor.BridgeActivity;
import com.moengage.capacitor.MoECapacitorCorePlugin;
import com.moengage.capacitor.MoECapacitorHelper;
public class MainActivity extends BridgeActivity {
@Override public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
MoECapacitorHelper.INSTANCE.onConfigurationChanged();
}
}
```
## Call the MoEngage plugin's orientation change API
Call the below API to notify SDK of the orientation change.
```javascript TypeScript theme={null}
import { MoECapacitorCore } from 'capacitor-moengage-core';
MoECapacitorCore.onOrientationChanged();
```
# Android Notification Runtime Permissions
Source: https://moengage.com/docs/developer-guide/capacitor-sdk/push/basic/android-notification-runtime-permissions
Handle Android 13 notification runtime permissions in your Capacitor app using the MoEngage SDK.
Android 13 (API level 33) and higher supports [runtime permission](https://developer.android.com/guide/topics/permissions/overview#runtime) for sending [non-exempt](https://developer.android.com/develop/ui/views/notifications/notification-permission#exemptions) (including Foreground Services (FGS)) notifications from an app [POST\_NOTIFICATIONS](https://developer.android.com/reference/android/Manifest.permission#POST_NOTIFICATIONS). This change helps users focus on the notifications that are most important to them.
Refer to the [official documentation](https://developer.android.com/develop/ui/views/notifications/notification-permission) for more details.
The below-mentioned APIs are supported starting MoEngage core Android SDK version **12.3.01**
When an application runs on Android 13 and wants to show notifications to the user, it must request the user's notification permission. You have two options: let MoEngage handle permissions for you or handle the notification permission with your code.
* MoEngage handles Notification permission.
* You just have to call a single line of code mentioned on this page.
* You maintain the notification permission logic.
* Notify MoEngage SDK if permission to push notifications is granted.
We recommend you let MoEngage handle push notification permissions.
## Notify SDK of permission result
Once the application requests the user for notification permission notify the SDK of the user response using the below API. *If you are letting MoEngage SDK handle the notification permissions, you should ignore this step.*
```javascript TypeScript theme={null}
import { MoECapacitorCore } from 'capacitor-moengage-core'
MoECapacitorCore.pushPermissionResponseAndroid({isGranted: isGranted});
```
## Update the Permission request count(optional)
Once the application requests the user for notification permission, update the SDK of the request attempts.
**Why does the SDK require permission attempt count?**
SDK requires the attempt count to accurately track the number of times the permission request was attempted. If the user denies the permission request twice the application/SDK cannot request permission further i.e. if we request permission it would be automatically denied without the user seeing the request dialog. As an SDK we cannot be sure of the number of times the user has denied the permission we try to optimize the calls to request permission based on the attempt count.
```javascript TypeScript theme={null}
import { MoECapacitorCore } from 'capacitor-moengage-core'
MoECapacitorCore.updatePushPermissionRequestCountAndroid({appId: "YOUR_WORKSPACE_ID", count : count});
```
## Setup Notification Channels
If the application has already taken notification permission from the user call the below API to set up Notification Channels for showing push notifications.
```javascript TypeScript theme={null}
import { MoECapacitorCore } from 'capacitor-moengage-core'
MoECapacitorCore.setupNotificationChannelsAndroid();
```
## Let MoEngage SDK handle Notification permission
MoEngage SDK provides helper APIs to show the permission request to the end-user or navigate the user to the settings screen for enabling notifications.
Use the below API to show the permission request dialog to the user.
When using the below API SDK automatically tracks the response, sets up the required notification channel, etc, mentioned above.
```javascript TypeScript theme={null}
import { MoECapacitorCore } from 'capacitor-moengage-core'
MoECapacitorCore.requestPushPermissionAndroid();
```
## Navigate to Notification Settings (situational/optional)
Use the below API to show navigate the user to the Notification Settings for the application on the device.
*Note*: Below Android 8(API level 26) the user is directed to the Application Info screen of your application.
```javascript TypeScript theme={null}
import { MoECapacitorCore } from 'capacitor-moengage-core'
MoECapacitorCore.navigateToSettingsAndroid();
```
# Android Push Configuration
Source: https://moengage.com/docs/developer-guide/capacitor-sdk/push/basic/android-push-configuration
Configure Android push notifications in your Capacitor app including FCM setup and push registration.
# Basic Setup
Follow the basic setup outlined in this section to enable push notifications on an Android device using MoEngage.
* **FCM Setup on MoEngage Dashboard -** FCM Authentication is the method to enable sending push notifications to your app installed on Android devices. Use the methods mentioned in [this article](/developer-guide/android-sdk/push/basic/fcm-authentication) to authenticate MoEngage to access Firebase services.
* **Adding metadata for push notification -** Set the small icon and large icon drawable and other options to handle push notifications using the methods available in [this article](/developer-guide/components-for-sdk/push-notification/android-push-configuration-for-hybrid-applications#adding-metadata-for-push-notification).
* **Android Notification Runtime Permissions** - When the application is running on Android 13 to show notifications to the user, applications would need to request the user for notification permission. Refer to the methods available in [this article](/developer-guide/react-native-sdk/push/basic/android-notification-runtime-permissions) to handle permission requests.
* **Push Registration and Receiving** - To use Push Notification in your React Native application, you must configure Firebase. Configuring Firebase steps will depend on how you want to integrate it. MoEngage recommends leaving the push handling to MoEngage SDK, as the best practices are properly integrated. You can also handle the push at your app level. In any case, look at the following section that applies to you and finish the integration steps.
**Add messaging service**\
You must add the messaging service to the Manifest file for MoEngage SDK to show the notifications. Refer to this document [here](/developer-guide/android-sdk/push/basic/push-token-registration-and-display#push-token-registration-and-display-by-moengage-sdk).
**Callback on token registration (optional)**\
To get a callback whenever a new token is registered or refreshed, refer to the method [here](/developer-guide/android-sdk/push/basic/push-token-registration-and-display#push-token-registration-and-display-by-moengage-sdk).
**Notification Clicked Callback**
To receive a callback whenever a push is clicked and for custom handling redirection, use the method [in this article](/developer-guide/android-sdk/push/advanced/callbacks-and-customisation#notification-received-callback).
**How to opt out of MoEngage Registration?**\
The MoEngage SDK attempts to register for a push token; since your application handles push, you need to opt out of SDK's token registration using the method in [this article](/developer-guide/android-sdk/push/basic/push-token-registration-and-display#pass-the-push-token-to-moengage-sdk).
**Pass the Push Token To MoEngage SDK** - After receiving the push token from FCM, use the method in [this article](/developer-guide/android-sdk/push/basic/push-token-registration-and-display) to pass the Push Token to the MoEngage SDK to set it in the MoEngage platform.
**Passing the Push payload to the MoEngage SDK** - After receiving the push payload on the app, use the method in [this article](/developer-guide/android-sdk/push/basic/push-token-registration-and-display#passing-the-push-payload-to-the-moengage-sdk)to send out push notifications to the device.
MoEngage recommends using the Android native APIs to pass the push payload to the MoEngage SDK instead of the React-Native/Javascript APIs. React-Native Engine might not get initialized if the application is killed or if the notification is not sent at a high priority.
* [Pass the Push Token To MoEngage SDK](/developer-guide/capacitor-sdk/push/basic/android-push-configuration#passing-push-token)
* [Pass the Push payload to the MoEngage SDK](/developer-guide/capacitor-sdk/push/basic/android-push-configuration#passing-push-payload)
* [Callbacks and customizations](/developer-guide/react-native-sdk/push/basic/android-push-configuration#customizing-push-notification)
# Capacitor APIs
We highly recommend you to use the Android native APIs for passing the push payload to the MoEngage SDK instead of the Capacitor APIs. Capacitor Engine might not get initialised if the application is killed or if the notification is not sent at a high priority.
## Passing Push Token
```javascript TypeScript theme={null}
import { MoECapacitorCore } from 'capacitor-moengage-core'
// pass the push token as a string
passFcmPushToken({ token: "TOKEN", appId: "YOUR_Workspace_ID" });
```
## Passing Push Payload
```javascript TypeScript theme={null}
import { MoECapacitorCore } from 'capacitor-moengage-core'
// pass the push payload object
passFcmPushPayload(payload: object, appId: "YOUR_WORKSPACE_ID" });
```
We highly recommend you to use the Android native APIs for passing the push payload to the MoEngage SDK instead of the Capacitor APIs. Capacitor Engine might not get initialised if the application is killed or if the notification is not sent at a high priority.
# Notification Runtime Permission
Android 13 (API level 33) and higher supports [runtime permission](https://developer.android.com/guide/topics/permissions/overview#runtime) for sending [non-exempt](https://developer.android.com/develop/ui/views/notifications/notification-permission#exemptions) (including Foreground Services (FGS)) notifications from an app `POST_NOTIFICATIONS`. This change helps users focus on the notifications that are most important to them.
Refer to the [official documentation](https://developer.android.com/develop/ui/views/notifications/notification-permission) for more details.
The below-mentioned APIs are supported from Plugin version **2.0.0**
When the application is running on Android 13 to show notifications to the user, applications would need to request the user for notification permission.
For applications integrating the MoEngage SDK, would need to
* Notify the SDK of the permission request's response from the user.
* If the application has already requested push permission(before MoEngage integration) help MoEngage set up notification channels for notification display.
## Notify SDK of permission result
Once the application requests the user for notification permission notify the SDK of the user response using the below API.
```typescript Typescript theme={null}
import { MoECapacitorCore} from 'capacitor-moengage-core'
MoECapacitorCore.pushPermissionResponseAndroid({ isGranted: true/false });
```
## Setup Notification Channels
If the application has already taken notification permission from the user call the below API to set up Notification Channels for showing push notifications.
```typescript Typescript theme={null}
import { MoECapacitorCore} from 'capacitor-moengage-core'
MoECapacitorCore.setupNotificationChannelsAndroid();
```
MoEngage SDK provides helper APIs to show the permission request to the end-user or navigate the user to the settings screen for enabling notifications.
Use the below API to show the permission request dialog to the user.
When using the below API SDK automatically tracks the response, sets up the required notification channel, etc, mentioned above.
```typescript Typescript theme={null}
import { MoECapacitorCore} from 'capacitor-moengage-core'
MoECapacitorCore.requestPushPermissionAndroid();
```
Use the below API to show navigate the user to the Notification Settings for the application on the device.
*Note*: Below Android 8(API level 26) the user is directed to the Application Info screen of your application.
```typescript Typescript theme={null}
import { MoECapacitorCore} from 'capacitor-moengage-core'
MoECapacitorCore.navigateToSettingsAndroid();
```
## Customizing Push notification
If required the application can customize the behavior of notifications by using Native Android code (Java/Kotlin). To learn more about the customization refer to the [Advanced Push Configuration](/developer-guide/android-sdk/push/advanced/callbacks-and-customisation) documentation.Instead of extending ***PushMessageListener*** as mentioned in the above document extend ***PluginPushCallback.***
Refer to the below documentation for Push Amp+, Push Templates, and Geofence.
* [Push Amplification](/developer-guide/android-sdk/push/optional/push-amplification)
* [Push Amp Plus](/developer-guide/android-sdk/push/optional/push-amp-plus/push-amp-plus-integration)
* [Push Templates](/developer-guide/android-sdk/push/optional/push-templates)
* [GeoFence Push](/developer-guide/android-sdk/push/optional/location-triggered)
# iOS Push Configuration
Source: https://moengage.com/docs/developer-guide/capacitor-sdk/push/basic/ios-push-configuration
Configure iOS push notifications in your Capacitor app including APNS certificates and registration.
## APNS Certificate:
First, you will have to create an APNS certificate and upload to the dashboard to be able to send push notifications in iOS. Follow the steps below to do that:
* [Create an APNS certificate](/developer-guide/ios-sdk/push/basic/apns-certificate-pem-file-legacy)
* [Convert the resultant certificate to .pem format](/developer-guide/ios-sdk/push/basic/apns-certificate-pem-file-legacy)
* [Upload .pem file to MoEngage Dashboard](/developer-guide/ios-sdk/push/basic/apns-certificate-pem-file-legacy)
## Adding Push Entitlement to your Project:
Once the APNS Certificate is uploaded, enable Push Entitlement in the Xcode project. For that select your app target, then go to Capabilities. Here enable the Push Notifications capability for your app as shown below:
## Uninstall Tracking:
We make use of silent pushes to track uninstalls. For tracking uninstalls of all the users, enable Remote Notification background mode in-app capabilities for the same as shown below:
## Push Registration:
After this you will have to register for push notification by using **registerForPush** method of the plugin as shown below :
```javascript TypeScript theme={null}
//This is only for iOS
import { MoECapacitorCore } from 'capacitor-moengage-core'
MoECapacitorCore.registerForPush();
```
**AppDelegate Remote notification methods will not be called**
The plugin gets all the remote notification-related callbacks, therefore you won't receive any of them in your AppDelegate. Therefore, you will have to add observers for the notifications provided by the plugin instead.
## Rich Push and Templates Support:
Please refer to the Native iOS SDK docs for supporting Rich Push(images/videos/audio in the notification) and Templates in the app:
* [Rich Push](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial#optional)
* [Push Templates](/developer-guide/ios-sdk/push/optional/push-templates)
# Push Callback
Source: https://moengage.com/docs/developer-guide/capacitor-sdk/push/basic/push-callback
Set up listeners for push token generation and notification click events in the MoEngage Capacitor SDK.
# Configuring Push Callbacks
MoEngage Plugin provides listeners for push events. These events are a common trigger for both iOS and Android platforms. Refer to the below code to set the listener to the same:
Make sure you are calling **initialize()** method of the plugin to receive these callbacks. Refer [Initialise Capacitor Component](/developer-guide/capacitor-sdk/sdk-integration/sdk-installation/framework-dependency) for more info.
## Push Token Generated Observer
Add a listener to listen to the **pushTokenGenerated** as shown below.
```typescript TypeScript theme={null}
import { MoECapacitorCore, MoEPushTokenData } from 'capacitor-moengage-core'
MoECapacitorCore.addListener("pushTokenGenerated", (data: MoEPushTokenData) => {
console.log(" Received callback 'pushTokenGenerated', data: " + JSON.stringify(data))
});
```
## Notification Click Observers
Add a listener to listen to the **pushClicked** as shown below.
```typescript TypeScript theme={null}
import { MoECapacitorCore, MoEPushCampaignData } from 'capacitor-moengage-core'
MoECapacitorCore.addListener("pushClicked", (data: MoEPushCampaignData) => {
console.log(" Received callback 'pushClicked', data: " + JSON.stringify(data))
});
```
# Payload
PushToken received in the callback is a **MoEPushTokenData** instance with the following definition:
```typescript TypeScript theme={null}
/**
* Push token object
*/
export interface MoEPushTokenData {
/**
* Platform type
*/
platform: MoEPlatform;
/**
* Type of push service
*/
pushService: MoEPushService;
/**
* Push Token
*/
token: String;
}
export declare enum MoEPlatform {
iOS = "iOS",
ANDROID = "android"
}
export declare enum MoEPushService {
APNS = 0,
FCM = 1,
MI_PUSH = 2,
PUSH_KIT = 3
}
```
NotificationPayload received in the callback is a **MoEPushCampaignData** instance with the following definition:
```typescript TypeScript theme={null}
/**
* Push event data
*/
export interface MoEPushCampaignData {
/**
* Account information
*/
accountMeta: MoEAccountMeta;
/**
* Push campaign object
*/
pushCampaign: MoEPushCampaign;
/**
* Platform data
*/
platform: MoEPlatform;
}
/**
* Account Object
*/
export interface MoEAccountMeta {
/**
* Account identifier
*/
appId: string;
}
export interface MoEPushCampaign {
/**
* Is the click action a defualt action
*/
isDefaultAction: boolean;
/**
* Clicked Action data
*/
clickedAction: Map;
/**
* Key-Value Pair entered on the MoEngage Platform during campaign creation.
*/
payload: Map;
}
export declare enum MoEPlatform {
iOS = "iOS",
ANDROID = "android"
}
```
Payload Structure for `clickedAction` Map
```json JSON theme={null}
{
"clickedAction": {
"type": "navigation/customAction",
"payload": {
"type": "screenName/deepLink/richLanding",
"value": "",
"kvPair": {
"key1": "value1",
"key2": "value2",
...
}
}
}
}
```
`platform` - Native platform from which callback is triggered. Possible values - `android`, `ios`\
`isDefaultAction` - This key is present only for the Android Platform. It's a boolean value indicating if the user clicked on the default content or not. true if the user clicks on the default content else false.\
`clickedAction` - Action to be performed on notification click.\
`clickedAction.type` - Type of click action. Possible values `navigation` and `customAction`. Currently, `customAction` is supported only on Android.\
`clickAction.payload` - Action payload for the clicked action.\
`clickedAction.payload.type` - Type of navigation action defined. Possible values `screenName`, `deepLink`, `richLanding`. Currently, in the case of iOS, richlanding and deep-link URLs are processed internally by the SDK and not passed in this callback therefore possible value in the case of iOS is only `screenName`.\
`clickAction.value` - value entered for navigation action or custom payload.\
`clickAction.kvPair` - Custom key-value pair entered on the MoEngage Platform.\
`payload` - Complete campaign payload.
## Android Payload
If the user clicks on the default content of the notification the key-value pair and campaign payload can be found inside the `payload` key. If the user clicks on the action button or a push template action the action payload would be found inside `clickedAction`.\
You can use the `isDefaultAction` key to check whether the user clicked on the default content or not and then parse the payload accordingly.
## iOS Payload
In the case of iOS, you would always receive the key-value pairs with respect to clicked action in `clickedAction` property. Refer to this \[/developer-guide/ios-sdk/push/advanced/custom-notification-handling#notification-payload] for knowing the iOS notification payload structure.
# Location Triggered
Source: https://moengage.com/docs/developer-guide/capacitor-sdk/push/optional/location-triggered
Add geofence-based location-triggered push notifications to your Capacitor app using MoEngage.
# Installation
## Adding Geofence Plugin
Add **capacitor-moengage-geofence** plugin to the capacitor project as shown below :
```auto Shell theme={null}
$npm install capacitor-moengage-geofence
```
## Android Installation
## Install using BOM
Integration using BOM is the recommended way of integration; refer to the [Install Using BOM document](/developer-guide/android-sdk/sdk-integration/basic-integration/Install-Using-BOM). Once you have configured the BOM add the dependency in the *app/build.gradle* file as shown below:
```json build.gradle wrap theme={null}
dependencies {
...
implementation("com.moengage:geofence")
}
```
Once the BOM is configured, include the specific MoEngage modules required for the application. \
Note: Version numbers are not required for these dependencies; the BOM automatically manages them.
## Manual Installation

Once you install the Flutter Plugin add MoEngage's native Android SDK dependency to the Android project of your application.\
Navigate to **android/app/build.gradle**. Add the MoEngage Android SDK's dependency in the **dependencies** block.
```css build.gradle theme={null}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation("com.moengage:geofence:$sdkVersion")
}
```
where **\$sdkVersion** should be replaced by the latest version of the MoEngage Geofence SDK
## iOS
In the case of iOS, the native dependency is part of the Geofence Cordova SDK itself, so there is no need to include any additional dependency for supporting Geofence.
## Configuration
### Start Geofence Monitoring
After integrating the geofence package call **startGeofenceMonitoring()** method to initiate the geofence module, this will fetch the geofences around the current location of the user. Please take a look at the [iOS doc](/developer-guide/ios-sdk/push/optional/location-triggered) and [Android doc](/developer-guide/android-sdk/push/optional/location-triggered) for more information on Geofence. By default, the geofence feature is not enabled. You need to call the \*\*startGeofenceMonitoring()\*\*to receive location-triggered push messages.
```auto Typescript theme={null}
import { MoECapacitorGeofence } from 'capacitor-moengage-geofence';
MoECapacitorGeofence.startGeofenceMonitoring({ appId: "YOUR_WORKSPACE_ID" });
```
### Stop Geofence Monitoring
If you want to stop the geofence monitoring or feature use the **stopGeofenceMonitoring()** API. This API will remove the existing geofences.
```auto Typescript theme={null}
import { MoECapacitorGeofence } from 'capacitor-moengage-geofence';
MoECapacitorGeofence.stopGeofenceMonitoring({ appId: "YOUR_WORKSPACE_ID" });
```
# Capacitor Sample App
Source: https://moengage.com/docs/developer-guide/capacitor-sdk/sample-app/capacitor-sample-app
Explore the MoEngage Capacitor sample application on GitHub as a reference for SDK integration.
The [MoEngage Capacitor Sample application](https://github.com/moengage/Capacitor-Sample) offers a useful reference point for integrating MoEngage into your Capacitor app.
## Next Steps
* [SDK Installation](/developer-guide/capacitor-sdk/sdk-integration/sdk-installation/framework-dependency)
* [Framework Initialization](/developer-guide/capacitor-sdk/sdk-integration/sdk-initialization/framework-initialization)
# Android SDK Initialization
Source: https://moengage.com/docs/developer-guide/capacitor-sdk/sdk-integration/sdk-initialization/android-sdk-initialization
Initialize the MoEngage Android SDK in your Capacitor app's Application class with your Workspace ID.
# Initializing the SDK
Initialize the SDK on the main thread inside onCreate() and not create a worker thread and initialize the SDK on that thread.
```Java Java theme={null}
import android.app.Application;
import com.moengage.capacitor.MoEInitializer;
import com.moengage.core.MoEngage;
import com.moengage.core.DataCenter;
public class MainApplication extends Application {
@Override public void onCreate() {
super.onCreate();
// this is the instance of the application class and "YOUR_WORKSPACE_ID" is the Workspace ID from the dashboard.
MoEngage.Builder moEngage = new MoEngage.Builder(this,"YOUR_WORKSPACE_ID”, DataCenter.DATA_CENTER_X);
MoEInitializer.initialiseDefaultInstance(this, moEngage);
}
}
```
Following details of the different data centers you need to set based on the dashboard hosts
| Data Center | Dashboard host |
| -------------------------- | ------------------------- |
| DataCenter.DATA\_CENTER\_1 | dashboard-01.moengage.com |
| DataCenter.DATA\_CENTER\_2 | dashboard-02.moengage.com |
| DataCenter.DATA\_CENTER\_3 | dashboard-03.moengage.com |
| DataCenter.DATA\_CENTER\_4 | dashboard-04.moengage.com |
| DataCenter.DATA\_CENTER\_5 | dashboard-05.moengage.com |
Refer to the [API reference](https://moengage.github.io/android-api-reference/core/com.moengage.core/-mo-engage/-builder/index.html) for more information about the detailed list of possible configurations.
All the configurations are added to the builder before initialization. If you are calling initialize at multiple places, ensure that all the required flags and configurations are set each time you initialize to maintain consistency in behavior.
In case your application does not have an Application class yet navigate to the java source code inside the android platform folder and add the Application class file.
Make sure your application class is defined in the **AndroidManifest.xml** file as well.
# Register MoEngage's Plugin
Register the plugin in your **Activity** class's **onCreate()**.
```Java Java theme={null}
import com.getcapacitor.BridgeActivity;
import com.moengage.capacitor.MoECapacitorCorePlugin;
public class MainActivity extends BridgeActivity {
@Override protected void onCreate(Bundle savedInstanceState) {
//register the MoEngage Capacitor Plugin
registerPlugin(MoECapacitorCorePlugin.class);
super.onCreate(savedInstanceState);
}
}
```
# Exclude MoEngage Storage File from Auto-Backup
This is a mandatory integration step and is very essential to prevent your data from getting corrupted. Android's auto back-up service periodically backs up Shared Preference files, Database files, etc, more details [here](https://developer.android.com/guide/topics/data/autobackup). This backup results in MoEngage SDK's identifiers being backed up and restored after re-install.This restoration of the identifier results in your data being corrupted and users not being reachable via push notifications.
To ensure data is not corrupted after a backup is restored, opt out of MoEngage SDK's storage files. Refer to [Exclude MoEngage Storage File from the Auto-Backup](/developer-guide/android-sdk/sdk-integration/basic-integration/exclude-mo-engage-storage-file-from-auto-backup) section of the documentation to learn more about which files to exclude.
# Framework Initialization
Source: https://moengage.com/docs/developer-guide/capacitor-sdk/sdk-integration/sdk-initialization/framework-initialization
Initialize the MoEngage Capacitor plugin in your Ionic app using the appropriate lifecycle callback.
# Initialize Plugin
Initialize the MoEngage Plugin by calling the **`MoECapacitorCore.initialize({ appId: "YOUR_WORKSPACE_ID", initConfig: initConfig});`**. In the case of Ionic-React initialize the plugin in the **`useIonViewWillEnter()`** callback, for Ionic-Angular initialize the plugin in **`ngOnInit()`**.
For more information, read [Ionic React Lifecycle](https://ionicframework.com/docs/react/lifecycle).
## iOS
Starting from version 5.x.x of **capacitor-moengage-core**, the default tracking for the custom boolean attribute will be changed to bool from double. To configure this, use ***MoEAnalyticsConfig*** and pass true to track the boolean as double or pass false to track it as bool.
```typescript Typescript theme={null}
import { MoECapacitorCore, MoEAnalyticsConfig, MoEInitConfig} from 'capacitor-moengage-core'
const analyticsConfig: MoEAnalyticsConfig = {shouldTrackUserAttributeBooleanAsNumber: true};
const initConfig: MoEInitConfig = {analyticsConfig: analyticsConfig};
MoECapacitorCore.initialize({ appId: "YOUR_WORKSPACE_ID", initConfig: initConfig });
```
Refer to the [doc](/developer-guide/capacitor-sdk/data-tracking/tracking-user-attributes) for more info
Make sure you are setting the Push/InApp callback listeners before calling the **`initialize({ appId: "YOUR_WORKSPACE_ID", initConfig: initConfig })`**.
# iOS SDK Initialization
Source: https://moengage.com/docs/developer-guide/capacitor-sdk/sdk-integration/sdk-initialization/ios-sdk-initialization
Initialize the MoEngage iOS SDK in your Capacitor app's AppDelegate with your Workspace ID.
To initialize the iOS Application with the MoEngage Workspace ID from Settings in the dashboard. In your project, go to AppDelegate file and call the initialize method of `MoECapacitorInitializer` instance in `applicationdidFinishLaunchingWithOptions()` method as shown below:
Sample code to initialize from `application:didFinishLaunchingWithOptions:` method in
```objectivec Swift theme={null}
import UIKit
import Capacitor
import CapacitorMoengageCore
import MoEngageSDK
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let sdkConfig = MoEngageSDKConfig(withAppID: YOUR Workspace ID)
sdkConfig.moeDataCenter = .data_center_01
MoECapacitorInitializer.sharedInstance.initializeDefaultInstance(sdkConfig, andLaunchOptions: launchOptions)
return true
}
}
```
# Data Center
In case your app wants to redirect data to a specific zone due to any data regulation policy please configure the zone in the MOSDKConfig object.
For more information on Data Center, refer [here](/developer-guide/ios-sdk/sdk-integration/basic/data-center).
# Android SDK Installation
Source: https://moengage.com/docs/developer-guide/capacitor-sdk/sdk-integration/sdk-installation/android-sdk-installation
Install the MoEngage Android SDK in your Capacitor project using BOM or manual dependency configuration.
# Configuring Build Settings
## Option 1: Using BOM (Recommended)

Use the Bill of Materials (BOM) to automatically manage compatible versions of the SDK modules.
```auto build.gradle theme={null}
dependencies {
...
// Import the MoEngage BOM
implementation(platform("com.moengage:android-bom:"))
// Add optional modules as needed
implementation("com.moengage:inapp")
}
```
Replace **\\`** with the latest BOM version. For more info on integration using BOM, refer [here](/developer-guide/android-sdk/sdk-integration/basic-integration/Install-Using-BOM).
## Option 2: Manual Integration
### Add Maven Repository
Add *mavenCentral()* repository in the project-level ***build.gradle*** file. If not present already.
Path - ***android/build.gradle(.kts)***
```auto Groovy theme={null}
buildscript {
repositories {
mavenCentral()
}
}
allprojects {
repositories {
mavenCentral()
}
}
```
### Enable Java 8
The SDK target and source compatible with version 8 of the Java Programming Language. Enable Java 8 in the application ***build.gradle***if not done already.
Path - ***android/app/build.gradle(.kts)***
```auto build.gradle theme={null}
android {
...
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
```
```auto build.gradle.kts theme={null}
android {
...
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
}
```
### Add Androidx Libraries
The SDK depends on a few Androidx libraries for its functioning, add the below Androidx libraries in your application's build.gradle file in the dependencies block if not done already.
Path - ***android/app/build.gradle(.kts)***
```auto Groovy theme={null}
dependencies {
...
implementation("androidx.core:core:1.9.0")
implementation("androidx.appcompat:appcompat:1.4.2")
implementation("androidx.lifecycle:lifecycle-process:2.7.0")
}
```
The MoEngage SDK depends on the **lifecycle-process** library for a few key features to work and the latest version of **lifecycle-process** depends on the **androidx.startup:startup-runtime** library. Hence do not remove the **InitializationProvider** component from the manifest. When adding other Initializers using the **startup-runtime** make sure the Initializer for **lifecycle-process** library is also added. Refer to the [documentation](https://developer.android.com/jetpack/androidx/releases/lifecycle#2.4.0) to know how to add the Initializer.
# Framework Dependency
Source: https://moengage.com/docs/developer-guide/capacitor-sdk/sdk-integration/sdk-installation/framework-dependency
Add the MoEngage Capacitor plugin to your project and configure native platform dependencies.
Capacitor is a cross-platform native runtime that makes it easy to build modern web apps that run natively on iOS and Android.
# Adding MoEngage Plugin
Add **capacitor-moengage-core** plugin to capacitor project as shown below :
```Shell Shell theme={null}
$npm install capacitor-moengage-core
```
Once the plugin is installed run ***npx cap sync*** to update capacitor native platform(s) and dependencies.
Follow the ***Capacitor*** framework's guidelines for adding plugins.
A working Sample App can be found [here](https://github.com/moengage/Capacitor-Sample).
# Integrate Native platforms
To install and integrate the respective platforms, follow the docs given below:
* [Android SDK Installation](/developer-guide/capacitor-sdk/sdk-integration/sdk-installation/android-sdk-installation)
* [iOS SDK Installation](/developer-guide/capacitor-sdk/sdk-integration/sdk-installation/ios-sdk-installation)
# iOS SDK Installation
Source: https://moengage.com/docs/developer-guide/capacitor-sdk/sdk-integration/sdk-installation/ios-sdk-installation
Install the MoEngage iOS SDK in your Capacitor project by running the ionic capacitor sync command.
We have added our native SDK **MoEngage-iOS-SDK** as a dependency for **capacitor-moengage-core** plugin. Hence run **ionic capacitor sync** to add native SDK to your iOS Project.
# Troubleshooting and FAQs - Capacitor
Source: https://moengage.com/docs/developer-guide/capacitor-sdk/troubleshooting-and-faqs/troubleshooting-and-faqs-capacitor
Troubleshoot common Capacitor SDK issues including missing MoEngage logs and configuration problems.
## Why are you not able to see the MoEngage logs?
There could be couple of reasons for this -
1. Ensure you have enabled verbose logs in the application class of your project - you can read more information [here](/developer-guide/android-sdk/troubleshooting-and-faqs/how-to-share-android-moengage-sdk-logs).
2. Ensure that the name of the application class in the manifest file in your android project is same as application name that is mentioned in your application file. check the image below for more understanding.
# JavaScript Bridge for HTML In-Apps
Source: https://moengage.com/docs/developer-guide/components-for-sdk/javascript-bridge/javascript-bridge-for-html-in-apps
Use the MoEngage JavaScript bridge API to interact with the SDK from HTML in-app message templates.
HTML in-app messages for Android support a bridge interface for web apps to interact with the MoEngage SDK.
The bridge contains a set of APIs that can be accessed using a global variable `moengage`.
The below table lists all the JS Bridge methods and in the subsequent sections, each API is explained in detail.
| Method Name | Description |
| ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| moengage.dismissMessage() | Attach this method on your template for closing the in-app message |
| moengage.navigateToScreen("screen-name", "optional-data-json") | Use this method to navigate the user to a specific screen on click of a template element. Params: "screen-name" : name of the screen for redirection "optional-data-json" : additional key value pairs |
| moengage.openDeepLink("deeplink-url", "optional-data-json") | Use this method when you want to open a deeplink from your html in-app template "deeplink-url" : deeplink url "optional-data-json" : additional key value pairs |
| moengage.openRichLanding("richlanding-url", "optional-data-json") | Use this method when you want to open a URL inside the app's webview "richlanding-url" : url that you want to open "optional-data-json" : additional key value pairs |
| moengage.openWebURL("web-url", "optional-data-json"). | Use this method when you want to open a URL on the app's default browser "web-url" : url that you want to open "optional-data-json" : additional key value pairs |
| moengage.copyText("text-to-copy", "message") | Use this method to copy a coupon code or offer code from your html in-app template to clipboard "text-to-copy": This text will be copied to clipboard "optional-message": This message will be shown after copy |
| moengage.call("mobile-number") | Use this method to initiate a call from your html in-app template "mobile-number": This number will appear in the dialer |
| moengage.sms("mobile-number", "message") | Use this method to initiate an sms from your html in-app template "mobile-number": SMS will be sent to this "message": This message will be sent as the SMS |
| moengage.share("share-text") | Use this method to initiate the share action via any of the available apps on the device. |
| moengage.customAction("data-json") | Use this method to initiate a custom action defined by your app. "data-json": key value pairs |
| moengage.showPushOptIn() | This only for iOS and based on current notification status, either the notification permission pop is shown or will be taken to settings screen where notification status can be updated. |
| moengage.navigateToSettings() | Use this method to navigate to the settings screen of the device |
| moengage.trackEvent(eventName, generalAttrJson) | Use this method to track an event from html in-app template "eventName" : Name of the tracked event "generalAttrJson" : Event attributes that will be tracked along with the event |
| moengage.trackClick("widgetId") | Use this method to track clicks stats for campaign performance measurement. "widgetId": This is an optional argument and if passed will help populate the click distribution table. Effective when you have multiple CTAs in a single template |
| moengage.trackDismiss(widgetId) | Use this method to track dismiss stats for campaign performance measurement and identifying users who dismiss the in-app message "widgetId": This is an optional argument and if passed will help populate the click distribution table. Effective when you have multiple dismiss CTAs in a single template |
| moengage.setEmailId("value") | Use this method to capture the email\_id of your users. This will be saved in user profile automatically and can be used to send email campaigns. You can use this with your lead generation / signup forms. "value" : This is the email\_id of the user |
| moengage.setMobileNumber("value") | Use this method to capture the mobile number of your users. This will be saved in user profile automatically and can be used to send SMS campaigns. You can use this method with your lead generation / signup forms. "value" : This is the mobile number of the user |
| moengage.setUserName("value") | Use this method to capture the Name of your users. This will be saved in user profile automatically. You can use this method with your lead generation / signup forms. "value" : This is the username of the user |
| moengage.setFirstName("value") | Use this method to capture the First Name of your users. This will be saved in user profile automatically. You can use this method with your lead generation / signup forms. "value" : This is the first name of the user |
| moengage.setLastName("value") | Use this method to capture the Last Name of your users. This will be saved in user profile automatically. You can use this method with your lead generation / signup forms. "value" : This is the last name of the user |
| moengage.setUniqueId() | Use this method to set the Client ID of your users. |
| moengage.setAlias() | Use this method to update the existing Client ID of your users. |
| moengage.setGender() | Use this method to set the Gender of your users. |
| moengage.setBirthDate() | Use this method to set the Birthdate of your users. |
| moengage.setUserLocation(lat, lng) | Use this method to set the Location (lat,lng) of your users. |
| moengage.setUserAttribute(name,value) | Use this method to set custom attributes of your users when data type of the attribute is string, numeric or boolean. name : Name of the user attribute to be tracked value : Value of the tracked user attribute. |
| moengage.setUserAttributeDate(name,value) | Use this method to set custom attributes of your users when data type of the attribute is date name : Name of the user attribute to be tracked value : Value of the tracked user attribute in ISO 8601 format |
| moengage.setUserAttributeLocation(name,lat,lng) | Use this method to set custom attributes of your users when data type of the attribute is location name : Name of the user attribute to be tracked lat,lng : Location of the user |
| moengage.trackRating() | Use this method to capture the rating of your users from a rating template. |
The subsequent sections provide more details on how to use each API. The provided JS Methods are classified into two categories - JS Methods for Actions and JS Methods for Data Tracking
# Actions
The following sections will provide more details on the JS Methods for actions.
**JS Methods for Actions**
Integrate the JS Methods for Actions with your HTML Template to execute on-click actions like message close, navigation actions like re-direction to screens or webpages, or any other actions as supported with in-app campaigns.
# Dismiss In-App Message
To dismiss in-app messages use `moengage.dismissMessage()` API.
```javascript JavaScript theme={null}
moengage.dismissMessage();
```
Do not use other API when the `moengage.dismissMessage()`API is in use.
# Navigation Actions
## Navigate to Screen
You can open a screen using `moengage.navigateToScreen(, )`.
```javascript JavaScript theme={null}
var screenName = "com.moengage.sampleapp.ui.activity.MainActivity";
// Optionally add data json object
var attributes = {
"nav_screen_attr1": "val1",
"nav_screen_attr2": 100,
"nav_screen_attr3": 123.11,
"nav_screen_attr4": true
};
moengage.navigateToScreen(value, attributes);
```
## Open Deeplink URL
To open a deeplink URL use `moengage.openDeepLink(, )`.
```javascript JavaScript theme={null}
var value = "moengage://testdeeplink/testActivity";
// Optionally add data json object
var attributes = {
"nav_screen_attr1": "val1",
"nav_screen_attr2": 100,
"nav_screen_attr3": 123.11,
"nav_screen_attr4": true
};
moengage.openDeepLink(value, attributes);
```
## Open Richlanding Screen
To open a Richlanding screen use `moengage.openRichLanding(, )`.
```javascript JavaScript theme={null}
var value = "https://www.google.com";
// Optionally add data json object
var attributes = {
"nav_screen_attr1": "val1",
"nav_screen_attr2": 100,
"nav_screen_attr3": 123.11,
"nav_screen_attr4": true
};
moengage.openRichLanding(value, attributes);
```
## Open Web URL
To open a URL in a web browser use `moengage.openWebURL(, )`.
```javascript JavaScript theme={null}
var value = "https://www.google.com";
// Optionally add data json object
var attributes = {
"nav_screen_attr1": "val1",
"nav_screen_attr2": 100,
"nav_screen_attr3": 123.11,
"nav_screen_attr4": true
};
moengage.openWebURL(value, attributes);
```
# Copy Text to Clipboard
To copy text to clipboard use `moengage.copyText(, )` API.
```javascript JavaScript theme={null}
moengage.copyText("COUPON100", "Rs.100 OFF!");
```
# Call
To perform call action use `moengage.call(` API.
```javascript JavaScript theme={null}
moengage.call("1234567890");
```
# SMS
To send an SMS use `moengage.sms(, )` API.
```javascript JavaScript theme={null}
moengage.sms("1234567890", "Hi There!");
```
# Share
To share a string content use `moengage.share()` API.
```javascript JavaScript theme={null}
moengage.share("Content to share");
```
# Custom Action
To perform custom action set the data using `moengage.customAction()` API.
```javascript JavaScript theme={null}
var attributes = {
"attr1": "val1",
"attr2": 100,
"attr3": 123.11,
"attr4": {
"int": 30
}
};
moengage.customAction(attributes);
```
# Data Tracking
The following sections will provide more details on the JS Methods for data tracking.
**JS Methods for Data Tracking**
You would need to integrate the JS Methods for Data Tracking in your template for the following use-cases:
* Tracking stats (clicks, close)
* Tracking events (for surveys, rating, lead gen)
* Tracking user attributes (for lead gen, signup etc.)
## Track Event
To track an event use `moengage.trackEvent(eventName, generalAttrJson, locationAttrJson, dateAttrJson, isNonInteractive, shouldAttachCampaignMeta)` API.
The trackEvent() takes in up to six parameters.
* eventName : String
* generalAttrJson : JSON Object for general attributes. Accepted data types are string, float, boolean, int, JSON objects.
```javascript JavaScript theme={null}
{
" ": " ",
" ": " ",
...
}
```
* locationAttrJson : JSON Object for location attributes. Accepts attribute name and latitude and longitude
```javascript JavaScript theme={null}
{
" ": {
"latitude": ,
"longitude":
},
" ": {
"latitude": ,
"longitude":
},
...
}
```
* dateAttrJson : JSON Object for date-time attributes. Accepts only ISO-8601 format dates
```javascript JavaScript theme={null}
{
" ": "yyyy-MM-dd'T'HH:mm:ss.fff'Z'",
" ": "yyyy-MM-dd'T'HH:mm:ss.fff'Z'",
...
}
```
* isNonInteractive: true if you want the event to be non-interactive, else false.
* shouldAttachMetaData: true if you want to attach campaign metadata to the event, else false.
Apart from the `eventName` parameter, other parameters are non-mandatory you can pass `{}`.\
It is important to maintain the order in which parameters are passed, i.e. if you want to pass only the location attributes general attribute should be passed `{}`.
For general cases, you would just be passing the event-name and event-attributes JSON and in this case you can skip the other params. A method for this case would be like - **`moengage.trackEvent("Response_Submitted", {"response1":"johndoe@gmail.com","response2":"approved"})`**
## Track Click Event
To track widget click events use `moengage.trackClick(widgetId)` API. The `` can be int or string, otherwise, the click event will not be tracked.
```javascript JavaScript theme={null}
//track click event
moengage.trackClick("image_1");
moengage.trackClick(10);
```
## Track Dismiss
To track in-app dismissal events, use `moengage.trackDismiss(widgetId)` API. The `` can be int or string. If not passed, the dismiss event will be tracked without widgetID. If not passed, the event will get tracked without ``
```javascript JavaScript theme={null}
moengage.trackDismiss("dismiss_btn_1");
moengage.trackDismiss(1);
```
## Track Dismiss(Deprecated - Use Above API with widget ID instead)
To track the in-app dismissal use `moengage.trackDismiss()` API.
```javascript JavaScript theme={null}
moengage.trackDismiss();
```
## Track Default User Attributes
The following JavaScript methods are available for tracking default user attributes.
| API name | API Description |
| ---------------------------- | ---------------------------------------------------------------------------- |
| moengage.setAlias() | Update user's unique id which was previously set by \`moengage.setUniqueId() |
| moengage.setUniqueId() | Set user UniqueId |
| moengage.setUserName() | Set user name |
| moengage.setFirstName() | Set user first name |
| moengage.setLastName() | Set user last name |
| moengage.setEmailId() | Set user email-id |
| moengage.setMobileNumber() | Set user mobile number |
| moengage.setGender() | Set user gender ("male"/"female"/"other") |
| moengage.setBirthDate() | Set user birthday NOTE: the value must be ISO-8601 format dates. |
| moengage.setUserLocation(, ) | Set user location |
| moengage.trackRating() | Track user input action rating |
Example:
```javascript JavaScript theme={null}
// Set alias
moengage.setAlias("user-alias");
// Set UniqueId
moengage.setUniqueId("unique-id");
// Set user name
moengage.setUserName("John Doe");
// Set user first name
moengage.setFirstName("Jane");
//Set user last name
moengage.setLastName("Doe");
// Set Email id
moengage.setEmailId("abc@abc.com");
// Set mobile number
moengage.setMobileNumber("1234567890");
// Set User gender
moengage.setGender("female");
// Set user birthday
moengage.setBirthDate("2017-08-02T06:05:30.000Z");
//Set user location
moengage.setUserLocation(3.0539652, 77.672683);
// Set rating value
moengage.trackRating(4.5);
```
## Track Custom user attributes
The following JavaScript methods are available for tracking custom user attributes.
| API name | API description |
| --------------------------------------- | ------------------------- |
| moengage.setUserAttribute(, ) | Set custom user attribute |
| moengage.setUserAttributeDate(, ) | Set custom user date |
| moengage.setUserAttributeLocation(, , ) | Set custom user location |
Example:
```javascript JavaScript theme={null}
// Set custom user attribute
moengage.setUserAttribute("int", 100);
moengage.setUserAttribute("float", 10.5);
moengage.setUserAttribute("String", "test");
moengage.setUserAttribute("Boolean", true);
//Set custom date attribute
moengage.setUserAttributeDate("Date1", "2017-08-02T06:05:30.000Z");
//Set custom user location
moengage.setUserAttributeLocation("Location 1", 3.0539652, 77.672683);
```
# Deprecation for Older Platform Versions
Source: https://moengage.com/docs/developer-guide/components-for-sdk/platform-updates/deprecation-for-older-platform-versions
Review deprecated Android API levels and iOS versions in MoEngage SDK releases after April 2025.
MoEngage will support at minimum API level 23 for Android and iOS 13 for iOS starting April 26th, 2025, and a minimum of iOS 13 for iOS starting May 27th, 2025. Currently, the MoEngage SDK supports [Android API level](https://source.android.com/docs/setup/reference/build-numbers) \[Placeholder\_Link] 21 and 22 (Android 5, Lollipop) for Android and iOS 12 for iOS devices. Releases after April 26th, 2025, for Android and May 27th, 2025, for iOS, will increase the minimum supported:
* API level from 21 to 23 (Android 6, Marshmallow) for Android
* iOS 12 to iOS 13 for iOS
# Why Are We Discontinuing Support for API Level 21 and 22 and iOS 12 in MoEngage SDK?
## For Android
The Lollipop platform and iOS 12 are almost 8 and 6 years old respectively. A very small percentage of all Android devices are using these or lesser versions. You can read more about the current distribution of Android devices. We believe that many of these old devices are not actively being used.
Many developers have already discontinued support for these versions in their apps. This helps them build better apps that make use of the newer capabilities of the platforms. For MoEngage, the situation is the same. By making this change, MoEngage can provide a more robust collection of tools for developers with greater speed.
# What Does This Mean for Your App That Uses MoEngage SDK?
You may use versions of MoEngage SDK released before April 26th, 2025 (for Android) and May 27th, 2025 (for iOS), as you are currently using. These versions will continue to work with Lollipop and iOS 12 devices, as they have worked in the past
When you choose to upgrade to the future versions released after April 26th, 2025 (for Android) and May 27th, 2025 (for iOS), you will not encounter any versioning problems if your app supports:
* Android API level 23 or greater (typically specified as “minSdkVersion” in your build.gradle)
* iOS 13
However, if your app supports lower than API level 21 or 22 or iOS 12, you will encounter a problem at build time with an error. This means, you will not be able to successfully run your app on older devices. To use MoEngage SDK versions released after April 26th, 2025 (for Android) and May 27th, 2025 (for iOS), you can choose one of the following options:
## For iOS
To discontinue support for iOS 12, perform the following changes in the **General** tab of your target XCode project:
1. Select the minimum iOS version you want to support in the **Deployment Target** drop-down list.
2. If your app is compatible with multiple devices, make sure to set the minimum iOS version for each device type (iPhone, iPad, and so on) in the same **Deployment Info** section.
## For Android
* Target API level 23 as the minimum supported API level (recommended)
To discontinue support for API levels that are no longer supported by the MoEngage SDK, increase the minSdkVersion value in your app’s build.gradle to at least 23. If you update your app in this way and publish it to the Play Store, users of devices with less than that level of support cannot see or download the update. However, they can still download and use the most recently published version of the app that does target their device.
For Android devices, if your app still has a significant number of users on older devices, you can use multiple APK support in Google Play to deliver an APK that uses lower versions of the MoEngage SDK. This is described below.
* Build multiple APKs to support devices with an API level less than 23 (not recommended).
With some configuration and code management, you can [build multiple APKs](https://developer.android.com/training/multiple-apks/api.html) \[Placeholder\_Link] that support different minimum API levels, with different versions of the MoEngage SDK. You can accomplish this with [build variants](https://developer.android.com/studio/build/build-variants.html) \[Placeholder\_Link] in Gradle. First, define build flavors for legacy and newer versions of your app. For example, in your build.gradle, define two different product flavors, with two different compile dependencies for the components of Play Services you are using:
```Kotlin Kotlin theme={null}
productFlavors {
legacy {
minSdkVersion 9??
versionCode 901 // Min API level 9, v01??
}
current {
minSdkVersion 14??
versionCode 1401 // Min API level 14, v01??
}
}
dependencies {
legacyCompile 'com.google.android.gms:play-services:10.0.0'??
currentCompile 'com.google.android.gms:play-services:10.2.0'??
}
```
In the situation above, there are two product flavors being built for two different versions of the Google Play services client libraries. This will work fine if only APIs available in lower MoEngage SDK versions are called. If you need to call newer APIs made available with versions released after April 26th, 2025, you must create a compatibility library for the newer API calls so that they are only built into the version of the application that can use them:
* Declare a Java interface that exposes the higher-level functionality you want to perform that is only available in the current versions of Play services.
* Build two Android libraries that implement that interface. The *current* implementation must call the newer APIs as desired. The *legacy* implementation must no-op or otherwise act as desired with older versions of the MoEngage SDK. You must add the interface to both libraries.
* Conditionally compile each library into the app using *legacyCompile* and *currentCompile* dependencies.
* In the app’s code, call through to the compatibility library whenever newer MoEngage SDK APIs are required.
After building a release APK for each flavour, publish them both to the Play Store, and the device will update with the most appropriate version for that device. Read more about [multiple APK support in the Play Store](https://developer.android.com/google/play/publishing/multiple-apks). \[Placeholder\_Link]
For any queries, please contact your MoEngage Customer Success Manager (CSM) or the Support team.
# Android Push Configuration For Hybrid Applications
Source: https://moengage.com/docs/developer-guide/components-for-sdk/push-notification/android-push-configuration-for-hybrid-applications
Configure Android push notification metadata and FCM authentication for your hybrid MoEngage app.
# Configuring your MoEngage Account
* Please make sure you have set up [Firebase](https://firebase.google.com/docs/android/setup) in your application.
* Configure FCM Authorization on the MoEngage Dashboard. For more information, refer to [FCM Authentication](/developer-guide/android-sdk/push/basic/fcm-authentication).
* Ensure you add the keys in both the Test and Live environments.
## Adding metadata for push notification
Metadata regarding the notification is required to show push notifications where the small icon and large icon drawable are mandatory.
For more information about API reference for all the possible options, refer to [NotificationConfig](https://moengage.github.io/android-api-reference/core/com.moengage.core/%5Bandroid-jvm%5D-mo-engage/-builder/index.html).
Use the [*configureNotificationMetaData()*](https://moengage.github.io/android-api-reference/core/com.moengage.core/%5Bandroid-jvm%5D-mo-engage/-builder/index.html) to transfer the configuration to the SDK.
```Kotlin Kotlin theme={null}
import com.moengage.core.DataCenter
import com.moengage.core.MoEngage
val moEngage = MoEngage.Builder(this, "YOUR_Workspace_ID", [YOUR_DATA_CENTER])
.configureNotificationMetaData(NotificationConfig(R.drawable.small_icon, R.drawable.large_icon))
MoEInitializer.initializeDefaultInstance(applicationContext, moEngage)
```
```Java Java theme={null}
import com.moengage.core.DataCenter;
import com.moengage.core.MoEngage;
MoEngage.Builder moEngage = new MoEngage.Builder(this, "YOUR_Workspace_ID", [YOUR_DATA_CENTER])
.configureNotificationMetaData(new NotificationConfig(R.drawable.small_icon, R.drawable.large_icon));
MoEInitializer.INSTANCE.initializeDefaultInstance(getApplicationContext(), moEngage);
```
Could you make sure that the SDK is initialized with the metadata in the onCreate() of the Application class for push notifications to work?
**Notification Small Icon Guidelines**
The notification small icon should be flat, pictured face on, and must be white on a transparent background.
## Notification Small Icon Density, Size
| Density (dp) | Size (px) |
| ------------ | --------- |
| MDPI | 24x24 |
| HDPI | 36x36 |
| XHDPI | 48x48 |
| XXHDPI | 72x72 |
| XXXHDPI | 96x96 |
**Critical**
Please ensure the small icon is set. If the small icon is not set, notifications will not be displayed.
# Real-time Uninstall Tracking
Source: https://moengage.com/docs/developer-guide/components-for-sdk/tracking/real-time-uninstall-tracking
Track app uninstalls in real time using Firebase Cloud Functions instead of daily silent push notifications.
# What is real-time uninstall tracking?
Real-time uninstall tracking enables you to track the uninstall immediately after the user uninstalls an app integrated with *Firebase Analytics*.
The Firebase tracks the event **app-remove** when an app is uninstalled. The **app-remove** event is used by MoEngage using Firebase Cloud Functions.
# What are Firebase Cloud Functions?
Cloud Functions for Firebase is a serverless framework that programmatically provides responses to events triggered by Firebase features and HTTPS requests. For more information, refer to [Cloud Functions for Firebase](https://firebase.google.com/docs/functions).
# How is real-time uninstall tracking different from the existing uninstall tracking?
The current uninstall tracking in MoEngage happens by sending Silent Push notifications once a day to all user devices. Up to 24 hours is required to track uninstall.
Using the real-time uninstall tracking, the uninstall is tracked immediately by the Firebase SDK so that you can respond quickly to user uninstalls
# Implementation of real-time uninstall tracking
Ensure you have the Firebase Blaze plan account.
To deploy Cloud Functions to the runtime environment, your project must be on the [Firebase pricing plan](https://firebase.google.com/pricing).
## Set up a common identifier
Ensure your app has integrated Firebase Analytics SDK. For more information, refer to [Get started with Google Analytics](https://firebase.google.com/docs/analytics/get-started).
Add the following code in your app to set up a common identifier between MoEngage and Firebase.
```kotlin Kotlin theme={null}
val firebaseAnalytics = FirebaseAnalytics.getInstance(this)
MoEHelper.getInstance(this).setUniqueId("")
firebaseAnalytics.setUserProperty("MOE_USER_ATTRIBUTE_UNIQUE_ID", "")
}
```
**Note:** The following values are not allowed in the UniqueID field: "unknown", "guest", "null", "0", "1", "true", "false", "user\_attribute\_unique\_id", "(empty)", "na", "n/a", "", "dummy\_seller\_code", "user\_id", "id", "customer\_id", "uid", "userid", "none", "-2", "-1", "2"
## Set up the conversion event using Firebase
Ensure that the App is integrated with Firebase Analytics for real-time uninstall tracking.
Firebase analytics automatically collects the event `app_remove`. The `app_remove` event is, an Android-only event, tracked when an application package is removed or uninstalled from the device, regardless of the installation source. To set up a real-time uninstall make sure that the `app_remove` event is marked as the conversion event on the Firebase dashboard.
To set up a conversion event, follow these steps:
1. Navigate to [Firebase Console](https://console.firebase.google.com/) and select the Firebase project integrated with the app.
2. From the Firebase dashboard, select **Analytics > Events**.
3. Enable the ***Mark as Conversion*** toggle for **app\_remove** event in the event list.
## Create Cloud Function
After the conversion event is set up, use the [Cloud Function for Firebase](https://firebase.google.com/docs/functions/get-started) to create a function and send the **app\_remove** event to MoEngage.
To create and publish a cloud function using Node JS, follow these steps:
1. Install [Node.js](https://nodejs.org/en/) and [npm](https://www.npmjs.com/).\
Node.js environment is required to write functions. Use the Firebase CLI to deploy functions to the Cloud Functions runtime.
2. Install Firebase CLI using the following code:
```CLI CLI Command theme={null}
npm install -g firebase-tools
```
3. Run ***firebase login*** to log in using the browser and authenticate the firebase tool.
4. Navigate to your Firebase project directory.
5. Run ***firebase init functions***.
6. Select ***Javascript*** as a language option.
7. Add the following code to the **index.js** file:
```javascript index.js theme={null}
"use strict";
const functions = require("firebase-functions");
const admin = require("firebase-admin");
const https = require("https");
require("firebase-functions/lib/logger/compat");
admin.initializeApp();
exports.sendAndroidUninstallToMoEngage = functions.analytics.event("app_remove")
.onLog((event) => {
console.log("sendAndroidUninstallToMoEngage() : Event is: " +
JSON.stringify(event));
return exports.sendAppUninstallEventData(event);
});
exports.sendAppUninstallEventData = function(event) {
//fetch the unique ID
var uniqueId = event.user.userProperties.MOE_USER_ATTRIBUTE_UNIQUE_ID.value;
//send event using S2S API of MoEngage
//https://developers.moengage.com/hc/en-us/articles/4404674776724-Data-API#user-api-0-10
};
```
8. Add the following code to **package.json** file:
```json pacakage.json theme={null}
{
"name": "functions",
"description": "Cloud Functions for Firebase",
"scripts": {
"lint": "eslint .",
"serve": "firebase emulators:start --only functions",
"shell": "firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"engines": {
"node": "12"
},
"main": "index.js",
"dependencies": {
"firebase-admin": "^10.0.0",
"firebase-functions": "^3.16.0",
"firebase-tools": "^9.23.0",
"g": "^2.0.1",
"requestretry": "^4.1.1"
},
"devDependencies": {
"eslint": "^7.6.0",
"eslint-config-google": "^0.14.0",
"eslint-plugin-promise": "^4.0.1",
"firebase-functions-test": "^0.2.0",
"requestretry": "^4.1.1",
"web-push": "^3.4.5"
},
"private": true
}
```
# Delete User From MoEngage Server
Source: https://moengage.com/docs/developer-guide/cordova-sdk/data-tracking/delete-user-from-moengage-server
Delete the current user from the MoEngage server using the Cordova SDK on Android.
This API is supported from **cordova-moengage-core** version **8.4.0** and is only available for the Android platform and is a no-operation for other platforms.
To delete the current user from the MoEngage server use ***deleteUser()*** method as shown below
```javascript JavaScript theme={null}
var moe = MoECordova.init(YOUR_Workspace_ID);
moe.deleteUser().then(result =>
//add your code to handle the callback
console.log("User Deletion Result",result.toString())
).catch(error =>
//add your code to handle the Error
console.error("Error while Deleting User",error.toString())
);
```
# Enable Advertising Identifier Tracking
Source: https://moengage.com/docs/developer-guide/cordova-sdk/data-tracking/enable-advertising-identifier-tracking
Enable advertising identifier tracking in your Cordova app for accurate device analytics.
For accurate analytics around devices and tracking Re-installs, it is essential to track the Advertising Identifier.
This is not supported in iOS
## Add Ad Identifier Library
Add the below dependency in the application level ***build-extras.gradle*** file.
```groovy Groovy theme={null}
implementation("com.google.android.gms:play-services-ads-identifier:18.0.1")
```
To enable Advertising Identifier tracking use the *enableAdIdTracking()* method as shown below.
```javascript Javascript theme={null}
var moe = MoECordova.init(YOUR_Workspace_ID);
moe.enableAdIdTracking();
```
Before you enable Advertising Id tracking please ensure the application is complying with the [Google Play Policy](https://support.google.com/googleplay/android-developer/answer/10144311) regarding Advertising Id tracking. Refer to our [help document](https://help.moengage.com/hc/en-us/articles/7457641031828) for more information on the policy.
In case, you need to disable advertising-id after enabling tracking use the following method.
```javascript Javascript theme={null}
var moe = MoECordova.init(YOUR_Workspace_ID);
moe.disableAdIdTracking();
```
The above APIs are available only starting plugin version 7.3.3. In the older versions, Advertising Identifier tracking is enabled by default.
# Install/Update differentiation
Source: https://moengage.com/docs/developer-guide/cordova-sdk/data-tracking/install-update-differentiation
Set the app status as install or update in the MoEngage Cordova SDK for migration tracking.
This is solely required for migration to the MoEngage Platform. We need your help to tell the SDK whether the user is a new user for on your app(first Install) or an existing user who has updated to the latest version.
Make use of the **setAppStatus** method as shown below to track Install/Update as shown below:
```javascript JavaScript theme={null}
var moe = MoECordova.init(YOUR_Workspace_ID);
// For fresh Install
moe.setAppStatus("INSTALL");
// For tracking App Update
moe.setAppStatus("UPDATE");
```
# Tracking Events
Source: https://moengage.com/docs/developer-guide/cordova-sdk/data-tracking/tracking-events
Track user actions and event attributes using the MoEngage Cordova SDK for segmentation and campaigns.
SDK adheres to the MoEngage FUP policies. For more information, refer to the [Fair Usage Policy](https://help.moengage.com/hc/en-us/articles/24151864954644-Fair-Usage-Policy-FUP#h_01HQSMZVQWT2KYP0PY1P8GQMRM).
Tracking events is how you record any actions your users perform, along with any properties that describe the action.
```javascript JavaScript theme={null}
var moe = MoECordova.init(YOUR_APP_ID);
moe.trackEvent(eventName, generalAttributes, locationAttributes, dateTimeAttributes, isNonInteractive);
```
The trackEvent() takes in 5 parameters eventName and eventAttribute.
* eventName : String
* generalAttributes : JSON Object for general attributes. Accepted data types are string, number, boolean
```json JSON theme={null}
{
"": "",
"": "",
"": "",
...
}
```
* locationAttributes: JSON Object for location attributes. Accepts attribute name and latitude and longitude
```json JSON theme={null}
{
"": {
"latitude": ,
"longitude":
},
"": {
"latitude": ,
"longitude":
},
"": {
"latitude": ,
"longitude":
},
...
}
```
* dateTimeAttributes: JSON Object for date-time attributes. Accepts only ISO-8601 format dates
```json JSON theme={null}
{
"": "yyyy-MM-dd'T'HH:mm:ss.fff'Z'",
"": "yyyy-MM-dd'T'HH:mm:ss.fff'Z'",
"": "yyyy-MM-dd'T'HH:mm:ss.fff'Z'",
...
}
```
* isNonInteractive: true if you want the event to be non-interactive, else false.
Apart from the **eventName** parameter, other parameters are non-mandatory you can choose to pass **null** or or **undefined**.\
It is important to maintain the order in which parameters are passed, i.e. if you want to pass only the location attributes general attribute should be passed **null** or or **undefined**
Example
```json JSON theme={null}
moe.trackEvent("testEvent", {"attr1": "string", "attr2": 123, "attr3": false},{"loc1": { "latitude": 14.90123,"longitude": 13.1627} },
{"date1" : "2017-08-02T06:05:30.000Z"}, true);
```
You can not use "moe\_" as a prefix while naming events, event attributes, or user attributes. It is a system prefix and using it might result in periodic blacklisting without prior communication.
# Analytics
MoEngage SDK has started tracking user session and application traffic source. Refer to the [Sessions in MoEngage Analytics](https://help.moengage.com/hc/en-us/articles/35724347745812-Session-and-Source-Overview) and [Source Analysis in MoEngage Analytics](https://help.moengage.com/hc/en-us/articles/35724347745812-Session-and-Source-Overview) to learn more about how user session and application traffic source tracking works.
With user session tracking we have introduced the flexibility to selectively mark events as non-interactive.
## What is a non-interactive event?
Events that do not affect the session calculation in anyways are called non-interactive events. Non-interactive events have the below properties
* Do not start a new session.
* Do not extend the session.
* Do not have information related to a user session.
# Tracking User Attributes
Source: https://moengage.com/docs/developer-guide/cordova-sdk/data-tracking/tracking-user-attributes
Track user attributes and manage login and logout states using the MoEngage Cordova SDK.
User Attributes are pieces of information you know about a user which could be demographics like age or gender, account-specific like plan, or even things like whether a user has seen a particular A/B test variation. It's up to you! It is basically a customer identity that you can reference across the customer’s whole lifetime.
# Implementing Login/Logout
* It's important to set the User Attribute Unique ID when a user logs into your app.
* This is to merge the new user with the existing user, if any exists, and will help prevent creation of unnecessary/stale users.
* Setting the Unique ID is a critical piece to tie a user across devices and installs/uninstalls as well across all platforms (i.e. iOS, Android, Windows, The Web). Set the **USER\_ATTRIBUTE\_UNIQUE\_ID** attribute as soon as the user is **logged in**. Unique ID can be something like an email ID, a username (unique), or a database ID or any Backend generated ID.
* Do not set this for the user who not logged in.
## Login
```javascript JavaScript theme={null}
var moe = MoECordova.init(YOUR_Workspace_ID);
moe.setUniqueId(uniqueID);
```
**Note:** The following values are not allowed in the UniqueID field: "unknown", "guest", "null", "0", "1", "true", "false", "user\_attribute\_unique\_id", "(empty)", "na", "n/a", "", "dummy\_seller\_code", "user\_id", "id", "customer\_id", "uid", "userid", "none", "-2", "-1", "2"
## Logout
The application needs to notify the MoEngage SDK whenever the user is logged out of the application. To notify the SDK, call the API whenever the user is logged out of the application.
```javascript JavaScript theme={null}
var moe = MoECordova.init(YOUR_Workspace_ID);
moe.logout();
```
To clear out the existing user's data and identity, call the logout method. This will clear the data for the current user and create a new one, when you re-login as explained in the above log-in scenario your user will be merged (if already exist in our system)
## Updating User Attribute Unique ID
In a scenario where you have to update the User Attribute Unique ID value for a logged-in user use ***setAlias()*** as shown below:
```javascript JavaScript theme={null}
var moe = MoECordova.init(YOUR_Workspace_ID);
moe.setAlias("updatedUniqueID");
```
Please make sure that you use ***setAlias()*** for updating the User Attribute Unique ID and not ***setUserAttribute()*** with **USER\_ATTRIBUTE\_UNIQUE\_ID** attribute and a new value, as this will reset the current user and lead to the creation of unintended users in our system.
# SDK User Attributes Keys
You can also set the default user attributes like mobile number, gender, user name, birthday, location, etc using the below APIs
```javascript JavaScript theme={null}
var moe = MoECordova.init(YOUR_Workspace_ID);
moe.setUserName("abc");
moe.setFirstName("abc");
moe.setLastName("xyz");
moe.setEmail("abc@xyz.com");
moe.setPhoneNumber(1234567890);
moe.setGender("Male"); // OR Female
moe.setLocation(25.23, 73.23);
// Format - ISO-8601 String
moe.setBirthdate("1970-01-01T12:00:00Z");
```
For setting custom user attributes, use the method **setUserAttribute(key, value).**
```javascript JavaScript theme={null}
var moe = new MoECordova.init(YOUR_Workspace_ID);
moe.setUserAttribute("", "");
```
Date attributes and Birthday in ISO-8601 format -**yyyy-MM-dd'T'HH:mm:ss'Z'**
```javascript JavaScript theme={null}
var moe = MoECordova.init(YOUR_Workspace_ID);
moe.setUserAttributeLocation("attribute", 25.23, 73.23);
```
You can use the following method set the timestamp user attribute :
```javascript JavaScript theme={null}
var moe = MoECordova.init(YOUR_Workspace_ID);
moe.setUserAttributeISODateString("LastPurchaseDate", "1970-01-01T12:00:00Z");
```
You can not use "moe\_" as a prefix while naming events, event attributes, or user attributes. It is a system prefix and using it might result in periodic blacklisting without prior communication.
## Custom Boolean User Attribute
### iOS(optional)
Starting from version 9.x.x of cordova-moengage-core, the default tracking for the custom boolean attribute will be changed to ***boolean(true/false)*** from ***double(0/1)***. To configure this, use ***analyticsConfig*** with ***shouldTrackUserAttributeBooleanAsNumber*** and pass true to track the boolean as double. By default, this is set as ***false*** to track boolean as true/false
Refer to the initialization code snippet below.
```java TypeScript theme={null}
let initializationConfig = {analyticsConfig: {shouldTrackUserAttributeBooleanAsNumber: true}};
var moe = MoECordova.init(YOUR_Workspace_ID, initializationConfig);
```
Refer to the example code below for tracking the boolean user attribute
```java TypeScript theme={null}
var moe = new MoECordova.init(YOUR_Workspace_ID);
/// If shouldTrackUserAttributeBooleanAsNumber is passed as true then `boolean attribute True` will tracked with value 1 else true
moe.setUserAttribute("boolean attribute True", true);
/// If shouldTrackUserAttributeBooleanAsNumber is passed as true then `boolean attribute False` will tracked with value 0 else false
moe.setUserAttribute("boolean attribute False", false);
```
## Reserved keywords for User Attributes
Below is the list of keys that should not be used when tracking user attributes.
* USER\_ATTRIBUTE\_UNIQUE\_ID
* USER\_ATTRIBUTE\_USER\_EMAIL
* USER\_ATTRIBUTE\_USER\_MOBILE
* USER\_ATTRIBUTE\_USER\_NAME
* USER\_ATTRIBUTE\_USER\_GENDER
* USER\_ATTRIBUTE\_USER\_FIRST\_NAME
* USER\_ATTRIBUTE\_USER\_LAST\_NAME
* USER\_ATTRIBUTE\_USER\_BDAY
* USER\_ATTRIBUTE\_NOTIFICATION\_PREF
* USER\_ATTRIBUTE\_OLD\_ID
* MOE\_TIME\_FORMAT
* MOE\_TIME\_TIMEZONE
* USER\_ATTRIBUTE\_DND\_START\_TIME
* USER\_ATTRIBUTE\_DND\_END\_TIME
* MOE\_GAID
* INSTALL
* UPDATE
* MOE\_ISLAT
* status
* user\_id
# InApp NATIV
Source: https://moengage.com/docs/developer-guide/cordova-sdk/in-app-messages/inapp-nativ
Set up MoEngage in-app NATIV campaigns in your Cordova app to show contextual messages to users.
In-App Messaging is custom views that you can send to a segment of users to show custom messages or give new offers or take to some specific pages. They can be created from your MoEngage account.
## Install Android Dependency
## Install using BOM
Integration using BOM is the recommended way of integration; refer to the [Install Using BOM ](/developer-guide/android-sdk/sdk-integration/basic-integration/Install-Using-BOM)document. Once you have configured the BOM add the dependency in the *app/build.gradle* file as shown below:
```json build.gradle wrap theme={null}
dependencies {
...
implementation("com.moengage:inapp")
}
```
Once the BOM is configured, include the specific MoEngage modules required for the application. \
Note: Version numbers are not required for these dependencies; the BOM automatically manages them.
## Manual installation

Add the following dependency in the \*\*android/\*\****app/build-extras.gradle*** file.
```json build-extras.gradle theme={null}
dependencies {
...
implementation("com.moengage:inapp:\$sdkVersion")
}
```
replace **\$sdkVersion** with the appropriate SDK version
### **Requirements for displaying images and GIFs in InApp**
Starting InApp version **7.0.0,** SDK requires [Glide](https://bumptech.github.io/glide/) to show images and GIFs in the in-apps. You need to add the below dependency in your **build.gradle** file.
```groovy Groovy theme={null}
dependencies {
...
implementation("com.github.bumptech.glide:glide:4.16.0")
}
```
# How to show In-App Messages?
Use **showInApp()** method to show inApp as shown below:
```javascript JavaScript theme={null}
var moe = MoECordova.init(YOUR_Workspace_ID);
moe.showInApp();
```
# Nudges
Nudges are non-intrusive In-App messages that can be displayed at various positions on the screen. Use the **showNudge()** method to display them:
```javascript JavaScript theme={null}
var moe = MoECordova.init(YOUR_Workspace_ID);
// To show a nudge with the Top position
moe.showNudge(MoENudgePosition.top);
// To show a nudge with the Bottom position
moe.showNudge(MoENudgePosition.bottom);
// To show a nudge with the BottomLeft position
moe.showNudge(MoENudgePosition.bottomLeft);
// To show a nudge with the BottomRight position
moe.showNudge(MoENudgePosition.bottomRight);
// To show a nudge with the Any position
moe.showNudge(MoENudgePosition.any);
```
# InApp/Nudge Redirection default behavior
On clicking an Inapp or Nudge, MoEngage SDKs will handle **only rich landing navigation** redirection.
For the screen name and deep link redirection, your app code should redirect the user to the right screen or deep link. To handle the screen name and deep link redirection, you must implement inapp click callback methods. MoEngage SDK will just pass the inapp payload to this call back code. Implementation steps are mentioned in the InApp callback section of the Integration.
# Context-Based InApps
We have introduced context-based InApps. While creating InApp campaigns you can set the contexts OR tags to the campaign. SDK will check with the current context set in the App and show the inApp only when a current set context matches the campaign context.
## Set Current Context:
To set the current context for the InApp module use **setCurrentContext()** method as shown below:
```javascript JavaScript theme={null}
moe.setCurrentContext(\["Home","CategoriesScreen"\]);
```
## Reset Context:
To reset the current context for the InApp module call **resetCurrentContext()** method:
```javascript JavaScript theme={null}
moe.resetCurrentContext();
```
# Self Handled In-App Messaging
The SDK does not show self-handled In-Apps. While creating the campaign, a JSON payload has to be provided in the dashboard. The same payload will be provided to the app by the SDK on calling the **getSelfHandledInApp()** method, and info will be received by a callback post all the delivery controls are checked:
```javascript JavaScript wrap theme={null}
var moe = MoECordova.init(YOUR_Workspace_ID);
moe.getSelfHandledInApp();
//Callback for receiving self-handled inapp
moe.on('onInAppSelfHandle', function(selfHandledPayload) {
console.log('Self hanlded InApp Info: ' + JSON.stringify(selfHandledPayload));
});
```
Post consuming the Self-handled inApp, to update impression, click and dismiss stats call the following methods with the payload received in self-handled In-App callback:
```javascript JavaScript theme={null}
var moe = MoECordova.init(YOUR_Workspace_ID);
// Track impression
moe.selfHandledShown(selfHandledPayload)
// Track Click
moe.selfHandledClicked(selfHandledPayload)
// Track Dismiss
moe.selfHandledDismissed(selfHandledPayload)
```
# In-App Messaging Rules
We use the following rules while showing the In-App:
Preconditions for In-App to work:
* If InApp Backend Sync was successful in the current session or not.
* Check if the Device is NOT iPad/Tablet.
* Check if InApp is disabled on the current screen.
* Check Device Orientation is Portrait(Landscape is not supported).
The following are checked for each campaign in the list of active campaigns(sorted according to priority and Last Updated Time)
* Check Global Delay has lapsed, skip this if **Ignore Global Delay** set for the campaign.
* Check if the campaign has expired
* Display Rules
* Check Show Only on Screen
* Check with current contexts
* Delivery Controls
* Persistence Check(If the primary action of InApp is done but still want to show the inApp)
* Check if the campaign has been shown max times
* Check if the campaign level delay has crossed.
The first campaign satisfying all the rules is shown to the user.
# Callback in JavaScript on In-App Events
To get a callback in javascript on in-app events you need to register for a click listener as shown below.
Minimum Plugin version required: 6.0.0
```javascript JavaScript wrap theme={null}
var moe = MoECordova.init(YOUR_Workspace_ID);
moe.on('onInAppShown', function(inAppInfo) {
console.log('InApp Shown with Info: ' + JSON.stringify(inAppInfo));
});
moe.on('onInAppClick', function(inAppInfo) {
console.log('InApp Shown Clicked with Info: ' + JSON.stringify(inAppInfo));
});
moe.on('onInAppDismiss', function(inAppInfo) {
console.log('InApp Dismissed with Info: ' + JSON.stringify(inAppInfo));
});
moe.on('onInAppCustomAction', function(inAppInfo) {
console.log('InApp Custom Action with Info: ' + JSON.stringify(inAppInfo));
});
```
## Payload Structure in Callbacks
InAppInfo received in the callbacks above have the following structure:
```javascript JavaScript wrap theme={null}
{
"accountMeta": {
"appId": ""
},
"data": {
"platform": "iOS/android",
"campaignName": "",
"campaignId": "",
"campaignContext": {},
"actionType": "navigation",
"navigation": { // Key will only be present for onInAppClick callback
"navigationType": "screen/deep_linking",
"value": "",
"kvPair": {
"k1": "v1"
}
},
"customAction": {// Key will only be present for onInAppCustomAction callback
"kvPair": {
"k2": "v2"
}
},
"data": { // Key will only be present for onInAppSelfHandle callback
"payload": "", // payload entered in dashboard while creating selfHandled campaign
"dismissInterval": 60 // auto dismiss interval
}
}
}
```
# Handling Orientation Change
This is only for the Android platform.
Starting SDK version **7.3.0** in-apps are supported in both portrait and landscape modes. SDK has to be notified when the device orientation changes for SDK to handle in-app display.
There are two ways to do it:
1. Add the API call in the Android native part of your app
2. Call MoEngage plugin's **onOrientationChanged()**
## Add the API call in the Android native part of your app
Notify the SDK when **onConfiguartionChanged()** API callback is received in your App's Activity class.
```java Java wrap theme={null}
import android.os.Bundle;
import org.apache.cordova.\*;
import com.moengage.cordova.MoECordovaHelper;
public class MainActivity extends CordovaActivity {
...
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
MoECordovaHelper.getInstance().onConfigurationChanged();
...
}
...
}
```
## Call MoEngage plugin's orientation change API
Call the below API to notify SDK of the orientation change.
```javascript JavaScript wrap theme={null}
var moe = MoECordova.init(YOUR_Workspace_ID);
...
// Notify SDK on orientation change
moe.onOrientationChanged();
```
# Migrating to 4.x.x
Source: https://moengage.com/docs/developer-guide/cordova-sdk/migration/migrating-to-4xx
Migrate your MoEngage Cordova plugin from version 3.2.0 or below to the 4.x.x release.
This migration is required only for people who have integrated plugin version 3.2.0 or below. If your plugin version is greater than 3.2.0 you can ignore this step.
# Removing existing plugin
Remove MoEngage SDK Plugin
```javascript JavaScript theme={null}
cordova plugin remove moengagesdk
```
Remove MoEngage Push Extension, if added. Use the command `cordova plugin list` to check whether the plugin is installed or not.
```javascript JavaScript theme={null}
cordova plugin remove moengagepushextension
```
# Install the new plugin
Install the new MoEngage SDK plugin.
```javascript JavaScript theme={null}
cordova plugin add moengagesdk --variable APP_ID="[your_Workspace_id]"
```
### Variables
* **APP\_ID** = Workspace ID found under the settings page on the MoEngage dashboard.
# Initialize SDK(only for Android)
To initialize SDK create a class extending `Application` the class of Android and override `onCreate()`.\
Inside the `onCreate()` initialize the SDK as shown below.
```javascript JavaScript theme={null}
// this is the instance of the application class and "XXXXXXXXXXX" is the Workspace ID from the dashboard.
MoEngage moEngage =
new MoEngage.Builder(this, "XXXXXXXXXXX")
.build();
MoEngage.initialise(moEngage);
```
Make sure your application class is defined in the `AndroidManifest.xml` file as well.
# Setting up Push Notification(only Android)
MoEngage SDK supports both FCM and GCM, based on what you are using in your application install the appropriate plugin.\
The SDK no longer ships with Google's GCM or FCM library please ensure you have added the appropriate dependency in your app.
## FCM
```javascript JavaScript theme={null}
cordova plugin add cordova-moengage-fcm-dependency
```
## GCM
```javascript JavaScript theme={null}
cordova plugin add cordova-moengage-gcm-dependency
```
If MoEngage SDK is registering for push notification add the appropriate FCM/GCM listeners.
## FCM
```javascript JavaScript theme={null}
cordova plugin add cordova-moengage-fcm-listeners
```
## GCM
```javascript JavaScript theme={null}
cordova plugin add cordova-moengage-gcm-listeners
```
# Adding Push Related Meta Data
Refer to [Push Notification](/developer-guide/android-sdk/push/basic/push-configuration) documentation and add all the required meta-data for push notifications to work.
# Android Notification Runtime Permissions
Source: https://moengage.com/docs/developer-guide/cordova-sdk/push/basic/android-notification-runtime-permissions
Handle Android 13 notification runtime permissions in your Cordova app using the MoEngage SDK.
Android 13 (API level 33) and higher supports [runtime permission](https://developer.android.com/guide/topics/permissions/overview#runtime) for sending [non-exempt](https://developer.android.com/develop/ui/views/notifications/notification-permission#exemptions) (including Foreground Services (FGS)) notifications from an app [POST\_NOTIFICATIONS](https://developer.android.com/reference/android/Manifest.permission#POST_NOTIFICATIONS). This change helps users focus on the notifications that are most important to them.
Refer to the [official documentation](https://developer.android.com/develop/ui/views/notifications/notification-permission) for more details.
The below-mentioned APIs are supported starting MoEngage core Android SDK version **12.3.01**
When an application runs on Android 13 and wants to show notifications to the user, it must request the user's notification permission. You have two options: let MoEngage handle permissions for you or handle the notification permission with your code.
* MoEngage handles Notification permission.
* You just have to call a single line of code mentioned on this page.
* You maintain the notification permission logic.
* Notify MoEngage SDK if permission to push notifications is granted.
We recommend you let MoEngage handle push notification permissions.
## Notify SDK of permission result
Once the application requests the user for notification permission notify the SDK of the user response using the below API. *If you are letting MoEngage SDK handle the notification permissions, you should ignore this step.*
```javascript JavaScript theme={null}
var moe = MoECordova.init("YOUR_Workspace_ID");
//isGranted = true/false
moe.pushPermissionResponseAndroid(requestCount)
```
## Update the Permission request count(optional)
Once the application requests the user for notification permission, update the SDK of the request attempts.
**Why does the SDK require permission attempt count?**
SDK requires the attempt count to accurately track the number of times the permission request was attempted. If the user denies the permission request twice the application/SDK cannot request permission further i.e. if we request permission it would be automatically denied without the user seeing the request dialog. As an SDK we cannot be sure of the number of times the user has denied the permission we try to optimize the calls to request permission based on the attempt count.
```javascript JavaScript theme={null}
var moe = MoECordova.init("YOUR_Workspace_ID");
moe.updatePushPermissionRequestCountAndroid(requestCount)
```
## Setup Notification Channels
If the application has already taken notification permission from the user call the below API to set up Notification Channels for showing push notifications.
```javascript JavaScript theme={null}
var moe = MoECordova.init("YOUR_Workspace_ID");
moe.setupNotificationChannelsAndroid()
```
## Let MoEngage SDK handle Notification permission
MoEngage SDK provides helper APIs to show the permission request to the end-user or navigate the user to the settings screen for enabling notifications.
Use the below API to show the permission request dialog to the user.
When using the below API SDK automatically tracks the response, sets up the required notification channel, etc, mentioned above.
```javascript JavaScript theme={null}
var moe = MoECordova.init("YOUR_Workspace_ID");
moe.requestPushPermissionAndroid();
```
## Navigate to Notification Settings (situational/optional)
Use the below API to show navigate the user to the Notification Settings for the application on the device.
*Note*: Below Android 8(API level 26) the user is directed to the Application Info screen of your application.
```javascript JavaScript theme={null}
var moe = MoECordova.init("YOUR_Workspace_ID");
moe.navigateToSettingsAndroid();
```
# Android Push Configuration
Source: https://moengage.com/docs/developer-guide/cordova-sdk/push/basic/android-push-configuration
Configure Android push notifications in your Cordova app including FCM setup and push token handling.
## Basic Configuration
* **FCM Setup on MoEngage Dashboard** - FCM Authentication is the method to enable sending push notifications to your app installed on Android devices. Use the methods mentioned in [this article](/developer-guide/android-sdk/push/basic/fcm-authentication) to authenticate MoEngage to access Firebase services.
## Passing Push Token
```javascript JavaScript theme={null}
var moe = MoECordova.init(YOUR_Workspace_ID);
moe.passFcmToken()
```
## Passing Push Payload
```javascript JavaScript theme={null}
var moe = MoECordova.init(YOUR_Workspace_ID);
moe.passFcmPayload()
```
Passing payload and token from JavaScript is only supported for Firebase Messaging Service.
We highly recommend you to use the Android native APIs for passing the push payload to the MoEngage SDK instead of the Cordova/JavaScript APIs. Cordova Engine might not get initialized if the application is in the killed state which will lead to poor push reachability or delivery.
## Customizing Push notification
If required the application can customize the behavior of notifications by using Native Android code (Java/Kotlin). To learn more about the customization refer to the [Advanced Push Configuration](/developer-guide/android-sdk/push/advanced/callbacks-and-customisation) documentation.Instead of extending ***PushMessageListener*** as mentioned in the above document extend ***PluginPushCallback.***
Refer to the below documentation for Push Amp+, Push Templates, and Geofence.
* [Push Amplification](/developer-guide/android-sdk/push/optional/push-amplification)
* [Push Amp Plus](/developer-guide/android-sdk/push/optional/push-amp-plus/push-amp-plus-integration)
* [Push Templates](/developer-guide/android-sdk/push/optional/push-templates)
* [GeoFence Push](/developer-guide/android-sdk/push/optional/location-triggered)
# iOS Push Configuration
Source: https://moengage.com/docs/developer-guide/cordova-sdk/push/basic/ios-push-configuration-7xx
Configure iOS push notifications in your Cordova app including APNS certificates and push registration.
# Configuring Push Notifications in iOS
## APNS Certificate
To send push notifications in iOS, create an APNS certificate and upload it to the dashboard. Complete the following steps:
* [Create an APNS certificate](/developer-guide/ios-sdk/push/basic/apns-certificate-pem-file-legacy)
* [Convert the resultant certificate to .pem format](/developer-guide/ios-sdk/push/basic/apns-certificate-pem-file-legacy)
* [Upload .pem file to MoEngage Dashboard](/developer-guide/ios-sdk/push/basic/apns-certificate-pem-file-legacy)
## Adding Push Entitlement to your Project
Once the APNS Certificate is uploaded, enable Push Entitlement in the Xcode project. For that select your app target, then go to Capabilities. Here enable the Push Notifications capability for your app as shown below :
## Uninstall Tracking
We make use of silent pushes to track uninstalls. For tracking uninstalls of all the users, enable Remote Notification background mode in-app capabilities for the same as shown below :
## Push Registration
After this you will have to register for push notification by using **registerForPushNotification** method of the plugin as shown below :
```javascript JavaScript theme={null}
var moe = new MoECordova.init();
moe.registerForPushNotification();
```
Push token generated is received from `onPushTokenGenerated` callback
```javascript JavaScript theme={null}
moe.on('onPushTokenGenerated', function (payloadInfo) {
console.log('pushToken generated' + JSON.stringify(payloadInfo));
});
```
## Rich Push and Templates Support:
Please refer to the Native iOS SDK docs for supporting Rich Push(images/videos/audio in the notification) and Templates in the app:
* [Rich Push](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial#optional)
* [Push Templates](/developer-guide/ios-sdk/push/optional/push-templates)
# Push Callback
Source: https://moengage.com/docs/developer-guide/cordova-sdk/push/basic/push-callback
Set up JavaScript callbacks for push notification click events in the MoEngage Cordova SDK.
## Callback in JavaScript on Notification Click
To get a callback in javascript on notification click you need to register for a click listener as shown below.
Minimum Plugin version required : 3.0.0
```javascript JavaScript theme={null}
var moe = MoECordova.init(YOUR_Workspace_ID);
moe.on('onPushClick', function(payloadInfo) {
//add logic here
});
```
## Payload
NotificationPayload received in the callback **onPushClick** will have the following structure:
```auto JSON theme={null}
{
"accountMeta": {
"appId": ""
},
"data": {
"platform": "android/iOS",
"isDefaultAction": false,
"clickedAction": {
"type": "navigation/customAction",
"payload": {
"type": "screenName/deepLink/richLanding",
"value": "",
"kvPair": {
"key1": "value1",
"key2": "value2"
...
}
}
},
"payload": {}
}
}
```
**accountMeta.appId** - The Workspace ID of MoEngage.\
**data.platform** - Native platform from which callback is triggered. Possible values - **android**, **ios**\
**data.isDefaultAction** - This key is present only for the Android Platform. It's a boolean value indicating if the user clicked on the default content or not. true if the user clicks on the default content else false.\
**data.clickedAction** - Action to be performed on notification click.\
**data.clickedAction.type** - Type of click action. Possible values **navigation** and **customAction**. Currently, **customAction** is supported only on Android.\
**data.clickAction.payload** - Action payload for the clicked action.\
**data.clickedAction.payload.type** - Type of navigation action defined. Possible values **screenName**, **deepLink**, **richLanding**. Currently, in the case of iOS, richlanding and deep-link URL are processed internally by the SDK and not passed in this callback therefore possible value in case of iOS is only **screenName**.\
**data.clickAction.payload.value** - value entered for navigation action or custom payload.\
**data.clickAction.payload.kvPair** - Custom key-value pair entered on the MoEngage Platform.\
**data.payload** - Complete campaign payload.
### Android Payload
If the user clicks on the default content of the notification the key-value pair and campaign payload can be found inside the **payload** key. If the user clicks on the action button or a push template action the action payload would be found inside **clickedAction**.\
You can use the **isDefaultAction** key to check whether the user clicked on the default content or not and then parse the payload accordingly.
### iOS Payload
In the case of iOS, you would always receive the key-value pairs with respect to clicked action in **clickedAction** key. Refer to this [link](/developer-guide/ios-sdk/push/advanced/custom-notification-handling#notification-actions) for knowing the iOS notification payload structure.
# Location Triggered
Source: https://moengage.com/docs/developer-guide/cordova-sdk/push/optional/location-triggered
Add geofence-based location-triggered push notifications to your Cordova app using MoEngage.
# Installation
## Adding Geofence Plugin
Add **cordova-moengage-geofence** plugin to Cordova project as shown below :
```auto Shell theme={null}
$ cordova plugin add cordova-moengage-geofence
```
## Android Installation
## Install using BOM
Integration using BOM is the recommended way of integration; refer to the [Install Using BOM ](/developer-guide/android-sdk/sdk-integration/basic-integration/Install-Using-BOM)document. Once you have configured the BOM add the dependency in the *app/build.gradle* file as shown below:
```json build.gradle wrap theme={null}
dependencies {
...
implementation("com.moengage:geofence")
}
```
Once the BOM is configured, include the specific MoEngage modules required for the application. \
Note: Version numbers are not required for these dependencies; the BOM automatically manages them.
## Manual Installation

Once you install the Flutter Plugin add MoEngage's native Android SDK dependency to the Android project of your application.\
Navigate to **android/app/build.gradle**. Add the MoEngage Android SDK's dependency in the **dependencies** block.
```json build.gradle theme={null}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation("com.moengage:geofence:$sdkVersion")
}
```
where **\$sdkVersion**should be replaced by the latest version of the MoEngage Geofence SDK
## iOS
In the case of iOS, the native dependency is part of the Geofence Cordova SDK itself, so there is no need to include any additional dependency for supporting Geofence.
## Configuration
### Start Geofence Monitoring
After integrating the geofence package call **startGeofenceMonitoring()** method to initiate the geofence module, this will fetch the geofences around the current location of the user. Please take a look at the [iOS doc](/developer-guide/ios-sdk/push/optional/location-triggered) and [Android doc](/developer-guide/android-sdk/push/optional/location-triggered) for more information on Geofence. By default, the geofence feature is not enabled. You need to call the \*\*startGeofenceMonitoring()\*\*to receive location-triggered push messages.
```auto Javascript theme={null}
MoEGeofence.startGeofenceMonitoring("YOUR_Workspace_ID");
```
### Stop Geofence Monitoring
If you want to stop the geofence monitoring or feature use the **stopGeofenceMonitoring()** API. This API will remove the existing geofences.
```javascript Javascript wrap theme={null}
MoEGeofence.stopGeofenceMonitoring("YOUR_Workspace_ID");
```
# Limitations
Source: https://moengage.com/docs/developer-guide/cordova-sdk/sdk-integration/limitations
Review unsupported features and native integration requirements when using the MoEngage Cordova plugin.
Compared to the Native Android/iOS SDKs there are a certain set of features we either do not support or it requires native Android/iOS implementation when using our Cordova plugin.
# Features not supported
* Nudges
* Action Buttons in iOS Notifications
# Features that are supported but requires Native Integration
* Inbox Module
* Cards Module
# Android SDK Initialization
Source: https://moengage.com/docs/developer-guide/cordova-sdk/sdk-integration/sdk-initialization/android-sdk-initialization
Initialize the MoEngage SDK in your Android application's onCreate method for Cordova integration.
# Initialization
Get the Workspace ID from the **Settings Page Dashboard --> Settings --> App --> General** on the MoEngage dashboard and initialize the MoEngage SDK in the **Application** class's **onCreate()**
It is recommended that you initialize the SDK on the main thread inside **onCreate()** and not create a worker thread and initialize the SDK on that thread.
```Java Java theme={null}
import com.moengage.cordova.MoEInitializer;
import com.moengage.core.MoEngage;
import com.moengage.core.DataCenter;
// this is the instance of the application class and "YOUR_Workspace_ID" is the Workspace ID from the dashboard.
MoEngage.Builder moEngage = new MoEngage.Builder(this,"YOUR_Workspace_ID”, DataCenter.DATA_CENTER_X);
MoEInitializer.initialiseDefaultInstance(this, moEngage);
```
Following details of the different data centers you need to set based on the dashboard hosts
| Data Center | Dashboard host |
| -------------------------- | ------------------------- |
| DataCenter.DATA\_CENTER\_1 | dashboard-01.moengage.com |
| DataCenter.DATA\_CENTER\_2 | dashboard-02.moengage.com |
| DataCenter.DATA\_CENTER\_3 | dashboard-03.moengage.com |
| DataCenter.DATA\_CENTER\_4 | dashboard-04.moengage.com |
| DataCenter.DATA\_CENTER\_5 | dashboard-05.moengage.com |
In case your application does not have an Application class yet navigate to java source code inside the android platform folder and add the Application class file.
Make sure your application class is defined in the **AndroidManifest.xml** file as well.\
Refer to the [API reference doc](https://moengage.github.io/android-api-reference/core/com.moengage.core/-mo-engage/-builder/index.html) for a detailed list of possible configurations.
# Exclude MoEngage Storage File from Auto-Backup
This is a mandatory integration step and is very essential to prevent your data from getting corrupted. Android's auto back-up service periodically backs up Shared Preference files, Database files, etc, more details [here](https://developer.android.com/guide/topics/data/autobackup). This backup results in MoEngage SDK's identifiers being backed up and restored after re-install.This restoration of the identifier results in your data being corrupted and users not being reachable via push notifications.
To ensure data is not corrupted after a backup is restored, opt out of MoEngage SDK's storage files. Refer to [Exclude MoEngage Storage File from the Auto-Backup](/developer-guide/android-sdk/sdk-integration/basic-integration/exclude-mo-engage-storage-file-from-auto-backup) section of the documentation to learn more about which files to exclude.
# Framework Initialization
Source: https://moengage.com/docs/developer-guide/cordova-sdk/sdk-integration/sdk-initialization/framework-initialization
Initialize the MoEngage Cordova plugin in your application using the MoECordova.init() method.
# Initialise Cordova Component
Initialise MoEngage plugin in the ***index.js*** of your application by calling the \*\*\*MoECordova.init()\*\*\*in the ***onDeviceReady()***.
```javascript JavaScript theme={null}
var moe = MoECordova.init("YOUR_Workspace_ID");
```
Refer to the following for platform-specific initialization:
* [Android](/developer-guide/cordova-sdk/sdk-integration/sdk-initialization/android-sdk-initialization)
* [iOS](/developer-guide/cordova-sdk/sdk-integration/sdk-initialization/ios-sdk-initialization)
# iOS SDK Initialization
Source: https://moengage.com/docs/developer-guide/cordova-sdk/sdk-integration/sdk-initialization/ios-sdk-initialization
Initialize the MoEngage Cordova SDK in your iOS application using code-based initialization.
## Code Initialization
From plugin version 8.0.0 we support initialization only via code. In the version 8.0.0 we have removed the initialization of SDK support via info.plist which was supported in 7.1.1 and above.
* Call any one of the below-given initialization methods in **application:didFinishLaunchingWithOptions:** method. The method accepts the **MoEngageSDKConfig** instance as its parameter. Refer [doc](/developer-guide/ios-sdk/sdk-integration/basic/sdk-initialization) for more info on all the properties which can be configured using **MoEngageSDKConfig**.
```objective-c Objective-C wrap theme={null}
/// @param sdkConfig MoEngageSDKConfig instance for SDK configuration
/// @param launchOptions Launch Options dictionary
- (void)initializeDefaultSDKConfig:(MoEngageSDKConfig*)sdkConfig andLaunchOptions:(NSDictionary*)launchOptions;
/// @param sdkConfig MoEngageSDKConfig instance for SDK configuration
/// @param sdkState Enum indicating if SDK is Enabled/Disabled
/// @param launchOptions Launch Options dictionary
- (void)initializeDefaultSDKConfig:(MoEngageSDKConfig*)sdkConfig withMoEngageSDKState:(MoEngageSDKState)sdkState andLaunchOptions:(NSDictionary*)launchOptions;
```
* Sample code to initialise from **application:didFinishLaunchingWithOptions:** method:
```objectivec Objective-C wrap theme={null}
#import "AppDelegate.h"
#import "MainViewController.h"
// Make sure to import "AppDelegate+MoEngage.h"
#import "AppDelegate+MoEngage.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
self.viewController = [[MainViewController alloc] init];
MoEngageSDKConfig *sdkConfig = [[MoEngageSDKConfig alloc] initWithAppID: @"YOUR Workspace ID"];
sdkConfig.moeDataCenter = DATA_CENTER_01; // Possible Values DATA_CENTER_01/DATA_CENTER_02/ DATA_CENTER_03
sdkConfig.appGroupID = "App Group ID";
// ---
// Update other Parameters of SDK Config
[self initializeDefaultSDKConfig:sdkConfig andLaunchOptions:launchOptions];
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
@end
```
# Data Center
In case your app wants to redirect data to a specific zone due to any data regulation policy please configure the zone in the MOSDKConfig object.
For more information on Data Center, refer [here](/developer-guide/ios-sdk/sdk-integration/basic/data-center).
# Android SDK Installation
Source: https://moengage.com/docs/developer-guide/cordova-sdk/sdk-integration/sdk-installation/android-sdk-installation
Add the MoEngage Android SDK dependency to your Cordova project using BOM or manual configuration.
# Adding Dependency
To add MoEngage's Android SDK to your application, \/platforms/android/app` and create...` a file with the name **build-extras.gradle**. If you already have this file in your project, you need not create another one.
## Option 1: Using BOM (Recommended)

Use the Bill of Materials (BOM) to automatically manage compatible versions of the SDK modules.
```auto build.gradle theme={null}
dependencies {
...
// Import the MoEngage BOM
implementation(platform("com.moengage:android-bom:BOM_VERSION"))
// Add optional modules as needed
implementation("com.moengage:inapp")
}
```
Replace \*\*\`** with the latest BOM version.`. For more info on integration using BOM, refer [here](/developer-guide/android-sdk/sdk-integration/basic-integration/Install-Using-BOM).
## Option 2: Manual Integration
Once the file is created, add the MoEngage SDK dependency to it.
```auto Groovy theme={null}
// adding the repositories block is optional. You can choose not to add this block if you have already added these repositories to your project.
repositories {
google()
mavenCentral()
}
dependencies {
implementation("androidx.core:core:1.6.0")
implementation("androidx.appcompat:appcompat:1.3.1")
implementation("androidx.lifecycle:lifecycle-process:2.7.0")
implementation("com.moengage:moe-android-sdk:13.02.00")
}
```
Replace **\$sdkVersion** with the appropriate SDK version
You can add the firebase messaging dependency also to this file itself if your file does not already have firebase messaging added.
# Framework Dependency
Source: https://moengage.com/docs/developer-guide/cordova-sdk/sdk-integration/sdk-installation/framework-dependency
Add the cordova-moengage-core plugin to your Cordova project and configure platform settings.
# Adding MoEngage Plugin
Add the **cordova-moengage-core** plugin to the Cordova project as shown below :
```Shell Shell theme={null}
$ cordova plugin add cordova-moengage-core
```
After installing the plugin, use the following platform-specific configuration.
* [Android SDK Installation](/developer-guide/cordova-sdk/sdk-integration/sdk-installation/android-sdk-installation)
* [iOS SDK Installation](/developer-guide/cordova-sdk/sdk-integration/sdk-installation/ios-installation)
# iOS Installation
Source: https://moengage.com/docs/developer-guide/cordova-sdk/sdk-integration/sdk-installation/ios-installation
Install the MoEngage iOS SDK in your Cordova project using CocoaPods dependency management.
# SDK Installation
## Installation using CocoaPods (Plugin Version 5.0.0 and above)
Starting from **cordova-ios** version 4.3.0 and **cordova-cli** version 6.4.0, CocoaPod support is provided to bundle any iOS framework. Therefore, we have updated our plugin too to support this from version 5.0.0.
Cocoapods is a dependency manager for iOS projects and makes integration easier. If you don't have cocoapods installed, you can do it by executing the following command in your terminal:
```Ruby Ruby theme={null}
sudo gem install cocoapods
```
Here, after adding the plugin just go to the **ios** folder in **platforms** and run **pod install** command to integrate our **MoEngagePluginBase**:
```Ruby Ruby theme={null}
pod repo update
pod install
```
### Add script to remove Unwanted Architectures
**Do this if not already done:** Select App Target and go to Build Phase and add a Run Script step to your build steps, set it to use **/bin/sh** and enter the following script:
```Shell Shell theme={null}
APP_PATH="${TARGET_BUILD_DIR}/${WRAPPER_NAME}"
# This script loops through the frameworks embedded in the application and
# removes unused architectures.
find "$APP_PATH" -name '*.framework' -type d | while read -r FRAMEWORK
do
FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable)
FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"
echo "Executable is $FRAMEWORK_EXECUTABLE_PATH"
EXTRACTED_ARCHS=()
for ARCH in $ARCHS
do
echo "Extracting $ARCH from $FRAMEWORK_EXECUTABLE_NAME"
lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH"
EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH")
done
echo "Merging extracted architectures: ${ARCHS}"
lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "${EXTRACTED_ARCHS[@]}"
rm "${EXTRACTED_ARCHS[@]}"
echo "Replacing original executable with thinned version"
rm "$FRAMEWORK_EXECUTABLE_PATH"
mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"
done
```
This script is for removing unsupported architectures while exporting the build OR submitting app to the app store.
**For Plugin version 3.2.0 and below:**
Open your project in Xcode, select your project. Go to **Build Settings -> Linker -> Other Linker Flags** and add **-ObjC** flag
# Magento
Source: https://moengage.com/docs/developer-guide/ecommerce-platforms/magento/magento
Integrate MoEngage Web SDK into your Magento store using Google Tag Manager or direct integration.
# Overview
Magento is an open source ecommerce platform, that more than 150K online stores use. This document covers the multiple ways and the steps involved in integrating MoEngage Web SDK into your Magento store.
MoEngage / Magento integration can be done in two ways:
* Via Google Tag Manager
* Direct Integration
## Using Google Tag Manager
* Add Google Tag Manager (GTM) to your Magento store. Refer to this [Magento documentation](https://docs.magento.com/user-guide/v2.3/marketing/google-enhanced-ecommerce.html) for detailed steps.
* Complete the GTM / MoEngage integration by following the integration steps [here](https://partners.moengage.com/hc/en-us/articles/18795331766676).
* You can track any user event and/or User properties from your store to MoEngage via GTM.
This integration allows you to further integrate with the following MoEngage channels:
| Channel | Supported? |
| ------------------- | ---------- |
| On-site messaging | Yes |
| Web personalization | Yes |
| WebPush | No |
## Direct Integration with Magento
Please note that Magento versions below 2.2.0 are not supported.
* Install and set up your Magento store. Refer to the Magento [documentation](https://experienceleague.adobe.com/en/docs/commerce-operations/installation-guide/composer) for help.
* Login into your store's admin panel, and Navigate to Admin Panel > Content > Configuration
* Please choose the store view you want the head tag to be changed on or select *Global* to change it on every store view.\\
* Find the **HTML Head** section and add the [SDK script](/developer-guide/web-sdk/web-sdk-integration/basic-integration/web-sdk-integration) code in the **Scripts and Style Sheets** field.\\
* Please save the configuration and flush the cache.
To overcome any potential customer data privacy issues, please whitelist the MoEngage WebSDK URLs. Follow their official [documentation](https://developer.adobe.com/commerce/php/development/security/content-security-policies/#configure-a-modules-csp-mode) to add the rules. [Here](/developer-guide/web-sdk/web-sdk-integration/basic-integration/web-sdk-integration) is the list of URL that you should whitelist.
### Data Tracking
In Magento, to track events or user attributes on the existing elements, you would need to edit the default HTML. For example, to track an event on click of "Add to Cart" button:
Add a script in your phtml file where the Add to Cart button is defined. You can usually find the add to cart button in catalog/product/view/addtocart.phtml file.
```php Code theme={null}
```
This integration allows you to use the MoEngage for:
| Channel name | Supported? |
| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| On-site messaging | Yes |
| Web personalization | Yes ([integration](/developer-guide/personalize-sdk/sdk-integration/web-personalization-v2) script should be added) |
| User Event and User property tracking | Yes |
| WebPush | Yes |
For Webpush support service worker file can be added to the root of the project; usually inside /pub folder. This requires changes in the .htaccess file. If this is not possible for any reason, then please put the serviceworker inside the media folder or any custom folder inside the /pub directory.
If the service worker file is not placed in the root directory, then swPath and swScope can be added while initializing the SDK.
# Events and User Data Tracking
Source: https://moengage.com/docs/developer-guide/ecommerce-platforms/shopify/events-and-user-data-tracking
Learn about product, cart, checkout, and order events tracked with the MoEngage Shopify integration.
Events and User Data tracking helps you send user and event data to MoEngage. MoEngage can then track these events and enable you to send personalized communication to users upon the occurrence of these events.
# Tracked Events
The following events can be tracked by MoEngage if enabled on your Shopify app during integration.
| Event Type | Event Name | Description |
| ---------------- | ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Product Event | Product Viewed | This event is tracked when a user views a product. You can use this event to show personalized recommendations of similar products to the user or if the user happens to view a product that is out of stock, you can notify them when the item is back in stock, and so on. |
| Product Event | Product Searched | This is event is tracked when a product is searched. You can use this event to show personalized recommendations based on the user's search preferences. For example, if a user were to search for a cosmetic product such as toner, you could show them recommendations for toners or allied skin care products. |
| Cart Event | Shopify - Add To Cart and Shopify -Update Cart | This event is tracked when a product is added to cart, or the cart is updated. This can be used to track cart abandonment, and you can engage with customers who've added items to their cart but not acted on it. |
| Cart Event | Removed from Cart | This event is tracked when a product is removed from cart. You can nudge users towards a purchase with recommendations for similar items or engage with them based on their past purchase history, and so on. |
| User Login Event | Customer Registered | This event is tracked when a customer registers with the Shopify store. This event can be used to show welcome messages to the user and used for onboarding communication. |
| User Login Event | Customer Logged In | This event is tracked when a customer logs in to the Shopify store. This event can be used to show relevant offers and nudge customers to act on items in their cart or nudge them towards subscribing to newsletters, and so on. |
| User Login Event | Customer Logged Out | Tracked when a customer logs out of the Shopify store. |
| Checkout Event | Shopify - Checkout Started | This event is tracked when the customer checks out items in their cart. |
| Checkout Event | Shopify - Checkout updated | This event is tracked when the customer updates their cart during checkout. |
| Order Event | Shopify - Order placed | This event is tracked when a customer completes the purchase. This event can be used to send order summary communication, show subscription-related messages, and nudge users to sign up for loyalty programs. |
| Order Event | Shopify - Order fulfilled | This event is tracked when an order is [fulfilled](https://help.shopify.com/en/manual/checkout-settings/order-processing) and is ready to be shipped to the customer. |
| Order Event | Shopify - Order partially fulfilled | This event is tracked when an order is fulfilled but partially. This is raised when some items of the orders are fulfilled and some are not. |
| Order Event | Shopify - Order cancelled | This event is tracked when an order is canceled. |
| Order Event | Shopify - Refund created | This event is tracked when a refund has been created for the customer, either due to cancellation or complaints. These events can be used to send personalized communication to the users to ensure that they do not churn.\\ |
You can not use "moe\_" as a prefix while naming events, event attributes, or user attributes. It is a system prefix and using it might result in periodic blacklisting without prior communication.
## Types of Events
Events are generally generated from two ends:
1. **Webhook** - These events are generated at the Shopify end and sent to MoEngage using the Webhook.
2. **Web SDK** - These events are generated by MoEngage's Web SDK based on user behavior on the website. For more information, refer to Web SDK events.
The sample payloads for both these kinds of events are shared below.
## Sample Payloads for Webhook Events
```json Shopify - Update Cart theme={null}
{
"Event Received Time": "17th July 2023, 03:25:55 pm",
“Product Title”: “Sample Product”,
"Updated At": "17th July 2023, 03:26:15 pm",
"Variation ID": "123456",
"Currency": "USD",
"cart_token": "c1-fcdd3207bee3eef9f98abefaf2ca...",
"Product ID": "845236547",
"Price": 555.99,
“Source”: “Shopify”,
"Vendor Name": "845236547",
"Created At": "17th July 2023, 03:25:55 pm",
"Quantity": 2
}
```
```json Removed From Cart theme={null}
{
"Event Received Time": "17th July 2023, 03:25:55 pm",
“Product Title”: “Sample Product”,
"Updated At": "17th July 2023, 03:26:15 pm",
"Variation ID": "123456",
"Currency": "USD",
"Product ID": "845236547",
"Price": 555.99,
“Source”: “Shopify”,
"Vendor Name": "845236547",
"Created At": "17th July 2023, 03:25:55 pm",
"Quantity": 2
}
```
```json Shopify- Checkout Started theme={null}
{
"Event Received Time": "17th July 2023, 03:25:55 pm",
“Product Title”: “Sample Product”,
"Updated At": "17th July 2023, 03:26:15 pm",
"ID": "3cce6aeedf786679ac03e043729fd...",
"Variation ID": "0:123456", "Currency": "USD",
"Checkout ID": "3cce6aeedf786679ac03e043729fd...",
“Source Name”: “web”,
"cart_token": "c1-fcdd3207bee3eef9f98abefaf2ca...",
"Checkout URL": "https://publicstorenewdb.myshopify.com/products/the-complete-snowboard",
"Shopify Customer Id": 36838667059499,
"Total Price": 327,
"Price": 0:300.00, "Subtotal Price": 300.00,
“Source”: “Shopify”,
"Vendor Name": "845236547",
"Created At": "17th July 2023, 03:25:55 pm",
"Quantity": 2,
"Product ID": "845236547"
}
```
```json Shopify- Checkout Updated theme={null}
{
"Event Received Time": "17th July 2023, 03:25:55 pm",
“Product Title”: “0:Sample Product01”,
"Updated At": "17th July 2023, 03:26:15 pm",
"ID": "3cce6aeedf786679ac03e043729fd...",
"Variation ID": "0:123456",
"Currency": "USD",
"Checkout ID": "3cce6aeedf786679ac03e043729fd...",
"Source Name”: “web”,
"cart_token": "c1-fcdd3207bee3eef9f98abefaf2ca...",
"Checkout URL": "https://publicstorenewdb.myshopify.com/products/the-complete-snowboard",
"Shopify Customer Id": 36838667059499,
"Total Price": 327,
"Price": [0:300.00],
"Subtotal Price": 300.00,
“Source”: “Shopify”,
"Vendor Name": "845236547",
"Created At": "17th July 2023, 03:25:55 pm",
"Quantity": [0:1],
"Product ID": [0:845236547]
}
```
```json Updated after Shipment theme={null}
{
"Event Received Time": "17th July 2023, 03:25:55 pm",
"Shipping Address Country": "US",
"Billing Address City": "New York",
“Product Title”: “0:Sample Product01”,
"cart_token": "c1-fcdd3207bee3eef9f98abefaf2ca...",
"ID": "3cce6aeedf786679ac03e043729fd...",
"Checkout ID": "3cce6aeedf786679ac03e043729fd...",
"First Name": "John",
"Currency": "USD",
"Shipping Address Country Code": "US",
"Billing Address Country Code": "US",
"Updated At": "",
“Source Name”: “web”,
"first_name": "John",
"Shipping Address Province": "New York",
"Shipping Address Province": "NY",
"Checkout URL": "https://publicstorenewdb.myshopify.com/products/the-complete-snowboard",
"last_name": "Doe",
"Shopify Customer Id": 36838667059499,
"Total Price": 327,
"Price": 0:300.00,
"Shipping Address Zip": "10009",
"Subtotal Price": 300.00,
“Source”: “Shopify”,
"Shipping Address Province Code": "NY",
"Vendor Name": "845236547",
"Billing Address Country": "US",
"Created At": "17th July 2023, 03:25:55 pm",
"Variation ID": "0:123456",
"Quantity": [0:1],
"Product ID": [0:845236547]
}
```
```json Shopify - Order Placed theme={null}
{
"Event Received Time": "17th July 2023, 03:25:55 pm",
"Current Total Discounts" 0.00,
“Product Title”: “0:Sample Product01”,
"cart_token": "c1-fcdd3207bee3eef9f98abefaf2ca...",
"ID": "3cce6aeedf786679ac03e043729fd...",
"Name": "#1008",
"Order Status URL": "",
"Total Quantity": 1,
"Billing Address Country Code": "US",
"Billing Address Zip": 10009,
"Order ID": 12334534345,
"Currency": "USD",
"Total Price": 354,
"Checkout ID": "3cce6aeedf786679ac03e043729fd...",
"First Name": "John",
"Shipping Address Country Code": "US",
"Shipping Address City": "New York",
"Billing Address City": "NY",
"Order Number": 1008,
"Order Count": 1,
“Source Name”: “web”,
"first_name": "John",
"Shipping Address Country": "US",
"Current Total Price": 354.00,
"Shipping Address Province": "New York",
"Billing Address Province": "NY",
"last_name": "Doe",
"Last Name": "Doe",
"Price": [0:300.00],
"Shipping Address Zip": "10009",
"Current Total Tax": 54.00,
"Subtotal Price": 300.00,
“Source”: “Shopify”,
"Shipping Address Province Code": "NY",
"Vendor Name": "845236547",
"Payment Gateway Names": "manual",
"Billing Address Country": "US",
"Created At": "17th July 2023, 03:25:55 pm",
"Financial_status": "paid",
"Variation ID": "0:123456", "Quantity": [0:1],
"Product ID": [0:845236547]
}
```
```json Shopify - Order Partially Fulfiled theme={null}
{
"Event Received Time": "17th July 2023, 03:25:55 pm",
"product_title": [0:"product 2", 1:"product 2"],
"Updated At": "17th July 2023, 03:25:57 pm",
"product_id": [0:234234324, 1: 97897897897],
"variation_id": [0:23423423423, 1:23423423444],
"Total Spent": 5687,
"Currency": "USD",
"Total Price": 354,
"Checkout ID": "3cce6aeedf786679ac03e043729fd...",
"tracking_company": "1",
"vendor_name": [0:"ShopiWeb", 1:"ShopifyWeb"],
"OrderID": 34343455,
"item_fulfilment_status": [0:"partial", 1:"fulfilled"],
"Quantity": [0:4, 1:3],
"item_count": 2,
"order_fulfilment_status": "partial",
"Subtotal Price": 10500,
"Order Status URL": "https://yourshopifystore...",
"price": [0:1500.00, 1:1500.00],
"variation_title": [0:"product 2 - black", 1:"product 2 - red"],
"Financial status": "refunded",
"Created At": "17th July 2023, 03:25:55 pm"
}
```
```json Shopify - Order Fulfiled theme={null}
{
"Event Received Time": "17th July 2023, 03:25:55 pm",
"product_title": [0:"product 2"],
"cart_token": "c1-fcdd3207bee3eef9f98abefaf2ca...",
"product_id": [0:234234324],
"variation_id": [0:23423423423],
"Total Spent": 5687,
"Currency": "USD",
"Total Price": 354,
"Checkout ID": "3cce6aeedf786679ac03e043729fd...",
"Source Name": "web",
"vendor_name": [0:"ShopiWeb"],
"item_fulfilment_status": [0:"fulfilled"],
"Updated At": "17th July 2023, 03:25:58 pm",
"OrderID": 34343455,
"Quantity": [0:1],
"item_count": 1,
"order_fulfilment_status": "fulfilled",
"Subtotal Price": 300,
"Order Status URL": "https://yourshopifystore...",
"price": [0:1500.00, 1:1500.00],
"variation_title": [0:"product 2 - black"],
"Financial status": "paid",
"Created At": "17th July 2023, 03:25:55 pm"
}
```
```json Shopify- Order Cancelled theme={null}
{
"Event Received Time": "17th July 2023, 03:25:55 pm",
"product_title": [0:"product 2", 1:"product 2"],
"cart_token": "c1-fcdd3207bee3eef9f98abefaf2ca...",
"product_id": [0:234234324, 0:23423423446],
"variation_id": [0:23423423423, 0:84353458],
"Total Spent": 5687,
"Currency": "USD",
"Total Price": 354,
"Checkout ID": "3cce6aeedf786679ac03e043729fd...",
"cancelled at": "17th July 2023, 03:25:55 pm",
"Source Name": "web",
"vendor_name": [0:"ShopiWeb", 1:"ShopiWeb"],
"item_fulfilment_status": [0:"fulfilled"],
"Updated At": "17th July 2023, 03:25:58 pm",
"OrderID": 34343455,
"Quantity": [0:1, 1:2],
"item_count": 2,
"order_fulfilment_status": [0: , 1:],
"Subtotal Price": 300,
"Order Status URL": "https://yourshopifystore...",
"price": [0:1500.00, 1:1500.00],
"variation_title": [0:"product 2 - black", 1:"product 2 - red"],
"Financial status": "refunded",
"Created At": "17th July 2023, 03:25:55 pm"
}
```
```json Shopify - Refund Created theme={null}
{
"Event Received Time": "17th July 2023, 03:25:55 pm",
"Variation Title": [0:"Product 2 Black"]
"Product Title": [0:"Product 2"],
"Updated At": "17th July 2023, 03:25:59 pm",
"OrderID": 34343455,
"Variation ID" [0:234234234],
"Currency": "USD",
"email": "John.doe@example.com",
"user_id": 1545645465,
"Refund Created At": 17th July 2023, 03:25:55 pm",
"Source": "Shopify",
"Vendor Name": [0:"ShopifyWeb"],
"Created At": "17th July 2023, 03:25:55 pm",
"price": [0:500.00],
"Quantity": [0:1],
"Product ID": [0:8923423]
}
```
## Sample Payloads for Web SDK Events
```json Product Viewed theme={null}
{
"Event Received Time": "17th July 2023, 03:25:55 pm",
“Email”: “john.doe@example.com”,
“Product Title”: “Sample Product”,
"Variation ID": "123456",
"Total Variants": 3,
"Product Handle": "Product 1",
"Available": true,
"Currency": "USD",
"Product ID": "845236547",
"Price": 555.99,
“Source”: “Shopify”,
"Quantity": 3,
"First Session": true,
"URL": "URL of the Viewed Product Here"
}
```
```json Product Searched theme={null}
{
"Event Received Time": "17th July 2023, 03:25:55 pm",
"Variation ID": "123456",
"Currency": "USD",
"URL": "Search URL",
"Search String": "Sneakers Green",
“Source”: “Shopify”,
"First Session": true
}
```
```json Add to Cart theme={null}
{
"Event Received Time": "17th July 2023, 03:25:55 pm",
“Email”: “john.doe@example.com”,
“Product Title”: “Sample Product”,
"Variation ID": "123456",
"Variation Title": "Sea Green",
"Total Variants": 3,
"Product Handle": "Product 1",
"Available": true,
"Currency": "USD",
"Product ID": "845236547",
"Vendor Name": "845236547",
"Price": 555.99,
“Source”: “Shopify”,
"Quantity": 3,
"First Session": true,
"Product URL": "/product/type?type=Sneakers"
}
```
```json Update Cart theme={null}
{
"Event Received Time": "17th July 2023, 03:25:55 pm",
“Email”: “john.doe@example.com”,
“Product Title”: “Sample Product”,
"Variation ID": "123456",
"Variation Title": "Sea Green",
"Total Variants": 3,
"Product Handle": "Product 1",
"Available": true,
"Currency": "USD",
"Product ID": "845236547",
"Vendor Name": "845236547",
"Price": 555.99,
“Source”: “Shopify”,
"Quantity": 3,
"First Session": true,
"Product URL": "/product/type?type=Sneakers"
}
```
```json Removed From Cart theme={null}
{
"Event Received Time": "17th July 2023, 03:25:55 pm",
“Email”: “john.doe@example.com”,
“Product Title”: “Sample Product”,
"Variation ID": "123456",
"Currency": "USD",
"Product ID": "845236547",
"Price": 555.99,
“Source”: “Shopify”,
"Quantity": 3
}
```
```json Customer Registered theme={null}
{
"Event Received Time": "17th July 2023, 03:25:55 pm",
“Email”: “john.doe@example.com”,
“Source”: “Shopify”,
“First Session”: true,
“URL”: “https://publicstorenewdb.myshopify.com/”
}
```
```json Customer Logged In theme={null}
{
"Event Received Time": "17th July 2023, 03:25:55 pm",
“Email”: “john.doe@example.com”,
“Phone”: “”,
“FirstName”: “John”,
“LastName”: “Doe",
“Customer ID”: 7385786908975,
“Source”: “Shopify”,
“First Session”: true,
“URL”: “https://publicstorenewdb.myshopify.com/account”
}
```
```json Checkout Started theme={null}
{
"Event Received Time": "17th July 2023, 03:25:55 pm",
“Email”: “john.doe@example.com”,
“currency”: “USD”,
“Total Price”: 699.95,
“Product Prices”: [
699.95
],
“Product IDs”: [
“8869819679023"
],
“Product Quantities”: [
1
],
“Product Titles”: [
“The Complete Snowboard - Ice”
],
“Variation IDs”: [
“46822634324271”
],
“Vendor Names”: [
“Snowboard Vendor”
],
“Source”: “Shopify”,
“First Session”: true,
“URL”: “https://publicstorenewdb.myshopify.com/products/the-complete-snowboard”
}
```
## Tracked User Properties
The following user properties (information pertaining to the user) can be tracked by MoEngage if enabled on your Shopify app during integration.
| Attribute Name | Description |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| First Name | First Name of the user. |
| LastName | Last Name of the user. |
| Mobile | Mobile Number of the user. |
| Email | Email address of the user. |
| Tags | Tags used for the user by Shopify. |
| Accepts Marketing | Denotes whether the user prefers to receive marketing communication. This is tracked by Shopify. |
| Orders Count | Number of orders placed by the user. |
| Shopify Id | Id of the user in Shopify. |
| Shopify LTV | Life Time Value of the user. This is the total sum of revenue present in the App Conversion Goal event performed by a user. LTV is updated every time the app conversion goal event is executed by the user. |
| Shipping Mobile Number | The mobile number of the user to whom the item will be shipped. |
To track events and user data on the MoEngage Shopify app:
1. Navigate to the *Configuration* tab in your Shopify app.
2. Select user events and properties that you want to track or be tracked.
3. Click *Save configuration*.
If you have any questions about the working of your Shopify integration read our [FAQs](/developer-guide/ecommerce-platforms/shopify/faqs)
# FAQs
Source: https://moengage.com/docs/developer-guide/ecommerce-platforms/shopify/faqs
Find answers to frequently asked questions about the MoEngage Shopify integration and user identity.
Here are the most frequently asked questions about MoEngage integration for Shopify.
# Installation
* APP ID and API Key authentication not working?
* Usually, it takes 10 mins for the newly generated keys to take effect so please retry authentication for the Shopify app after 10 mins of generation of the MoEngage API key.
# User Identity
* How is the Unique user identity setting used?
* The unique user identifier setting is used to determine, out of mobile number or email, which identifier will be used as the unique user identifier to provide the single view of the end-user on the MoEngage dashboard. So if the same user visits your store from multiple devices we will be able to merge their activity under the same profile if the same unique identifier is set on all their devices/browsers.
* How to decide which identifier to use as the unique customer identifier?
* By default, Shopify uses email to identify a user uniquely.
* The choice of the unique identifier depends on your business use case i.e. what login identifier you are using across other systems or whether most of your users would want to use email or mobile number as the login identifier. If you are already using MoEngage, please select the same unique identifier as you are currently using. If you are currently using a unique identifier that is different from the available settings, please reach out to the support team or your account executive for help.
* Can I use anything other than a Mobile number or Email as the unique customer identifier?
* No, currently the setting is limited to the mobile number or email.
* Can I use both Email and Mobile number, as the unique customer identifier?
* No, currently you would have to select either of the two to uniquely identify a user. Multiple unique identifiers for a user will be available soon where Email and Mobile number, along with any of the other user attributes can be used to uniquely identify a user.
* What are the steps to set the mobile number as the unique identifier?
* Please make the following store change before using the mobile number as UID
* The option to get the User's mobile number is not available by default in the checkout flow, please make sure to enable this from your store’s checkout settings.
* The user signup/login flow also does not have the option to get the user’s mobile number, please use custom login and user signup to get the user’s mobile number as part of these flows to successfully use the Mobile number as the unique identifier.
* If these changes are not done, you will see a lot of anonymous profiles with the same user properties on MoEngage.
* Can I use a shipping mobile number as the unique identifier?
No. Shipping mobile numbers should not be used as the unique identifier for the end customers. It might lead to data corruption because the same user can place multiple orders with different shipping mobile numbers which will distort the single view of the customer on the MoEngage dashboard and would lead to sending the wrong communication to the users. This will also lead to data discrepancy of events data on MoEngage in comparison to Shopify reports and higher MTUs on MoEngage which might have an impact on pricing. It is explained in the example below:
* For example, with the shipping mobile number as the UID, a user Bob places an order with the shipping mobile number SM1. Bob's profile will be created with UID as SM1. Now Bob places another order with a different shipping mobile number SM2, another profile will be created on MoEngage with UID as SM2, with only the order placed event as the events before adding the SM2 as the shipping mobile number will be tracked against Bob's profile with SM1 as UID.
* Now SM1 user will get all the configured abandoned cart and abandoned checkout campaigns as the order placed event will be tracked against the SM2 user and SM1 will satisfy the Add to cart but not order placed criteria mostly used for abandoned cart/checkout campaigns.
* On Shopify reports, you will see one user with 2 orders while on MoEngage you will have 2 users with 2 orders placed.
* To avoid such miscommunication and discrepancy, it is strongly advised to not use the shipping mobile number as UID
- Why are there multiple profiles for the same mobile number/Email?
* Profiles are merged when their unique identifier is the same, so if the same user visits your website from multiple devices but does not provide the user attribute you are using as UID there will be multiple profiles for the same user as the UID between the two profiles does not match.
* For example, If email is set as UID, and the user places 2 orders from different devices/browsers but does not provide email while checking out, instead uses the same mobile number while placing both orders. Then there will be two profiles available on the MoEngage dashboard both with the same mobile number as the user attribute. This is because the UID that is expected to be Email does not match between these 2 profiles hence the profiles can't be merged.
# User and Order backfill
* What all data can be synced?
* User data, i.e. all the user profiles available at the time of installation will be synced when you sync data.
* Order data. i.e. the orders placed during the period selected by you will be synced
* The data sync has failed what could be the reason?
* If you have selected mobile number as the UID for users and some of the existing user profiles on Shopify do not have the mobile number attribute set, we will not be able to automatically successfully sync those users and their order data. \
You should reach out to our support team to get the user and event upload done manually.
* If the event retention policy on MoEngage is less than the period you are trying to sync the order data for, the data sync will be partial as per the retention policy of the event. You would need to get the retention of the Shopify-Order placed event increased first and then retry the sync to have all the expected past order events data synced successfully.
* The default retention policy allows 60 days of past order sync. So if you sync order events for the last 1 year only orders placed in the last 60 days will be synced.
* How do you sync data successfully?
* Please make sure that your account does not have any existing data in it before syncing the past order and user data. If there are existing user and event data, performing this sync might lead to duplicates and overall data corruption
* Please use the date range before the date of installation of the app as after the installation the order data is expected to be present in your MOE account. So if you are installing the app on 10th Jan 2024, please select a date before 10th Jan to sync the orders data.
# Catalog sync
* How does catalog sync work?
* MoEngage fetches the whole product catalog associated with your store and syncs the feed into Moengage.
* A new catalog in Moengage is automatically created when you enable the product catalog sync from within the app settings.
* The catalog is updated automatically every 24 hours. Sync happens at 8 am IST every day.
* What product details are synced?
* Each product variation ID is treated as a unique product identifier. In addition to variation ID other synced product attributes are Variation ID, product ID, Product title, image\_link, Vendor Name, SKU, Variation Title, Currency, Price, Quantity, Status, Description, created\_at, updated\_at
* How do I customize the feed to add more attributes?
* The product attributes are currently fixed, please raise a feature request to add more attributes to the existing list.
* You can create a new feed with the attributes you need and a sync frequency that works best for you to add your custom product attributes into MoEngage.
* What are the limitations of automatic catalog sync?
* The list of product attributes is fixed. Product attributes like product links are currently not available in the automated product feed.
# Event Tracking
* How does the automated event tracking work?
* Based on the app settings, we automatically track the events you have enabled for automated tracking. Events are tracked by the combination of our Web SDK and Shopify Webhooks.
* Events are not getting tracked against my profile?
* There are multiple ways to fix/debug this
* If the event in question is pre checkout event, add the moe [Chrome plugin](https://chromewebstore.google.com/detail/moengage-sdk/dhggnkfnnoebbfofpimfehcklnekmbgi) on your browser and then perform the events from your browser once again.
* If the Chrome plugin shows the events are tracked successfully, then the event tracking is working fine. Please check if you are looking at the correct user profile, user profile details are available in the Chrome plugin as well.
* If the plugin does not show the event as tracked, then it might be due to the customizations that you might have added to the website. Please check the console log to see if there are any errors.
* If you are still not able to identify the issue please reach out to the MoEngage support team.
* If the events in question are checkout and post-checkout events
* Check if the events are currently enabled for automated tracking.
* Check if the same event is getting tracked for other users
* Please check if the events are tracked against a different profile by filtering on event attributes with your order ID, email, or shopping mobile number.
* Please reach out to our support team if you are still not able to identify\
the reason.
* Why none of the events are getting tracked for my store?
* Please check using the [Chrome plugin](https://chromewebstore.google.com/detail/moengage-sdk/dhggnkfnnoebbfofpimfehcklnekmbgi) if MoEngage SDK is getting loaded on your store.
* If the SDK is not detected on your store, please follow the initialization steps again.
* Unsave and save the app embed setting again.
* If the MOE SDK is available on your store, please resave the event tracking settings from within the MoEngage Shopify App.
* Please uncheck a few events from the list and save the setting.
* Again check all the events and resave the settings.
* Now after 5 minutes, please perform the events again, the events will be flowing in.
# Linking multiple stores to a single MoEngage Account
Ideally, we do not recommend integrating multiple stores into the same account on MoEngage. But if you want to do it, you can use the same Authentication keys during installation across different stores to link it to the same account on MoEngage.
We suggest you take this decision after understanding the limitations below.
## Limitations
* * Web Push
* The same user will be asked for a separate web push permission for each store
* All users' campaigns will deliver duplicate notifications to users who have subscribed to web push on multiple stores
- OSM
* You would need to specify the target URL for each campaign targeting a specific store. Otherwise, all stores will be displaying the same campaign and any common user will see it on all of your stores.
- Data
* We recommend that organizations use the same user identifier for different brand stores to have a single view of customers across the stores else this will result in the creation of multiple profiles for the same user.
- Segmentation
* Please use either URL or store ID filters in the event attributes to identify the events for each store.
# Shopify 2.0
Source: https://moengage.com/docs/developer-guide/ecommerce-platforms/shopify/shopify-20
Install and configure the MoEngage app on your Shopify 2.0 store for cross-channel engagement.
# Overview
The Shopify and MoEngage integration allows you to seamlessly integrate MoEngage Web SDK to your brand's Shopify store to track user events and data. You can use channels such as Web Push, On-Site Messaging, SMS, Email, and Web Personalization to reach out to your store visitors to nudge them towards converting.
With this integration, you can enable real-time data sync, provide personalized recommendations, and increase conversions using cross-channel engagement.
You can also use Analytics to understand users' behavior on your Shopify Store and derive insights about them.
## Installing the MoEngage App on your Shopify store
1. Navigate to the *App marketplace* on the MoEngage Dashboard.
2. Search for *Shopify 2.0* and click on the Shopify tile.
3. Navigate to the Integrate tab.
4. Click *Install MoEngage app on your Shopify store*.
5. Click the *Install app* at the top left corner.
6. Enter the authentication parameters in the MoEngage app integration screen (MoEngage app ID and app key).
The Data API ID and Key are available at **Settings -> Account -> APIs**.
To fetch the app ID and app key, do the following:
1. If you do not have a MoEngage account, click *Sign up now*. You will be directed to the account creation page for MoEngage. Skip to step 3 if you have a MoEngage account already.
2. Fill out the form and submit the request for creating a MoEngage account. Once your MoEngage account has been created, you can fetch the authentication credentials described below.
3. Login to your MoEngage account.
4. From the dashboard, copy these values and paste them on your Shopify Installation page.
| **Field** | **Description** |
| :----------- | :------------------------------------------------------------------------------------------------------------------ |
| App ID | The Workspace ID of your MoEngage account is available at **Settings -> Account -> APIs ->** **Workspace ID**. |
| Data API ID | The Data API ID and the Workspace ID of your MoEngage account are the same. |
| Data API Key | The Data API key of your MoEngage account is available at **Settings -> App Settings -> APIs -> API Keys -> Data**. |
5. Click *Authenticate and Continue*. Once your authentication is successful, you can configure your app.
6. The Initialization Settings popup appears after you've successfully authenticated your app.
## Initialization Settings
The following steps must be performed for MoEngage to track user data and events.
The following settings must be configured on Shopify for successful integration:
1. Enable the MoEngage-Shopify app to embed on your Shopify Store. To do so:
1. Navigate to Theme Settings. (add link)
2. Turn on the *MoEngage Shopify app embed* setting.
3. Click *Save*.
2. Enable advanced order tracking - To track *Order Placed* events on MoEngage, copy the script shown in the Initialization Settings pop-up and paste it into the additional scripts section of the Shopify admin dashboard.
```ruby Code theme={null}
```
## Configuration Settings
After successful initialization, navigate to the Configuration tab and do the following:
1. Select user events and properties that you want to track or be tracked. Note: MoEngage tracks some events by default. For more information about tracked default events, refer to [Event and Data Tracking](/developer-guide/ecommerce-platforms/shopify/events-and-user-data-tracking).To track custom events, refer to [Tracking Custom Events in MoEngage](/developer-guide/web-sdk/data-tracking/web-sdk-events-tracking).
2. Select the User Identifier (Email or Phone Number) in the *User Identifier for user synced* field. You can choose this identifier only once during integration.
3. To sync user data, navigate to the Data tab and follow the instructions in [User Data Sync](/developer-guide/ecommerce-platforms/shopify/user-data-sync).
4. Navigate to the *Configuration* tab and click *Save configuration*.
# Enable Web personalization
MoEngage's Web personalization helps you personalize the website experience for every visitor with limited or no involvement from tech teams. To use MoEngage's Web Personalization for your Shopify store:
1. Web Personalization should be enabled for your MoEngage account. If it is not enabled for your account, contact your CSM or [raise a support ticket](https://help.moengage.com/hc/en-us/articles/28298317432724-Raise-a-Support-Ticket-from-the-MoEngage-Login-Page).
2. Turn on the *Enable web personalization on your store* toggle.
# Next Steps
Now that your integration is successful, you can sync data about your past orders and start tracking events.
1. [Events and User Data Tracking](/developer-guide/ecommerce-platforms/shopify/events-and-user-data-tracking)
2. [Sync User Data](/developer-guide/ecommerce-platforms/shopify/user-data-sync)
3. [Steps to Validate Integration](/developer-guide/ecommerce-platforms/shopify/validate-integration)
4. [FAQ](/developer-guide/ecommerce-platforms/shopify/faqs)
# Sync Product Catalog
Source: https://moengage.com/docs/developer-guide/ecommerce-platforms/shopify/sync-product-catalog
Sync your Shopify product catalog to MoEngage to generate personalized recommendations for customers.
Basic Recommendations should be enabled for your account. Accounts on the Enterprise plan have recommendations enabled by default. Other accounts should reach out to their CSM or the MoEngage Support team if you wish to enable it for your account.
You can sync your store's existing product catalog. to MoEngage and use it to generate personalized [Recommendations](https://help.moengage.com/hc/en-us/articles/16292685447444-Overview).
1. You can enable the catalog at any time after doing the initial installation of our Shopify App.
2. The first-time sync will start as soon as you enable the option. Once the sync is complete, the sync status will be updated. Then onward the catalog will be automatically refreshed daily between 8-10 am IST.
3. In case of a failure, you can try to sync again.
4. After the first successful sync, you can find a new Catalog created in your MoEngage account with the suffix "Shopify product catalog".
5. When you **Stop** the sync, the next daily refresh will be stopped. The catalog will still be available in the Moengage dashboard. You can manually remove the catalog from your Moengage account.
This auto-created catalog will have your existing store's product and their metadata synced with MoEngage. Each synced product's metadata includes
| Attribute | Description |
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Variation ID | The variation ID for each item. This is used as the unique identifier for each item in your catalog. |
| Product ID | The Product ID of your item in the catalog. Multiple variation IDs can have the same product IDs. |
| Link | The URL for accessing the item in your store. |
| Image\_link | The URL for accessing the image, associated with the variation ID |
| Vendor Name | The name of the product's vendor. |
| SKU | The SKU identifier for your item |
| Variation Title | The Title for the associated variation ID of your item |
| Currency | This is the same as the selection made by you while enabling the catalog sync |
| Price | The Price item. |
| Quantity | The quantity of the variation id present in your store. |
| Status | The status of the product \* active: The product is ready to sell and is available to customers. \* archived: The product is no longer being sold and isn't available to customers \* draft: The product isn't ready to sell and is unavailable to customers. By default, duplicated and unarchived products are set to draft. |
| Description | The description of your item. |
| Created\_at | Date and time ([ISO 8601 format](https://en.wikipedia.org/wiki/ISO_8601)) when the item was first added to your catalog. |
| Updated\_at | Date and time ([ISO 8601 format](https://en.wikipedia.org/wiki/ISO_8601)) when the item was last updated. |
If you have any questions about the working of your Shopify integration read our [FAQs](/developer-guide/ecommerce-platforms/shopify/faqs).
# User Data Sync
Source: https://moengage.com/docs/developer-guide/ecommerce-platforms/shopify/user-data-sync
Sync your existing Shopify users and order history to MoEngage for segmentation and engagement.
After you have completed the initial setup and have a working integration, you can use this option to sync your existing users and their order data into MoEngage.This ensures all your users' past data is available in your MoEngage account. You can use this data to start engaging and segmenting the users from Day 1.
# Sync User Data
To sync user data to MoEngage:
1. Switch to the *Sync Shopify data* tab on the installed App.
2. Select the period from which the order data has to be synced to MoEngage by selecting the *Date range*. You can sync data up to the last 2 years from the date of installation. But before doing the sync beyond 60 days please make sure to increase the event retention for the events. Reach out to your customer success manager or support for the next steps on increasing event retention.
3. The date range selection outlines the limit on the order data only, all the registered user data as of the installation date available in your store will be synced irrespective of when a user was created.
4. Click sync past data after choosing the date range. Once the sync has started, you will get information about it in the Sync progress section, as shown below. It may take up to 24 hours to complete data sync, depending on the date range selected. Once the sync is complete the status will be updated to "Sync successful".
The past order data will be synced in Moengage as a separate event for each unique order ID. The Event raised will be "[Shopify - Order Placed](/developer-guide/ecommerce-platforms/shopify/events-and-user-data-tracking)"and the "Created at" event attribute will be the date time value of when the order was placed.
Similarly, each synced user's profile will be created on MoEngage with either an Email or Mobile number as the unique identifier, as per the [UID set](/developer-guide/ecommerce-platforms/shopify/shopify-20). In addition to the UID, the following attributes will also be synced if available with the newly created profiles. If some attributes aren't present in the user's Shopify profile, those attributes will be left empty.
* Email
* First Name
* Last Name
* Phone
* City
* Country
* State
* Shopify Id
* Accepts Marketing
* Order count
If you have any questions about the working of your Shopify integration read our [FAQs](/developer-guide/ecommerce-platforms/shopify/faqs)
# User Profile Management with Shopify
Source: https://moengage.com/docs/developer-guide/ecommerce-platforms/shopify/user-profile-management-with-shopify
Understand how user profiles transition from anonymous to registered and how merging works with Shopify.
A typical journey of a user visiting a Shopify store starts from being an anonymous user to a known user to a registered user. This article aims to detail how the user transitions through these stages, and how certain user actions are tied to the changes that are made to their user profiles on MoEngage.
# Shopify User tracking
A user visiting your store's website is tracked by 2 major sources, MoEngage WebSDK, which is integrated with your store as part of the integration steps, and other is Webhooks, which MoEngage starts receiving from Shopify once the integration is complete. How and when all the automated user events are tracked can be best described by the image below.
For the events that are tracked from both SDK and Webhook, please always select the Webhook events while using them in segmentation or campaign creation, as they are received from Shopify directly and are likely to be more accurate.
# User Profile Attribute tracking
The profile attributes like First name, last name, and Shopify ID are typically tracked when the user creates an account for your Shopify store. For anonymous users, these attributes are collected while checkout along with the checkout updated event.
Email and mobile number attributes are collected as a result of the On-Site Messaging form submission, customer login, customer registration, or lastly when the user shares their mobile number or email during the checkout. As soon as these attributes are tracked they are also set as the UID of the profile based on the UID setting configured as part of the integration. So if Email is selected as the UID for the integration, when the email standard user attribute is tracked, the same value is set as the UID of the profile as well.
# Profile Merging
Profile merging usually happens when we find two profiles on MoEngage with the same UID value. So generally, when a user's UID attribute (either email or Mobile number) is tracked and we find another profile existing on MoEngage with the same UID these profiles are then merged.
Profile merging is a common practice to track user activity under a single profile when the same user visits your store's website from a new device. But with Shopify integration, profile merging is also used to merge the user event from the same device but from two sources as described in the previous sections. This merging happens mostly based on the common identifier that is present while tracking from both SDK and Webhooks. This attribute is a Cart token, which is generated when the cart is created on Shopify when you add your first item to the empty cart. The Cart token is generated every time a cart is left empty, either by placing the order or removing all the items from the cart.
The image below tries to describe the process of how profile merging happens in this case
# Things to know
1. Why are there more user profiles in MoEngage than the total visitors from Shopify reports?
* This is likely to happen in the following cases
* If your website allows a user to start the checkout process without requiring the product to be added to the cart ( aka BUY NOW button), the SDK events and webhooks events will not be merged into the same profile, hence creating more profiles on MoEngage that actual users.
* If an order is placed from a new device/browser where the attribute expected to be the UID is not entered by the user during checkout, there will be more than one user profile for the same user. E.g. if the Mobile number is set as UID, and the mobile number is not entered by the user while placing a new order from a new device, the profiles will not be merged. It is advised to use [multiple identifiers](https://help.moengage.com/hc/en-us/articles/24050999467284-Unified-Identity-Identity-Resolution#h_01HQK9NXP3J3SHZJTEH95J89AC) to address this.
2. Why does MoEngage create a new user profile to track events received via Webhooks?
* MoEngage only creates a new user for tracking the webhook events when, even after our best efforts, we aren't able to resolve the received webhook to an existing user profile. In such cases only we create a new user profile.
* We are optimising for the accuracy and efficacy of our event tracking so that the marketers can utilise all the users and their events while targeting a user from a campaign in MoEngage. If we do not create the new user, the event will not be tracked, and there could be important campaigns that will not be triggered at the right time, to the right users, if there are discrepancies in our event tracking.
# Validate Integration
Source: https://moengage.com/docs/developer-guide/ecommerce-platforms/shopify/validate-integration
Validate your MoEngage Shopify integration to ensure user events and data are tracked correctly.
After installing MoEngage on your Shopify store, validate the integration for seamless tracking of user events and data.
Use the steps below to validate your MoEngage \< > Shopify integration:
1. Install the MoEngage [Chrome plugin](https://chrome.google.com/webstore/detail/moengage-sdk/dhggnkfnnoebbfofpimfehcklnekmbgi).
2. Open your Shopify store on a new browser (or hard refresh).
3. Verify whether your website is loading the MoEngage SDK:
* If not, try un-saving and saving the app embed block settings in the App theme settings. The website may not load the MoEngage SDK if the integration steps are not followed consistently.
* If the issue persists, check the console log for errors.
* Contact MoEngage support if the above solutions don't work.
4. Once the MoEngage SDK is loaded, perform the **Product view** and **Add to Cart** events to check if MoEngage is successfully tracking data in your app settings.
MoEngage tracks data using Shopify's default checkout process. Therefore, if Shopify's default checkout flow is changed, it may affect the data tracking process and lead to discrepancies. In such cases, ensure to use a custom cart or checkout flow.
5. While the **Product view** and **Add to Cart** events are being tracked properly, ensure to check if the cart token user attribute is getting set or not.
The integration will be active and should function as intended if the above mentioned checklist is completed.
For more information, see [FAQs](/developer-guide/ecommerce-platforms/shopify/faqs).
# WooCommerce
Source: https://moengage.com/docs/developer-guide/ecommerce-platforms/woo-commerce/woocommerce
Integrate your WooCommerce store with MoEngage using Google Tag Manager for event and user tracking.
WooCommerce is an open source e-commerce platform built on WordPress, that is used by more than 3M+ online stores worldwide. This document covers the integration steps required to integrate a store on WooCommerce with Moengage.
* Add Google Tag Manager (GTM) to your WooCommerce store. Refer to this [official documentation](https://woocommerce.com/document/gtm-ecommerce-woo-pro/#how-to-install) for detailed steps.
* Complete the GTM and MoEngage integration by following the integration steps [here](https://partners.moengage.com/hc/en-us/articles/18795331766676).
* You can track any user event and/or User properties from your store to MoEngage via GTM.
* This integration allows you to further integrate with the following MoEngage channels.
| Channel | Supported? |
| ------------------- | ------------------------------------------------------------------------------------------------------------------- |
| On- site messaging | Yes |
| Web personalization | Yes ([integration](/developer-guide/personalize-sdk/sdk-integration/web-personalization-v2) script should be added) |
| WebPush | No |
Your store must be on WooCommerce Pro plan to complete this integration.
# Self Handled Cards
Source: https://moengage.com/docs/developer-guide/flutter-sdk/cards/self-handled-cards
Build custom card views in your Flutter app using the MoEngage self-handled cards SDK and APIs.
Self-handled cards give you the flexibility of creating Card Campaigns on the MoEngage Platform and displaying the cards anywhere inside the application. SDK provides APIs to fetch the campaign's data using which you can create your own view for cards.

# SDK Installation
# Installation
To add MoEngage Cards SDK to your application, edit the application's **pubspec.yaml** file and add the below dependency to it:
```yaml pubspec.yaml theme={null}
dependencies:
moengage_cards: $latestVersion
```
***\$latestVersion*** refers to the latest version of the plugin.
Post including the dependency, run ***flutter pub get*** command in the terminal to install the dependency.
After installing the plugin, use the following platform-specific configuration.
This plugin is dependent on **moengage\_flutter** plugin. Make sure you have installed the **moengage\_flutter** plugin as well. Refer to the [documentation](/developer-guide/flutter-sdk/sdk-integration/sdk-installation/framework-dependency) for the same.
# Android Installation
Add the following dependency in the *app/build.gradle* file.
```json build.gradle wrap theme={null}
dependencies {
...
implementation("com.moengage:cards-core:$sdkVersion")
}
```
replace **\$sdkVersion** with the appropriate SDK version. Minimum supported version 1.5.0.
# iOS Installation
In the case of iOS, the native dependency is part of the Cards flutter SDK itself, so there is no need to include any additional dependency for supporting Cards.
# Initialize Cards
MoEngage Cards module can be initialized in the widget where the cards module is being used.
```Dart Dart theme={null}
MoEngageCards cards = MoEngageCards(YOUR_Workspace_ID);
cards.initialize();
```
Example
```Dart Dart theme={null}
// Use Named Import otherwise MoEngage classes might be collided with classed in flutter/material.dart
import 'package:moengage_cards/moengage_cards.dart' as moe;
class CardsScreen extends StatefulWidget {
const CardsScreen({Key? key}) : super(key: key);
@override
State createState() => _CardsScreenState();
}
class _CardsScreenState extends State{
moe.MoEngageCards cards = moe.MoEngageCards("MOE_Workspace_ID");
@override
void initState() {
super.initState();
cards.initialize();
}
}
```
# Get Cards Info
Fetch All the cards campaign data that are eligible to show for the particular user which returns data as ***CardsInfo***. For a complete list of data models please refer to the [API documentation](https://pub.dev/documentation/moengage_cards/).
```Dart Dart theme={null}
MoEngageCards cards = MoEngageCards(YOUR_Workspace_ID);
CardsInfo cardsInfo = await cards.getCardsInfo();
```
## Widget and Widget Id Mapping
### Basic Card/Illustration Card
| Widget Id | Widget Type | Widget Information |
| --------- | -------------------------- | --------------------------------- |
| 0 | Image (WidgetType.IMAGE) | Image widget in the card. |
| 1 | Text (WidgetType.TEXT) | Header text for the card. |
| 2 | Text (WidgetType.TEXT) | Message text for the card. |
| 3 | Button (WidgetType.Button) | Call to action(CTA) for the card. |
# Refresh Cards
Use the ***refreshCards***\*()\*\*\* API to refresh cards on the User Demand. This API can be used to mimic Pull to refresh behavior.
```Dart Dart theme={null}
MoEngageCards cards = MoEngageCards(YOUR_Workspace_ID);
cards.refreshCards((data) { if (data?.hasUpdates == true) { // Update UI }});
```
# Fetch Cards
Use the ***fetchCards***\*()\*\*\* API to fetch cards for the User. This API can be used to sync latest cards data.
```Dart Dart theme={null}
MoEngageCards cards = MoEngageCards(YOUR_Workspace_ID);
cards.fetchCards().then((data) { // Update UI});
```
# Inbox Loaded
You can show the cards on a separate screen or a section of the screen. When the cards screen/section is loaded call ***onCardsSectionLoaded()***.
```Dart Dart theme={null}
MoEngageCards cards = MoEngageCards(YOUR_Workspace_ID);
cards.onCardsSectionLoaded((data) {
if (data?.hasUpdates == true) {
// Refresh UI
}
});
```
# Inbox UnLoaded
Call ***onCardSectionUnloaded()*** when the screen/section is no longer visible or going to the background.
```Dart Dart theme={null}
MoEngageCards cards = MoEngageCards(YOUR_Workspace_ID);
cards.onCardsSectionUnLoaded();
```
# Fetch Categories
To fetch all the categories for which cards are configured, use the ***getCardsCategories()*** API.
```Dart Dart theme={null}
MoEngageCards cards = MoEngageCards(YOUR_Workspace_ID);
List categories = await cards.getCardsCategories();
```
# All Cards Categories Enabled
To fetch all the categories for which cards are configured, use the ***isAllCategoryEnabled()*** API.
```Dart Dart theme={null}
MoEngageCards cards = MoEngageCards(YOUR_Workspace_ID);
bool isAllCategoryEnabled = await cards.isAllCategoryEnabled();
```
# Fetch Cards for Categories
To fetch cards eligible for display for a specific category use the ***getCardsForCategory()*** API.
```Dart Dart theme={null}
MoEngageCards cards = MoEngageCards(YOUR_Workspace_ID);
int count = await cards.getCardsForCategory(category);
```
# Get New Cards Count
To obtain the new cards count use ***getNewCardsCount()*** method as shown below:
```Dart Dart theme={null}
MoEngageCards cards = MoEngageCards(YOUR_Workspace_ID);
int count = await cards.getNewCardsCount();
```
# Card Shown
Call the ***cardShown()*** API to notify a card is shown to the user.
```Dart Dart theme={null}
MoEngageCards cards = MoEngageCards(YOUR_Workspace_ID);
cards.cardShown(context, card); // Pass Card Object
```
# Card Clicked
Call the ***cardClicked()*** API to notify a card is shown to the user.
```Dart Dart theme={null}
MoEngageCards cards = MoEngageCards(YOUR_Workspace_ID);
cards.cardClicked(card, widgetId); // Pass Card Object
```
# Delete Card
Call the ***deleteCard()*** API to delete a card.
```Dart Dart theme={null}
MoEngageCards cards = MoEngageCards(YOUR_Workspace_ID);
cards.deleteCard(card); // Pass Card Object
```
# Mark Card Delivered
To track delivery to the card section of the application call the ***cardDelivered()*** API when the cards section of the application is loaded.
```Dart Dart theme={null}
MoEngageCards cards = MoEngageCards(YOUR_Workspace_ID);
cards.cardDelivered();
```
# Delete Multiple Cards
Call the ***deleteCards()*** API to delete a card.
```Dart Dart theme={null}
MoEngageCards cards = MoEngageCards(YOUR_Workspace_ID);
cards.deleteCards(context, cards); // Pass List of Cards
```
# Get Unclicked Cards Count
To obtain the unclicked cards count use ***getUnClickedCardsCount()*** method as shown below.
```Dart Dart theme={null}
MoEngageCards cards = MoEngageCards(YOUR_Workspace_ID);
int count = await cards.getUnClickedCardsCount();
```
# App Open Card Sync Listener
Set this listener to get a callback for card sync on the App opened. This listener should be set before calling ***initialize()*** API. In most cases, this API is not required.
```Dart Dart theme={null}
MoEngageCards cards = MoEngageCards(YOUR_Workspace_ID);
cards.setAppOpenCardsSyncListener((data) {
//Update UI
});
cards.initialize();
```
The hybrid framework does not support the MoEngage default Card. Only the Self-handled Card is supported.
# Delete User From MoEngage Server
Source: https://moengage.com/docs/developer-guide/flutter-sdk/data-tracking/delete-user-from-moengage-server
Delete the current user from the MoEngage server using the deleteUser() method in the Flutter SDK.
This API is supported from **moengage\_flutter** version **6.1.0** and is only available for the Android platform and it will throw [UnImplementedError](https://api.flutter.dev/flutter/dart-core/UnimplementedError-class.html) error in other platforms
To delete the current user from the MoEngage server use the ***deleteUser()*** method as shown below, where you will get an instance of [***UserDeletionData***](https://pub.dev/documentation/moengage_flutter_platform_interface/latest/moengage_flutter_platform_interface/UserDeletionData-class.html).
```javascript Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
final MoEngageFlutter _moengagePlugin = MoEngageFlutter();
_moengagePlugin.initialise();
// Below method will return an instance of >
_moengagePlugin.deleteUser().then((value) {
// Add your code to handle the callback.
}).catchError((onError) {
// Add your code to handle the Error.
});
```
For more information, please refer to the [API documentation](https://pub.dev/documentation/moengage_flutter/6.1.0/moengage_flutter/MoEngageFlutter/deleteUser.html).
# Enable Advertising Identifier Tracking
Source: https://moengage.com/docs/developer-guide/flutter-sdk/data-tracking/enable-advertising-identifier-tracking
Enable advertising identifier tracking in your Flutter app for accurate device analytics.
For accurate analytics around devices and tracking Re-installs, it is essential to track the Advertising Identifier.
## Add Ad Identifier Library
Add the below dependency in the application level ***build.gradle*** file.
```groovy Groovy theme={null}
implementation("com.google.android.gms:play-services-ads-identifier:18.0.1")
```
To enable Advertising Identifier tracking use the *enableAdIdTracking()* method as shown below.
```dart Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
final MoEngageFlutter _moengagePlugin = MoEngageFlutter(YOUR_APP_ID);
_moengagePlugin.initialise();
_moengagePlugin.enableAdIdTracking();
```
Before you enable Advertising Id tracking please ensure the application is complying with the [Google Play Policy](https://support.google.com/googleplay/android-developer/answer/10144311) regarding Advertising Id tracking. Refer to our [help document](https://help.moengage.com/hc/en-us/articles/7457641031828) for more information on the policy.
In case, you need to disable advertising-id after enabling tracking use the following method.
```dart Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
final MoEngageFlutter _moengagePlugin = MoEngageFlutter(YOUR_APP_ID);
_moengagePlugin.initialise();
_moengagePlugin.disableAdIdTracking();
```
The above APIs are available only starting plugin version 4.2.0. In the older versions, Advertising Identifier tracking is enabled by default.
# Install/Update Differentiation
Source: https://moengage.com/docs/developer-guide/flutter-sdk/data-tracking/install-update-differentiation
Differentiate between app installs and updates in your Flutter app using the MoEngage setAppStatus API.
SDK needs support to enable the update by the user application or install the application. You need to have logic on the app side to distinguish between app *INSTALL* and *UPDATE*.
If the user was already using your application and has just updated to a new version that has MoEngage SDK, it is an update. Call the below API
```Dart Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
final MoEngageFlutter _moengagePlugin = MoEngageFlutter(YOUR_Workspace_ID);
_moengagePlugin.initialise();
_moengagePlugin.setAppStatus(MoEAppStatus.update);
```
In case it is a fresh install call the below API
```Dart Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
final MoEngageFlutter _moengagePlugin = MoEngageFlutter(YOUR_Workspace_ID);
_moengagePlugin.initialise();
_moengagePlugin.setAppStatus(MoEAppStatus.install);
```
For more information, refer to [Flutter SDK](https://github.com/moengage/Flutter-SDK).
# Setting Unique Id for SDK versions below 9.2.0
Source: https://moengage.com/docs/developer-guide/flutter-sdk/data-tracking/setting-unique-id-for-sdk-versions-below-920
Set a unique user ID for login and logout handling in MoEngage Flutter SDK versions below 9.2.0.
# Implementing Login/Logout
* It's important to set the User Attribute Unique ID when a user logs into your app.
* This is to merge the new user with the existing user, if any exists, and will help prevent creation of unnecessary/stale users.
* Setting the Unique ID is a critical piece to tie a user across devices and installs/uninstalls as well across all platforms (i.e. iOS, Android, Windows, The Web). Set the **USER\_ATTRIBUTE\_UNIQUE\_ID** attribute as soon as the user is **logged in**. Unique ID can be something like an email ID, a username (unique), or a database ID or any Backend generated ID.
* Do not set this for the user who not logged in.
## Login
```Dart Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
final MoEngageFlutter _moengagePlugin = MoEngageFlutter(YOUR_APP_ID);
_moengagePlugin.initialise();
_moengagePlugin.setUniqueId("Unique ID");
```
**Note:** The following values are not allowed in the UniqueID field: "unknown", "guest", "null", "0", "1", "true", "false", "user\_attribute\_unique\_id", "(empty)", "na", "n/a", "", "dummy\_seller\_code", "user\_id", "id", "customer\_id", "uid", "userid", "none", "-2", "-1", "2"
## Logout
The application needs to notify the MoEngage SDK whenever the user is logged out of the application. To notify the SDK, call the API whenever the user is logged out of the application.
```Dart Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
final MoEngageFlutter _moengagePlugin = MoEngageFlutter(YOUR_WORKSPACE_ID);
_moengagePlugin.initialise();
_moengagePlugin.logout();
```
## Updating User Attribute Unique Id
Use the method *setAlias()* to update the user attribute unique id instead of *setUniqueId()* with a different value. Using the method *setUniqueId()* with a new value creates unintended users in MoEngage.
```Dart Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
final MoEngageFlutter _moengagePlugin = MoEngageFlutter(YOUR_WORKSPACE_ID);
_moengagePlugin.initialise();
_moengagePlugin.setAlias("Updated Unique ID");
```
**Critical**
Please make sure that you use `setAlias()` for updating the Unique Identifier and not `setUniqueId()` as calling `setUniqueId()` with a new value will reset the current user and lead to the creation of unintended users in our system.
# Tracking Events
Source: https://moengage.com/docs/developer-guide/flutter-sdk/data-tracking/tracking-events
Track custom user events and their properties in your Flutter app using the MoEngage trackEvent API.
SDK adheres to the MoEngage FUP policies. For more information, refer to the [Fair Usage Policy](https://help.moengage.com/hc/en-us/articles/24151864954644-Fair-Usage-Policy-FUP#h_01HQSMZVQWT2KYP0PY1P8GQMRM).
Tracking events is how you record any actions your users perform, along with any properties that describe the action. Every trackEvent call records a single user action. We recommend that you make your event names human-readable so that everyone on your team can know what they mean instantly.
Every TrackEvent() call expects 2 parameters, event name, and Properties instance which represent additional event attributes about the event. Add all the additional information which you think would be useful for segmentation while creating campaigns. For eg: the following example shows an example of tracking an event with all the possible data types.
```Dart Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
var properties = MoEProperties();
properties.addAttribute("attrString", "String Value")
.addAttribute("attrInt", 123)
.addAttribute("attrBool", true)
.addAttribute("attrDouble", 12.32)
.addAttribute("attrLocation", new MoEGeoLocation( 12.1, 77.18) )
.addAttribute("attrArray", ["item1", "item2", "item3"])
.addAttribute('product', {'item-id' : 123,'item-type' : 'books','item-cost' : {'amount' : 100,'currency' : 'USD'}})
.addAttribute('products', [{'item-id' : 123,'item-cost' : {'amount' : 100,'currency' : 'USD'}},{'item-id' : 323,'item-cost' : {'amount' : 90,'currency' : 'USD'}}])
.addISODateTime("attrDate", "2019-12-02T08:26:21.170Z");
final MoEngageFlutter _moengagePlugin = MoEngageFlutter(YOUR_APP_ID);
_moengagePlugin.initialise();
_moengagePlugin.trackEvent('Flutter Event', properties);
```
You can not use "moe\_" as a prefix while naming events, event attributes, or user attributes. It is a system prefix and using it might result in periodic blacklisting without prior communication.
# Analytics
MoEngage SDK has started tracking user sessions and application traffic sources. Refer to the [Sessions in MoEngage Analytics](https://help.moengage.com/hc/en-us/articles/360031402891-Understanding-Sessions-in-MoEngage-Analytics) and [Source Analysis in MoEngage Analytics](https://help.moengage.com/hc/en-us/articles/360031146052-Source-Analysis-in-MoEngage-Analytics)to learn more about how user session and application traffic source tracking works.
With user session tracking we have introduced the flexibility to selectively mark events as non-interactive.
## What is a non-interactive event?
Events that do not affect the session calculation in anyways are called non-interactive events. Non-interactive events have the below properties
* Do not start a new session.
* Do not extend the session.
* Do not have information related to a user session.
## How to mark an event as non-interactive?
To mark an event as a non-interactive call **setNonInteractiveEvent()** for **Properties** instance as shown below:
```Dart Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
var properties = MoEProperties();
properties.addAttribute( "attrString", "String Value")
.addAttribute("attrInt", 123)
.setNonInteractiveEvent();
final MoEngageFlutter _moengagePlugin = MoEngageFlutter(YOUR_APP_ID);
_moengagePlugin.initialise();
_moengagePlugin.trackEvent('Non Interactive Event', properties);
```
# Tracking User Attributes and UserIdentity
Source: https://moengage.com/docs/developer-guide/flutter-sdk/data-tracking/untitled-page
Track user attributes and set identifiers in the MoEngage Flutter SDK for cross-platform identification.
User attributes are pieces of information you know about a user. They could be demographics such as age and gender, account-specific like plan, or whether a user has seen a particular A/B test variation. User attributes are customer properties you can reference throughout the customer's lifecycle.
## Difference Between User Attributes and User Identifiers
User attributes and user identifiers serve different purposes in MoEngage:
**User Identifiers:**
User identifiers are unique values that persist across multiple sessions and devices, allowing MoEngage to recognise a user as the same individual, even when they switch between different platforms or log in later. This process, known as identity resolution, is crucial for maintaining a unified user profile, providing a consistent user experience, and tracking user behaviour accurately.
Common examples of user identifiers include:
* Email address: A user's email address is a widely used identifier because it is unique to the individual and remains consistent across different platforms.
* Phone number: Similar to email addresses, phone numbers can serve as unique identifiers, especially in mobile applications.
* User ID: MoEngage assigns each user a unique ID upon registration. This ID is used as a reliable identifier within the MoEngage platform.
* Customer ID: In e-commerce and customer relationship management (CRM) systems, a customer ID is assigned to track individual customers across various interactions.
These identifiers are set using the ***identifyUser()*** method.
By default, parameter ***ID*** is the identifier used for your workspaces, unless [Identity resolution](https://help.moengage.com/hc/en-us/articles/24050999467284-User-Identity-Resolution#h_01HQK9NXP3J3SHZJTEH95J89AC) is enabled and identifiers are activated in your workspace.
**User Attributes**:
Descriptive information about a user that enhances their profile - Used for segmentation, personalisation, and analytics - Examples: name, age, gender, preferences, purchase history - Set using dedicated methods like ***setFirstName()*** or ***setUserAttribute()*** - Help create personalised user experiences
In simple terms, identifiers answer "Who is this user?" while attributes answer "What do we know about this user?"
## Powering MoEngage Features
User attributes and identifiers are crucial for leveraging MoEngage effectively:
* **Segmentation:**
* Use attributes to create targeted user groups based on demographics, behavior, etc.
* Example: Segment users by age, purchase history for specific campaigns.
* **Personalisation:**
* Identifiers ensure consistent user experience across devices.
* Attributes enable tailored content (messages, recommendations).
* Example: Personalise emails with names, recommend relevant products.
* **Analytics:**
* Attributes provide context to user actions and behavior data.
* Analyze conversion rates by segments, feature engagement by demographics.
* Gain deeper insights for data-driven decisions.
By using attributes and identifiers, you can build more relevant and engaging user experiences.
# Implementing Login/Logout
For SDK versions below 9.2.00 refer to this document.
## Login User
**Single Identifier**
If your application relies on a single unique user identifier, such as an email ID for login, use the API below to pass the identifier to the MoEngage SDK
```json Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
final MoEngageFlutter _moengagePlugin = MoEngageFlutter();
_moengagePlugin.initialise();
_moengagePlugin.identifyUser("flutter-uid"); //Pass any unique value for your user
```
**Multiple Identifiers**
If your application supports multiple login identifiers, such as an email ID, user ID, or mobile number, pass all relevant identifiers to the SDK using the following function:
```json Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
final MoEngageFlutter _moengagePlugin = MoEngageFlutter();
_moengagePlugin.initialise();
_moengagePlugin.identifyUser({"email": "flutter@moengage.com", "id": "flutter"});
```
Updates are made to SDK functions to improve user identification and session management.
* **Forced Logout**: The MoEngage SDK no longer automatically logs out the previous user when a new user is detected on the device. Logout should now be explicitly called for workspaces enabled with Identity resolution to avoid data corruption.
* **SetUniqueID**: *IdentifyUser* function supports multiple identifiers, which replaces the need of using *SetUniqueID* function for user identification. Note that *SetUniqueID* is marked for removal in the future releases of SDK versions - it is important to use *identifyUser* instead especially if you are using Identity resolution in your workspace.
* **SetAlias**: For workspaces with the Identity resolution feature enabled, MoEngage SDK stores the previous identifier values. When *IdentifyUser* function is used to track the new identifier values, MoEngage SDK detects the change in identifier value and reports accordingly.
* If you call the *IdentifyUser* function without logging out, then the existing logged-in user's ID is updated.
**Note**: Before implementing \*\*\*identifyUser()\*\*\*with multiple identifiers, you must activate the defined identifiers on the MoEngage dashboard. For configuration steps, see [this documentation](https://help.moengage.com/hc/en-us/articles/24050999467284-User-Identity-Resolution#h_01JK58XBFD66QA3W4JJNYVBD01).
***Behaviour of Multiple identifyUser() calls***
* When calling ***identifyUser()*** multiple times, the new identifiers are appended to the existing list rather than replacing them. Here's an example of how this works:
```json Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
final MoEngageFlutter _moengagePlugin = MoEngageFlutter();
_moengagePlugin.initialise();
//First call with email _moengagePlugin.identifyUser({"u_em": "flutter@moengage.com"});
//Later call identifyUser() with mobile Number
_moengagePlugin.identifyUser({"u_mb":"999999999"});
//Result now the user has both email and mobile identifiers;
```
* If you call ***identifyUser()*** with an identifier key that already exists, the new value will be update the existing one. Here's an example of how this works:
```json Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
final MoEngageFlutter _moengagePlugin = MoEngageFlutter();
_moengagePlugin.initialise();
//First call with initial email _moengagePlugin.identifyUser({"u_em":"abc@xyz.com"});
//Later call identifyUser() when User updates their email
_moengagePlugin.identifyUser({"u_em":"jfk@xyz.com"});
//Result now the user email is updated with the later one;
```
This behaviour allows you to:
* Add new identifiers as they become available
* Update specific identifiers without affecting others
* Build a complete user identity profile over time
Here, `u_em`, `u_mb` are standard user attributes. Please refer to [this section](/developer-guide/react-native-sdk/data-tracking/tracking-user-attributes-and-user-identity) to identify user with more standard user attributes
## Standard and Custom Attributes
**Standard attributes:** These are common user attributes that are pre-defined within the MoEngage dashboard, such as email address and mobile phone number. The table below lists these standard attributes and their corresponding key names
| User Attribute Name | Key name to be used in identifyUser method |
| ------------------------ | ------------------------------------------ |
| ID | uid |
| Email (Standard) | u\_em |
| Gender | u\_gd |
| Birthday | u\_bd |
| Name | u\_n |
| First Name | u\_fn |
| Last Name | u\_ln |
| Mobile Number (Standard) | u\_mb |
**Custom attributes:** These are attributes that you define yourself within the MoEngage dashboard in addition to the standard attributes. Here's an example of how you might work with custom attributes:
```Dart Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';final MoEngageFlutter _moengagePlugin = MoEngageFlutter();_moengagePlugin.initialise();
//replace custom_attribute_name with the actual name of your custom user attribute and attributeValue with the actual value you want to assign to the attribute
_moengagePlugin.identifyUser({ custom_attribute_name: 'attributeValue' });
//you can set two or more identities at the same time
_moengagePlugin.identifyUser({ cust_attr_1: 'value1', cust_attr_2: 'value2' });
//you can set custom user identity and standard user identity at the same time
_moengagePlugin.identifyUser({ cust_attr_1: 'value1', cust_attr_2: 'value2', u_em: 'emailValue@emailDomain.com' });
```
For detailed instructions on selecting both custom and standard attributes when configuring multiple identifiers, please refer to [this document](https://help.moengage.com/hc/en-us/articles/24050999467284-User-Identity-Resolution#h_01JMESGEFWSXRECFMTN7V31Q7C).
## Logout User
The application needs to notify the MoEngage SDK whenever the user is logged out of the application. To notify the SDK, call the API whenever the user is logged out of the application.
```json Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
final MoEngageFlutter _moengagePlugin = MoEngageFlutter(YOUR_WORKSPACE_ID);
_moengagePlugin.initialise();
_moengagePlugin.logout();
```
**Critical - Very Important Integration Guideline**
Never use both the login methods - `identifyUser` and `setUserUniqueID()`(method to assign identifier present in versions below 9.2.0) in your project. Use only either one of the methods. Using both the methods can lead to inconsistent user profile creation and merging in your MoEngage account.
# Tracking User Attributes
Use the following helper methods to set User attributes like Name, Email, Mobile, Gender, etc.
```json Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
final MoEngageFlutter _moengagePlugin = MoEngageFlutter(YOUR_WORKSPACE_ID);
_moengagePlugin.initialise();
_moengagePlugin.setUserName("User Name");
_moengagePlugin.setFirstName("FirstName");
_moengagePlugin.setLastName("LastName");
_moengagePlugin.setEmail("EmailID");
_moengagePlugin.setPhoneNumber("PhoneNumber");
_moengagePlugin.setGender(MoEGender.male); // Supported values also include MoEGender.female OR MoEGender.other
_moengagePlugin.setLocation(new MoEGeoLocation(23.1, 21.2)); // Pass coordinates with MoEGeoLocation instance
_moengagePlugin.setBirthDate("2000-12-02T08:26:21.170Z"); // date format - ` yyyy-MM-dd'T'HH:mm:ss.fff'Z'`
```
For setting other User Attributes, you can use the generic method ***setUserAttribute(key,value)***
To set custom user attributes, you will have to provide the attribute name as shown below:
```json Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
final MoEngageFlutter _moengagePlugin = MoEngageFlutter(YOUR_WORKSPACE_ID);
_moengagePlugin.initialise();
_moengagePlugin.setUserAttribute("int-attr", 0);
_moengagePlugin.setUserAttribute("bool-attr", true);
_moengagePlugin.setUserAttribute("string-attr", "Some Value");
_moengagePlugin.setUserAttribute("double-attr", 10.0);
_moengagePlugin.setUserAttribute("int-arr-attr", [100,200,300]);
_moengagePlugin.setUserAttribute("string-arr-attr", ["a","b","c"]);
_moengagePlugin.setUserAttribute("double-arr-attr", [1.0,2.0,3.0]);
_moengagePlugin.setUserAttribute('product', {'item-id' : 123,'item-type' : 'books','item-cost' : {'amount' : 100,'currency' : 'USD'}});
_moengagePlugin.setUserAttribute('products', [{'item-id' : 123,'item-cost' : {'amount' : 100,'currency' : 'USD'}},{'item-id' : 323,'item-cost' : {'amount' : 90,'currency' : 'USD'}}]);
```
You can not use "moe\_" as a prefix while naming events, event attributes, or user attributes. It is a system prefix and using it might result in periodic blacklisting without prior communication.
## Tracking Date as user attributes:
To track any date as user attributes use the ***setUserAttributeIsoDate(name, date)***. This API takes the attribute name and ISO Date as input.\
Date Format -***yyyy-MM-dd'T'HH:mm:ss.fff'Z***'\
Example:
```json Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
final MoEngageFlutter _moengagePlugin = MoEngageFlutter(YOUR_WORKSPACE_ID);
_moengagePlugin.initialise();
_moengagePlugin.setUserAttributeIsoDate("timeStamp", "2019-12-02T08:26:21.170Z")
```
## Tracking Location as user attributes: (Not available for Web)
To track any location as user attributes use the *setUserAttributeLocation()*. This API takes the attribute name and an instance of MoEGeoLocation for coordinates as input.\
Example:
```json Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
final MoEngageFlutter _moengagePlugin = MoEngageFlutter(YOUR_WORKSPACE_ID);
_moengagePlugin.initialise();
_moengagePlugin.setUserAttributeLocation("locationAttr", new MoEGeoLocation(72.8, 53.2));
```
## Custom Boolean User Attribute
### iOS (optional)
Starting from version 8.x.x of **moengage\_flutter**, the default tracking for the custom boolean attribute will be changed to ***boolean(true/false)*** from ***double(0/1)***. To configure this, use ***AnalyticsConfig*** with ***shouldTrackUserAttributeBooleanAsNumber*** and pass true to track the boolean as double. By default, this is set as ***false*** to track boolean as true/false.
Refer to the example below
```json Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
final MoEngageFlutter _moengagePlugin = MoEngageFlutter(YOUR_Workspace_ID, moEInitConfig: MoEInitConfig(analyticsConfig: AnalyticsConfig(shouldTrackUserAttributeBooleanAsNumber:true)));
@override
void initState() {
super.initState();
initPlatformState();
_moengagePlugin.initialise();
}
```
Refer to the example code below for tracking the boolean user attribute
```json Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
final MoEngageFlutter _moengagePlugin = MoEngageFlutter(YOUR_Workspace_ID, moEInitConfig: MoEInitConfig(analyticsConfig: AnalyticsConfig(shouldTrackUserAttributeBooleanAsNumber: false)));
_moengagePlugin.initialise();
// If shouldTrackUserAttributeBooleanAsNumber is passed as true then `bool-attr-false` will tracked with value 0 else false
_moengagePlugin.setUserAttribute("bool-attr-false", false);
// If shouldTrackUserAttributeBooleanAsNumber is passed as true then `bool-attr-true` will tracked with value 1 else true
_moengagePlugin.setUserAttribute("bool-attr-true", true);
```
## Reserved keywords for User Attributes
Below is the list of keys that should not be used when tracking user attributes.
* USER\_ATTRIBUTE\_UNIQUE\_ID
* USER\_ATTRIBUTE\_USER\_EMAIL
* USER\_ATTRIBUTE\_USER\_MOBILE
* USER\_ATTRIBUTE\_USER\_NAME
* USER\_ATTRIBUTE\_USER\_GENDER
* USER\_ATTRIBUTE\_USER\_FIRST\_NAME
* USER\_ATTRIBUTE\_USER\_LAST\_NAME
* USER\_ATTRIBUTE\_USER\_BDAY
* USER\_ATTRIBUTE\_NOTIFICATION\_PREF
* USER\_ATTRIBUTE\_OLD\_ID
* MOE\_TIME\_FORMAT
* MOE\_TIME\_TIMEZONE
* USER\_ATTRIBUTE\_DND\_START\_TIME
* USER\_ATTRIBUTE\_DND\_END\_TIME
* MOE\_GAID
* MOE\_ISLAT
* INSTALL
* UPDATE
* status
* user\_id
You can not use "moe\_" as a prefix while naming events, event attributes, or user attributes. It is a system prefix and using it might result in periodic blacklisting without prior communication.
# InApp NATIV
Source: https://moengage.com/docs/developer-guide/flutter-sdk/in-app-messages/inapp-nativ
Display in-app messages in your Flutter app using the MoEngage SDK with platform-specific configuration.
In-App Messaging is custom views that you can send to a segment of users to show custom messages or give new offers or take to some specific pages. They can be created from your MoEngage account.
## Installing Android Dependency
### **Requirements for displaying images and GIFs in InApp**
Starting InApp version **7.0.0,** SDK requires [Glide](https://bumptech.github.io/glide/) to show images and GIFs in the in-apps. You need to add the below dependency in your **build.gradle** file.
```groovy Groovy theme={null}
dependencies {
...
implementation("com.github.bumptech.glide:glide:4.16.0")
}
```
Additional dependency installation is not required for iOS.
# Show InApp
Call the below API to show an inApp campaign on a screen. You will have to handle the redirection of the user when they click on the inApps unless it's a rich landing navigation.
```Dart Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
final MoEngageFlutter _moengagePlugin = MoEngageFlutter(YOUR_APP_ID);
_moengagePlugin.initialise();
_moengagePlugin.showInApp();
```
# Display Nudges
Starting with ***moengage\_flutter*** ***version 7.0.0*** MoEngage InApp SDK supports displaying Non-Intrusive nudges. This API is supported only in Android & IOS. You will have to handle the redirection of the user when they click on the inApps unless it's a rich landing navigation.
To show a Nudge InApp Campaign call `showNudge()`
```javascript Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
final MoEngageFlutter _moengagePlugin = MoEngageFlutter(YOUR_APP_ID);
_moengagePlugin.showNudge(); // Display Nudge on any available position
_moengagePlugin.showNudge(position: MoEngageNudgePosition.top); // Display Nudge on the specific position
```
# InApp/Nudge Redirection default behavior
On clicking an Inapp or Nudge, MoEngage SDKs will handle **only rich landing navigation** redirection.
For the screen name and deep link redirection, your app code should redirect the user to the right screen or deep link. To handle the screen name and deep link redirection, you must implement inapp click callback methods. MoEngage SDK will just pass the inapp payload to this call back code. Implementation steps are mentioned in the InApp callback section of the Integration.
# Self Handled InApps
Self-handled In Apps are messages that are delivered by the SDK to the application, and the application builds the UI using the delivered payload by the SDK. To get the self-handled in-app, use the below API.
```Dart Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
final MoEngageFlutter _moengagePlugin = MoEngageFlutter(YOUR_APP_ID);
_moengagePlugin.getSelfHandledInApp();
```
To get the self-handled campaign, register for the callback as shown below.
## Multiple Self-Handled InApps
* This feature requires a minimum moengage\_flutter version **9.0.0**
* Event-triggered multiple self-handled inapps are not supported.
Fetch Multiple Self Handled Campaigns using [*getSelfHandledInApps()*](https://pub.dev/documentation/moengage_flutter/latest/moengage_flutter/MoEngageFlutter/getSelfHandledInApps.html). The MoEngage SDK will return up to 5 campaigns(in the order of campaign priority set at the time of campaign creation). The function will return self-handled in-app data in the future.
```Dart Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
MoEngageFlutter _moengagePlugin = MoEngageFlutter(YOUR_APP_ID);
_moengagePlugin.getSelfHandledInApps().then((campaignsData) {
// Show the Self Handled InApps
}).catchError((e) {
// Error occurred while fetching the campaigns
});
```
It will return data of type [SelfHandledInAppsData](https://pub.dev/documentation/moengage_flutter/latest/moengage_flutter/SelfHandledCampaignsData-class.html).
### Tracking Statistics for Multiple Self-Handled In-Apps
The *onCampaignsAvailable()* callback method returns [*SelfHandledCampaignsData*](https://moengage.github.io/android-api-reference/inapp/com.moengage.inapp.model/-self-handled-campaigns-data/index.html)\*\*,\*\*which contains a list of [*SelfHandledCampaignData*](https://moengage.github.io/android-api-reference/inapp/com.moengage.inapp.model/-self-handled-campaign-data/index.html) objects. The statistics for each *SelfHandledCampaignData* object must be tracked individually below APIs.
### Fetching Contextual Multiple Self-Handled InApps
To fetch contextual multiple self-handled inapps, set the inapp contexts using [*setCurrentContext()*](https://pub.dev/documentation/moengage_flutter/latest/moengage_flutter/MoEngageFlutter/setCurrentContext.html) before calling \*[getSelfHandledInApps()](https://pub.dev/documentation/moengage_flutter/latest/moengage_flutter/MoEngageFlutter/getSelfHandledInApps.html).\*This will return a list of contextual and non-contextual inapps(in the order of campaign priority set at the time of campaign creation).
## Tracking Statistics for Self-Handled In-Apps
The application must notify MoEngage SDK whenever the In-App messages are displayed, clicked on, or dismissed, as the application controls these actions. The following methods are called to notify the SDK. The data object provided to the application in the callback for self-handled in-app should be passed as a parameter to the following APIs.
```Dart Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
final MoEngageFlutter _moengagePlugin = MoEngageFlutter(YOUR_APP_ID);
// call this method to notify campaign was shown.
_moengagePlugin.selfHandledShown(message);
// call this method to noftify campaign was clicked.
_moengagePlugin.selfHandledClicked(message);
// call this method to notify campaign was dismissed.
_moengagePlugin.selfHandledDismissed(message);
```
# InApp Callbacks
We provide callbacks for in-app shown, in-app clicked, in-app dismissed, and self-Handled in-app available events. You can register for the same as shown below.
The callbacks must be registered before inapps are displayed either via show methods or triggered events. Make sure you are calling `initialise()` the method of the plugin after you set up these callbacks. Refer [doc](/developer-guide/react-native-sdk/sdk-integration/react-native/sdk-initialization/manual-initialization/framework-initialization) for more info.
```Dart Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
void _onInAppClick(ClickData message) {
print("This is a inapp click callback from native to flutter. Payload " +
message.toString());
}
void _onInAppShown(InAppData message) {
print("This is a callback on inapp shown from native to flutter. Payload " +
message.toString());
}
void _onInAppDismiss(InAppData message) {
print("This is a callback on inapp dismiss from native to flutter. Payload " +
message.toString());
}
void _onInAppSelfHandle(SelfHandledCampaignData? message) {
if (message == null) {
debugPrint('$tag _onInAppSelfHandle(): SelfHandled InApp Data is Null');
return;
}
print("This is a callback on inapp self handle from native to flutter. Payload " +
message.toString());
}
final MoEngageFlutter _moengagePlugin = MoEngageFlutter(YOUR_APP_ID);
//Register for callbacks
_moengagePlugin.setInAppClickHandler(_onInAppClick);
_moengagePlugin.setInAppShownCallbackHandler(_onInAppShown);
_moengagePlugin.setInAppDismissedCallbackHandler(_onInAppDismiss);
_moengagePlugin.setSelfHandledInAppHandler(_onInAppSelfHandle);
//NOTE: set up callbacks before initialise()
_moengagePlugin.initialise();
```
# Contextual InApp
You can restrict the in-apps based on the user's context in the application apart from restricting InApp campaigns on a specific screen. To set the user's context in the application use *setCurrentContext()* API as shown below.
## Set Context
Call the below method to set the context in the *initState()* method of the widget before calling *showInApp().*
```Dart Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
final MoEngageFlutter _moengagePlugin = MoEngageFlutter(YOUR_APP_ID);
_moengagePlugin.setCurrentContext(['C1', 'C2']);
```
## Reset Context
Once the user is moving out of the context use the *resetCurrentContext()* API to reset/clear the existing context.
```Dart Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
final MoEngageFlutter _moengagePlugin = MoEngageFlutter(YOUR_APP_ID);
_moengagePlugin.resetCurrentContext();
```
For more information on Contextual InApp, refer to the video tutorial available in [Troubleshooting and FAQs](/developer-guide/android-sdk/troubleshooting-and-faqs/troubleshooting-and-faqs).
# InApp Payload
InApp Data will be received in the below format:
```Dart Dart theme={null}
class InAppData {
/// Native platform from which the callback was triggered.
Platforms platform;
//Account Data
AccountMeta accountMeta;
///In-App Campaign Data
CampaignData campaignData;
}
class CampaignData {
/// Unique identifier for each campaign.
String campaignId;
///Campaign Name
String campaignName;
...
}
class ClickData {
/// Native platform from which the callback was triggered.
Platforms platform;
/// Account Data
AccountMeta accountMeta;
/// In-App Campaign Data
CampaignData campaignData;
/// Action data with type navigation/custom
Action action;
}
class NavigationAction extends Action {
/// Type of Navigation action.
/// Possible value deep_linking or screen
NavigationType navigationType;
/// Deeplink Url or the Screen Name used for the action.
String navigationUrl;
/// [Map] of Key-Value pairs entered on the MoEngage Platform for
/// navigation action of the campaign.
Map keyValuePairs;
}
class CustomAction extends Action {
///Key-Value Pair entered on the MoEngage Platform during campaign creation.
Map keyValuePairs;
}
class SelfHandledCampaignData {
/// Native platform from which the callback was triggered.
Platforms platform;
/// Account Data
AccountMeta accountMeta;
/// In-App Campaign Data
CampaignData campaignData;
//Self handled data
SelfHandledCampaign campaign;
}
class SelfHandledCampaign {
/// Self handled campaign payload.
String payload;
/// Interval after which in-app should be dismissed, unit - Seconds
int dismissInterval;
/// InApp Campaign Display Rules
Rules displayRules;
}
class Rules {
/// Screen name on which the campaign should be shown.
@Deprecated('This field is deprecated and will be removed in future releases. Use [screenNames] instead')
String? screenName;
/// Context for which the campaign should be shown.
List context;
/// Screen Names on which the campaign can be shown.
/// @since 10.0.0
List screenNames;
}
```
# Handling Orientation Change
This is only for the Android platform
Starting SDK version `4.1.0` in-apps are supported in both portrait and landscape modes.\
SDK has to be notified when the device orientation changes for SDK to handle in-app display.
There are two ways to do it:
1. Add the API call in the Android native part of your app
2. Call MoEngage plugin's `onOrientationChanged()`
## Add the API call in the Android native part of your app
Notify the SDK when **onConfigurationChanged()** API callback is received in your App's Activity class.
```Dart Dart theme={null}
public class MainActivity extends FlutterActivity {
...
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
MoEFlutterHelper.getInstance().onConfigurationChanged();
...
}
...
}
```
## Call MoEngage plugin's orientation change API
Call the below API to notify SDK of the orientation change.
```Dart Dart theme={null}
_moengagePlugin.onOrientationChanged();
```
# Getting Started with Flutter SDK
Source: https://moengage.com/docs/developer-guide/flutter-sdk/overview/getting-started-with-flutter-sdk
Get started with the MoEngage Flutter SDK for push notifications, in-app messages, and event tracking.
# Overview
MoEngage’s Flutter SDK helps you integrate MoEngage into iOS and Android applications built with Flutter. It allows you to work with push notifications, in-app messages, cards, user attributes, events, and much more.
To see the sample code, take a look at the [GitHub repository](/developer-guide/flutter-sdk/sample-app/flutter-sample-app). This article describes the steps to implement MoEngage features on Flutter.
You can now get notified whenever MoEngage releases a new version of the Flutter SDK. For more information, refer to [Subscribe to MoEngage SDK Releases](/developer-guide/release-notes/subscribe-to-moengage-sdk-releases/subscribe-to-mo-engage-sdk-releases).
# SDK Installation and Initialization
**Step 1: Installation**
To add MoEngage's Flutter SDK to your application, refer to [Installation Methods](/developer-guide/flutter-sdk/sdk-integration/sdk-installation/framework-dependency).
**Step 2: Complete Native Setup**\
The platform-specific native setup guidelines to complete the installation are described in the following articles:
* [Android Setup](/developer-guide/flutter-sdk/sdk-integration/sdk-installation/android)
* [iOS Setup](/developer-guide/flutter-sdk/sdk-integration/sdk-installation/ios)
* [Web Setup](/developer-guide/flutter-sdk/sdk-integration/sdk-installation/framework-dependency)
**Step 3: Framework Initialization**\
Initialize an instance of the MoEngage plugin by calling the [Framework Initialization](/developer-guide/flutter-sdk/sdk-integration/sdk-initialization/framework-initialization) method.
**Step 4: Platform Initialization**\
The platform-specific steps to initialize the SDK and set up the data center are described in the following articles:
* [Android](/developer-guide/flutter-sdk/sdk-integration/sdk-initialization/android-sdk-initialization)
* [iOS](/developer-guide/flutter-sdk/sdk-integration/sdk-initialization/ios-sdk-initialization)
* [Web](/developer-guide/flutter-sdk/sdk-integration/sdk-initialization/web-sdk-initialization)
# Data Tracking
Data tracking allows apps to monitor and analyze user behavior to optimize engagement strategies. It involves tracking various user actions such as login, logout, and event tracking in a way that avoids data corruption. Use the following methods to implement data tracking.
* **Install/Update Differentiation -** To track fresh installs and updates separately, refer to the methods in this [article](/developer-guide/flutter-sdk/data-tracking/install-update-differentiation).
* **Tracking Login, Logout, and Setting Unique ID** - To avoid data corruption, it is crucial to follow the steps outlined in the following articles when handling user login and logout.
* [Tracking Login and set user ID](/developer-guide/flutter-sdk/data-tracking/setting-unique-id-for-sdk-versions-below-920)
* [Tracking Logout](/developer-guide/flutter-sdk/data-tracking/setting-unique-id-for-sdk-versions-below-920)
* [Updating User Attribute Unique ID](/developer-guide/flutter-sdk/data-tracking/setting-unique-id-for-sdk-versions-below-920)\
\
It is essential to have a unique ID for each of your app's users, which can be passed onto MoEngage SDK using setUniqueId(). This unique ID helps to correctly identify a user across multiple installs and platforms to provide a unified view.
Once a user logs out of the app, it's critical to call logout() to initiate the creation of a new user. This step is necessary to ensure that any subsequent activities performed by the new user are not wrongly attributed to the previously logged-in user, which could distort user data.
* **Tracking user attributes** - To set custom attributes available in the user profile, refer to the methods in [this article](/developer-guide/flutter-sdk/data-tracking/tracking-user-attributes).
* **Tracking Events** - Tracking events is how you record user actions, along with any properties that describe the action. To track custom events, refer to the methods in [this article](/developer-guide/flutter-sdk/data-tracking/tracking-events).
* **Enable Advertising Identifier Tracking (Android only)** - MoEngage SDK uses a Device ID (persistent device identifier) to uniquely identify the user to deliver personalized content and associates this to AAID if allowed by the app. This allows accurate identification of reachable devices for sending push notifications and tracking re-installs for users over time. To enable tracking of the AAID after obtaining the user’s consent, refer to the methods in [this article](/developer-guide/android-sdk/data-tracking/enable-advertising-identifier-tracking).
# Push Notifications
Push campaigns target users through notifications for your app or website. Depending on the desired capability, follow the integration steps listed below to integrate push notifications.
## Basic Setup - Android
Follow the basic setup outlined in this section to enable push notifications on an Android device using MoEngage.
* **FCM Setup on MoEngage Dashboard -** FCM Authentication is the method to enable sending push notifications to your app installed on Android devices. Use the methods mentioned in [this article](/developer-guide/android-sdk/push/basic/fcm-authentication) to authenticate MoEngage to access Firebase services.
* **Adding metadata for push notification -** Set the small icon and large icon drawable and other options to handle push notifications using the methods available in [this article](/developer-guide/android-sdk/push/basic/push-configuration).
* **Android Notification Runtime Permissions** - When the application is running on Android 13 to show notifications to the user, applications would need to request the user for notification permission. Refer to the methods available in [this article](/developer-guide/flutter-sdk/push/basic/android-notification-runtime-permissions) to handle permission requests.
* **Push Registration and Receiving** - To use Push Notification in your Flutter application, you need to configure Firebase. Depending on your requirements, refer to one of the below methods to enable Push Registration and Receiving.
**Add messaging service**\
You must add the messaging service to the Manifest file for MoEngage SDK to show the notifications. Refer to this document [here](/developer-guide/android-sdk/push/basic/push-token-registration-and-display).
**Callback on token registration(optional)**\
To get an optional callback whenever a new token is registered or the token is refreshed, refer to the method [here](/developer-guide/android-sdk/push/basic/push-token-registration-and-display).
**Notification Clicked Callback**
To receive a callback whenever a push is clicked and for custom handling redirection, use the method in [this article](/developer-guide/android-sdk/push/advanced/callbacks-and-customisation).
**How to opt out of MoEngage Registration?**\
The MoEngage SDK attempts to register for a push token; since your application is handling push, you need to opt out of SDK's token registration using the method in [this article](/developer-guide/android-sdk/push/basic/push-token-registration-and-display).
**Pass the Push Token To MoEngage SDK** - After receiving the push token from FCM, use the method in [this article](/developer-guide/android-sdk/push/basic/push-token-registration-and-display) to pass the Push Token to the MoEngage SDK to set it in the MoEngage platform.
**Passing the Push payload to the MoEngage SDK** - After receiving the push payload on the app, use the method in [this article](/developer-guide/android-sdk/push/basic/push-token-registration-and-display) to send out push notifications to the device.
We recommend you use the Android native APIs to pass the push payload to the MoEngage SDK instead of the Flutter/Dart APIs. Flutter Engine might not get initialized if the application is in the killed state, which will lead to poor push reachability or delivery.
* [Pass the Push Token To MoEngage SDK](/developer-guide/flutter-sdk/push/basic/android-push-configuration#passing-push-token)
* [Pass the Push payload to the MoEngage SDK](/developer-guide/flutter-sdk/push/basic/android-push-configuration#basic-setup)
* [Callbacks and customizations](/developer-guide/flutter-sdk/push/basic/android-push-configuration#customizing-push-notification)
**Notification Clicked Callback -** MoEngage's Flutter plugin optionally provides a callback on push clicks with the method in [this article](/developer-guide/flutter-sdk/push/basic/push-callback).
## Basic Setup - iOS
Follow the basic setup outlined in this section to enable push notifications on an iOS device using MoEngage.
* **APNS Setup on MoEngage dashboard**\
APNS Authentication is the method to enable sending push notifications to your app installed on Android devices. You can use any of these options to set up APNS on the MoEngage dashboard.
* [APNS Authentication Key (recommended)](/developer-guide/ios-sdk/push/basic/apns-authentication-key)
* [APNS Certificate/PEM file](/developer-guide/ios-sdk/push/basic/apns-certificate-pem-file-legacy)
* **App target implementation** - Make changes to your app target to enable notifications by following the steps mentioned in [this article](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial).
* **Provide the App Group ID to SDK**- Pass the App Group ID to MoEngage SDK using the method in [this article](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial).
* **Push Registration and Receiving**
In MoEngage SDK, we have now swizzled the AppDelegate Class to get all the callbacks related to Push Notifications, and we have also applied the method swizzling for UserNotificationCenter delegate methods. This is to ease the integration of the SDK.
**Registering for Push notification**\
Follow the steps in [this article](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial) to initiate registration.
**Callback methods on receiving Push Notification**\
The callback the app would receive on receiving the push notifications is mentioned in [this article](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial). With Swizzling enabled, no additional configuration is required.
In case you do not prefer to use swizzling, you can disable the same by adding the flag MoEngageAppDelegateProxyEnabled in the app’s Info.plist file and setting it to Boolean value NO, and follow the steps below.
**Registering for Push notification -** Follow the steps in [this article](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial) to initiate registration and the steps in [this section](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial) to call the respective MoEngage SDK methods for registration callbacks.
**Callback methods on receiving Push Notification -** With Swizzling disabled, include calls to MoEngage SDK methods on receiving notification callbacks, as described in [this article](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial).
* **Disable Badge Reset**\
By default, the SDK sets the notification badge count to 0 on every app launch, and this also clears the notifications in the device notification center. If you would like to keep the notifications even after the App Launch, then disable badge reset by calling the method in [this section](/developer-guide/ios-sdk/push/advanced/custom-notification-handling).
* **Custom Sound for Notification**\
To optionally set a custom tone for notifications of your app, you can follow the method in [this section](/developer-guide/ios-sdk/push/advanced/custom-notification-handling).
* **Notification Service Extension Target Implementation**\
The notification service extension allows MoEngage SDK to customize the content of a notification before the system delivers it to the user. This gives you the capability to add media in notifications, support inbox, update badge count on notifications delivered, and track notification impressions. Follow the steps in [this article](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial) to set up the notification service extension.
* **Notification Actions**\
Actionable notifications let you add custom action buttons to the standard iOS push notifications. Follow the steps mentioned in [this article](/developer-guide/ios-sdk/push/basic/actionable-notifications) to add custom actions to your notifications and track the actions performed on notifications
This completes your basic setup for push notifications in Flutter.
## Push Templates
Push templates enable you to craft beautiful notifications within minutes without any coding. For information on how to create campaigns with templates in the dashboard, refer to [this article](/developer-guide/ios-sdk/push/optional/push-templates).
To enable push templates, please follow the platform-specific documentation
* [Android](/developer-guide/android-sdk/push/optional/push-templates)
* [iOS](/developer-guide/ios-sdk/push/optional/push-templates)
## Push Amp+
A significant percentage of notifications, around 25-30%, is not delivered due to issues with original equipment manufacturer (OEM) devices. To combat this problem and improve retention rates, MoEngage developed Push Amplification+ to reach customers who may not have received notifications. MoEngage has also partnered with OEMs to address these issues and ensure that notifications are reliably delivered. To minimize any additional burden on your application, we have developed individual software development kits (SDKs) for each OEM. You can choose and integrate the relevant SDK based on your application's specific needs and device share. Refer to the documentation for each OEM-specific service and integrate the appropriate ones into your application for optimal push notification delivery.
### Supported Integrations
* [HMS Push Kit](/developer-guide/android-sdk/push/optional/push-amp-plus/configuring-hms-push-kit)
## Push Amplification
Push Amplification works as a fallback mechanism when Firebase Cloud Messaging (FCM) fails to deliver Push Notifications. Follow the method here to set up [Push Amplification](/developer-guide/android-sdk/push/optional/push-amplification).
## Notification Center
The Notification Center shows your push notification history, allowing you to provide an option for the end-user to scroll back and see what they have missed. MoEngage provides out-of-box inbox support with a fully customizable default UI and also provides an option to build your own Notification Center. For more information, refer to [Notification Center](/developer-guide/flutter-sdk/push/optional/notification-triggered).
## Location Triggered Notifications
Location-triggered notifications allow you to send messages to your audience that are triggered on the user’s entry, exit, and dwell in defined Geo Fences. Follow the method in [this article](/developer-guide/flutter-sdk/push/optional/location-triggered) to set up location triggers.
## Device triggered notifications
Device-triggered notifications allow you to send messages to your audience that are triggered locally based on any activity on a device. Offline delivery of messages is supported as well.
To enable device-triggered notifications, use the following platform-specific articles:
* [Android](/developer-guide/android-sdk/push/optional/device-triggered)
* [iOS](/developer-guide/ios-sdk/push/optional/real-time-triggers)
## Advanced Use Cases in Android
For advanced use cases, the following options are available:
* **Non-MoEngage Payload** - To get an optional callback in case a push payload is received for any other server apart from the MoEngage Platform, refer to the method [here](/developer-guide/android-sdk/push/basic/push-token-registration-and-display).
* **Callbacks and customizations** - The MoEngage SDK allows the client application to optionally customize the notification display and extend/customize the behavior of the notification. Refer to the methods mentioned [here](/developer-guide/android-sdk/push/advanced/callbacks-and-customisation) to access the features, such as:
* Control whether a notification is shown to the user or not
* Notification Received Callback
* Notification Clicked Callback
* Notification Cleared Callback
* Custom Action on Action Button Click
* **Push Display Handled by Application(Android)** - When the application needs to handle the push display on the client side, you can track notification impressions and cases using the methods described in [this article](/developer-guide/android-sdk/push/advanced/push-display-handled-by-application).
# In-App
MoEngage In-App Campaigns target users by showing a message while the user is using your app. They are effective in providing contextual information and help to cross-sell/up-sell on desired screens of your app or/and on desired actions performed by the user in your app.
Basic Setup - To install In-app notifications in Flutter, use the following platform-specific methods:
* [Android](/developer-guide/flutter-sdk/in-app-messages/inapp-nativ)
* iOS (installation is not required for iOS)
## Displaying In-App Messages
You can either show In-app messages using MoEngage’s out-of-the-box UI, or you can use Self-handled In-apps to build the UI of the application using the payload from MoEngage.
**Show In-app**\
Call the method [here](/developer-guide/flutter-sdk/in-app-messages/inapp-nativ) to show an inApp campaign on a screen. In-app pop-ups will only show up where showInApp() method is called.
**Handling Orientation Change**\
In-apps are supported in both portrait and landscape modes. There are two ways to do it:
* [Add the API call in the Android native part of your app](/developer-guide/flutter-sdk/in-app-messages/inapp-nativ)
* [Call MoEngage plugin's onOrientationChanged()](/developer-guide/flutter-sdk/in-app-messages/inapp-nativ)
**Self-handled In-apps**\
Self-handled In Apps are messages that are delivered by the SDK to the application, and the application builds the UI using the delivered payload by the SDK. To get the self-handled in-app, refer to [this article](/developer-guide/flutter-sdk/in-app-messages/inapp-nativ).
* [Getting self-handled campaigns](/developer-guide/flutter-sdk/in-app-messages/inapp-nativ)
* [Tracking Statistics for Self-Handled In-Apps](/developer-guide/android-sdk/in-app-messages/in-app-nativ#tracking-statistics-for-self-handled-in-apps)
## InApp Callbacks
Optionally, we provide callbacks for in-app shown, in-app clicked, in-app dismissed, and self-handled in-app available events. You can register for the callbacks using the methods in [this article.](/developer-guide/flutter-sdk/in-app-messages/inapp-nativ#inapp-callbacks)
# Cards
MoEngage Cards campaigns help you interact with your users with persistent and non-intrusive messages in your customer's journey. Self-handled cards are message payloads that are delivered by the SDK to the application, and the application builds the UI using the delivered payload.
Refer to [this article](/developer-guide/flutter-sdk/cards/self-handled-cards) to implement self-handled cards on Flutter.
Cards are currently not supported for web platform.
# Android Notification Runtime Permissions
Source: https://moengage.com/docs/developer-guide/flutter-sdk/push/basic/android-notification-runtime-permissions
Handle Android 13 notification runtime permissions in your Flutter app using the MoEngage SDK.
Android 13 (API level 33) and higher supports [runtime permission](https://developer.android.com/guide/topics/permissions/overview#runtime) for sending [non-exempt](https://developer.android.com/develop/ui/views/notifications/notification-permission#exemptions)(including Foreground Services (FGS)) notifications from an app [POST\_NOTIFICATIONS](https://developer.android.com/reference/android/Manifest.permission#POST_NOTIFICATIONS). This change helps users focus on the notifications that are most important to them.
Refer to the [official documentation](https://developer.android.com/develop/ui/views/notifications/notification-permission) for more details.
The below-mentioned APIs are supported starting MoEngage core Android SDK version **12.3.01**
When an application runs on Android 13 and wants to show notifications to the user, it must request the user's notification permission. You have two options: let MoEngage handle permissions for you or handle the notification permission with your code.
* MoEngage handles Notification permission.
* You just have to call a single line of code mentioned on this page.
* You maintain the notification permission logic.
* Notify MoEngage SDK if permission to push notifications is granted.
We recommend you let MoEngage handle push notification permissions.
## Let MoEngage SDK handle Notification permission
MoEngage SDK provides helper APIs to show the permission request to the end-user or navigate the user to the settings screen for enabling notifications.
Use the below API to show the permission request dialog to the user.
When using the below API SDK automatically tracks the response, sets up the required notification channel, etc, mentioned above.
```dart Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
final MoEngageFlutter _moengagePlugin = MoEngageFlutter(YOUR_Workspace_ID);
_moengagePlugin.initialise();
_moengagePlugin.requestPushPermissionAndroid();
```
## Notify SDK of permission result
Once the application requests the user for notification permission notify the SDK of the user response using the below API. *If you are letting MoEngage SDK handle the notification permissions, you should ignore this step.*
```dart Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
final MoEngageFlutter _moengagePlugin = MoEngageFlutter(YOUR_Workspace_ID);
_moengagePlugin.initialise();
_moengagePlugin.pushPermissionResponseAndroid(isGranted);
```
## Navigate to Notification Settings (situational/optional)
Use the below API to show navigate the user to the Notification Settings for the application on the device.
*Note*: Below Android 8(API level 26) the user is directed to the Application Info screen of your application.
```dart Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
final MoEngageFlutter _moengagePlugin = MoEngageFlutter(YOUR_Workspace_ID);
_moengagePlugin.initialise();
_moengagePlugin.navigateToSettingsAndroid();
```
The update push permission count API is supported starting version **12.6.00.**
## Update the Permission request count
Once the application requests the user for notification permission, update the SDK of the request attempts.
### Why does the SDK require permission attempt count?
SDK requires the attempt count to accurately track the number of times the permission request was attempted. If the user denies the permission request twice the application/SDK cannot request permission further i.e. if we request permission it would be automatically denied without the user seeing the request dialog. As an SDK we cannot be sure of the number of times the user has denied the permission we try to optimize the calls to request permission based on the attempt count.
```Dart Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
final MoEngageFlutter _moengagePlugin = MoEngageFlutter(YOUR_Workspace_ID);
_moengagePlugin.initialise();
_moengagePlugin.updatePushPermissionRequestCountAndroid(requestCount);
```
# Android Push Configuration
Source: https://moengage.com/docs/developer-guide/flutter-sdk/push/basic/android-push-configuration
Configure push notifications for Android in your Flutter app including FCM setup and permissions.
# Basic setup
Follow the basic setup outlined in this section to enable push notifications on an Android device using MoEngage.
* **FCM Setup on MoEngage Dashboard -** FCM Authentication is the method to enable sending push notifications to your app installed on Android devices. Use the methods mentioned in [this article](/developer-guide/android-sdk/push/basic/fcm-authentication) to authenticate MoEngage to access Firebase services.
* **Adding metadata for push notification -** Set the small icon and large icon drawable and other options to handle push notifications using the methods available in [this article](/developer-guide/android-sdk/push/basic/push-configuration).
* **Android Notification Runtime Permissions** - When the application is running on Android 13 to show notifications to the user, applications would need to request the user for notification permission. Refer to the methods available in [this article](/developer-guide/flutter-sdk/push/basic/android-notification-runtime-permissions) to handle permission requests.
* **Push Registration and Receiving** - To use Push Notification in your Flutter application, you need to configure Firebase. Depending on your requirements, refer to one of the below methods to enable Push Registration and Receiving.
**Add messaging service**
Starting from version [10.4.0](https://github.com/moengage/Flutter-SDK/releases/tag/moengage_flutter-v10.4.0), the SDK automatically adds the Firebase service declaration to `AndroidManifest.xml`. The file `MoEFireBaseMessagingService` is declared with low priority (android:priority="-1") in `AndroidManifest.xml`. file to prevent conflicts.
| Integration Scenario | System Behavior | Action Required |
| ----------------------- | --------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| MoEngage Only | The SDK automatically handles push payloads and token updates using the built-in service. | Update & Build: Ensure you are on the latest SDK version and run `flutter clean` before building. No manifest changes are needed. |
| Multiple Push Providers | The Android system prioritizes your messaging service over the `MoEFireBaseMessagingService`. | Pass Data Manually: In your custom `FirebaseMessagingService`, intercept the payload and token. [Pass them to the MoEngage SDK](/developer-guide/android-sdk/push/basic/push-token-registration-and-display) APIs if the data originates from the MoEngage platform. |
For versions below 10.4.0, You must add the `MoEFireBaseMessagingService` to the `AndroidManifest.xml` file for MoEngage SDK to show the notifications. Refer [here](/developer-guide/android-sdk/push/basic/push-token-registration-and-display).
**Callback on token registration(optional)**\
To get an optional callback whenever a new token is registered or the token is refreshed, refer to the method [here](/developer-guide/android-sdk/push/basic/push-token-registration-and-display#token-callback-access-to-push-token-optional).
**Notification Clicked Callback**\
To receive a callback whenever a push is clicked and for custom handling redirection, use the method in [this article](/developer-guide/android-sdk/push/advanced/callbacks-and-customisation#notification-clicked-callback).
**How to opt out of MoEngage Registration?**\
The MoEngage SDK attempts to register for a push token; since your application handles push, you need to opt out of SDK's token registration using the method in [this article](/developer-guide/android-sdk/push/basic/push-token-registration-and-display#how-to-opt-out-of-moengage-push-token-registration).
**Pass the Push Token To MoEngage SDK** - After receiving the push token from FCM, use the method in [this article](/developer-guide/android-sdk/push/basic/push-token-registration-and-display#how-to-opt-out-of-moengage-push-token-registration) to pass the Push Token to the MoEngage SDK to set it in the MoEngage platform.
**Passing the Push payload to the MoEngage SDK** - After receiving the push payload on the app, use the method in [this article](/developer-guide/android-sdk/push/basic/push-token-registration-and-display#passing-the-push-payload-to-the-moengage-sdk) to send out push notifications to the device.
We recommend you use the Android native APIs to pass the push payload to the MoEngage SDK instead of the Flutter/Dart APIs. Flutter Engine might not get initialized if the application is in the killed state, which will lead to poor push reachability or delivery.
* [Pass the Push Token To MoEngage SDK](/developer-guide/flutter-sdk/push/basic/android-push-configuration#passing-push-token)
* [Pass the Push payload to the MoEngage SDK](/developer-guide/flutter-sdk/push/basic/android-push-configuration#basic-setup)
* [Callbacks and customizations](/developer-guide/flutter-sdk/push/basic/android-push-configuration#customizing-push-notification)
**Notification Clicked Callback -** MoEngage's Flutter plugin optionally provides a callback on push clicks with the method in [this article](/developer-guide/flutter-sdk/push/basic/push-callback).
# Flutter APIs for Push
You can skip this section completely if you let MoEngage handle push token registration and display or use Android Native methods to pass tokens and payload to MoEngage SDKs.
Read on if you want to use Flutter APIs of MoEngage SDK to pass tokens and payload to MoEngage SDKs.
We recommend you use the Android native APIs to pass the push payload to the MoEngage SDK instead of the Flutter/Dart APIs. Flutter Engine might not get initialized if the application is in the killed state, which will lead to poor push reachability or delivery.
## Passing Push Token
```auto Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
final MoEngageFlutter _moengagePlugin = MoEngageFlutter(YOUR_APP_ID);
_moengagePlugin.initialise();
_moengagePlugin.passFCMPushToken();
```
## Customizing Push notification
If required the application can customize the behavior of notifications by using Native Android code (Java/Kotlin). To learn more about the customization refer to the [Advanced Push Configuration](/developer-guide/android-sdk/push/advanced/callbacks-and-customisation) documentation.Instead of extending ***PushMessageListener*** as mentioned in the above document extend ***PluginPushCallback.***
Refer to the below documentation for Push Amp+, Push Templates, and Geofence.
* [Push Amplification](/developer-guide/android-sdk/push/optional/push-amplification)
* [Push Amp Plus](/developer-guide/android-sdk/push/optional/push-amp-plus/push-amp-plus-integration)
* [Push Templates](/developer-guide/android-sdk/push/optional/push-templates)
* [GeoFence Push](/developer-guide/android-sdk/push/optional/location-triggered)
# iOS Push Configuration
Source: https://moengage.com/docs/developer-guide/flutter-sdk/push/basic/ios-push-configuration
Configure iOS push notifications in your Flutter app using APNs authentication keys or certificates.
# Configuring Push in iOS
Following are the two ways to configure Push Notification
## APNS Authentication Key :
To send push notifications to iOS users, it is required to generate the APNs Auth Key file for your application and upload it to the MoEngage dashboard. Refer to the [link](/developer-guide/ios-sdk/push/basic/apns-authentication-key) to generate Auth key.
## APNS Certificate
First, you must create an APNS certificate and upload it to the dashboard to send push notifications on iOS. Follow the steps below to do that:
* [Create an APNS certificate](/developer-guide/ios-sdk/push/basic/apns-certificate-pem-file-legacy)
* [Convert the resultant certificate to .pem format](/developer-guide/ios-sdk/push/basic/apns-certificate-pem-file-legacy)
* [Upload .pem file to MoEngage Dashboard](/developer-guide/ios-sdk/push/basic/apns-certificate-pem-file-legacy)
Follow the links on each step to complete it.
## Project Capability Changes
Once the APNS Certificate is uploaded, enable Push Entitlement in the Xcode project. For that select your app target, then go to Capabilities. Here enable the Push Notifications capability for your app. Also, we make use of silent pushes to track uninstalls. For tracking uninstalls of all the users, enable Remote Notification background mode in the app's capabilities as shown below:
## Push Registration
After this, you will have to register for push notification by using the **registerForPushNotification()** method of the plugin, as shown below:
```auto Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
final MoEngageFlutter _moengagePlugin = MoEngageFlutter(YOUR_APP_ID);
_moengagePlugin.initialise();
_moengagePlugin.registerForPushNotification();
```
## Provisional Push Registration:
This feature is supported from version ***9.0.0*** of the plugin.
To register for provisional push notification, call [***registerForProvisionalPush()***](https://pub.dev/documentation/moengage_flutter/latest/moengage_flutter/MoEngageFlutter/registerForProvisionalPush.html) API of the plugin as shown below.
```auto Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
MoEngageFlutter _moengagePlugin = MoEngageFlutter(YOUR_APP_ID);
_moengagePlugin.initialise();
_moengagePlugin.registerForProvisionalPush();
```
## Rich Push and Templates Support
Please refer to the Native iOS SDK docs for supporting Rich Push(images/videos/audio in the notification) and Templates in the app:
* [Rich Push](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial)
* [Push Templates](/developer-guide/ios-sdk/push/optional/push-templates)
# Push Callback
Source: https://moengage.com/docs/developer-guide/flutter-sdk/push/basic/push-callback
Register for push click callbacks in your Flutter app to handle notification interactions with MoEngage.
## Push Click Callback
MoEngage's Flutter plugin optionally provides a callback on push clicks.
To register for the callback, call the **setPushClickCallbackHandler()** on the **MoEngageFlutter** object in your dart code.\
This API takes a method as input with whose **typedef** is **PushClickCallbackHandler(PushCampaignData data).**
```Dart Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
void _onPushClick(PushCampaignData message) {
print("_onPushClick(): Push click callback from native to flutter. Payload " +
message.toString());
}
final MoEngageFlutter _moengagePlugin = MoEngageFlutter(YOUR_Workspace_ID);
_moengagePlugin.setPushClickCallbackHandler(_onPushClick);
```
Make sure this callback is set as soon as the application is initialized. Preferably in the **initState()** of your application widget.
Make sure the callback is set before calling the initialize **()** of the MoEngage Plugin.
## Payload
NotificationPayload received in the callback is an `PushCampaignData` instance with the following definition:
```Dart Dart theme={null}
class PushCampaignData {
Platforms platform;
AccountMeta accountMeta;
PushCampaign data;
}
```
**platform** - Native platform from which callback is triggered. Possible values - **android**, **ios**. **data**- **PushCampaignData** object
```Dart Dart theme={null}
class PushCampaign {
bool isDefaultAction;
Map clickedAction;
Map payload;
}
```
**isDefaultAction** - This key is present only for the Android Platform. It's a boolean value indicating if the user clicked on the default content or not. true if the user clicks on the default content else false.
**clickedAction**- Action to be performed on notification click.
Payload Structure for **clickedAction** Map
```json JSON theme={null}
{
"clickedAction": {
"type": "navigation/customAction",
"payload": {
"type": "screenName/deepLink/richLanding",
"value": "",
"kvPair": {
"key1": "value1",
"key2": "value2",
...
}
}
}
}
```
**clickedAction.type**- Type of click action. Possible values **navigation** and **customAction**. Currently, **customAction** is supported only on Android.\
**clickAction.payload** - Action payload for the clicked action.\
**clickedAction.payload.type** - Type of navigation action defined. Possible values **screenName**, **deepLink**, and **richLanding**.
Currently, in the case of iOS, rich landing and deep-link URLs are processed internally by the SDK and not passed in this callback; therefore possible value in the case of iOS is only **screenName**.\
**clickAction.value** - value entered for navigation action or custom payload.\
**clickAction.kvPair** - Custom key-value pair entered on the MoEngage Platform.\
**payload** - Complete campaign payload.
## Android Payload
If the user clicks on the default content of the notification, the key-value pair and campaign payload can be found inside the **payload** key. If the user clicks on the action button or a push template action, the action payload would be found inside **clickedAction**.\
You can use the **isDefaultAction** key to check whether the user clicked on the default content and then parse the payload accordingly.
## iOS Payload
In the case of iOS, you would always receive the key-value pairs for clicked action in the **clickedAction** property. Refer to this [link](/developer-guide/ios-sdk/push/advanced/custom-notification-handling) to knowing the iOS notification payload structure.
## Self-Handled Push Click Android (Optional)
By default, when the user clicks on a notification the SDK redirects the user to the defined Activity and passes the callback to the Application to load the specific flutter component.
When the application is in the foreground it might seem like the application is reloading and not a very good user experience. You might just want to navigate the user to the specific flutter component. In order to handle the push click by yourself when the Application is in the foreground follow the below steps.
While initializing the Flutter Plugin, enable foreground click callback in the ***PushConfig*** object.
```Dart Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
...
final MoEngageFlutter _moengagePlugin = MoEngageFlutter(
"YOUR_Workspace_ID",
moEInitConfig: MoEInitConfig(
pushConfig: PushConfig(
shouldDeliverCallbackOnForegroundClick: true)
)
);
```
**Android Configuration**
Enable the **lifecycleAwareCallback** flag in the SDK initialization in the Application class as shown below.
```kotlin Kotlin wrap theme={null}
val moEngage = MoEngage.Builder(this, "YOUR_Workspace_ID")
MoEInitializer.initialiseDefaultInstance(
context = applicationContext,
builder = moEngage,
lifecycleAwareCallbackEnabled = true)
```
```java Java wrap theme={null}
MoEngage.Builder moEngage = new MoEngage.Builder(this, "YOUR_Workspace_ID");
MoEInitializer.INSTANCE.initializeDefaultInstance(getApplicationContext(), moEngage, true);
```
You must call the ***initialize()*** whenever the Application comes to the foreground by adding **WidgetsBindingObserver** in the root widget of your app.
So you would need to call **initialise()** in two places, one in **initState()** as usual and another time in **didChangeAppLifecycleState()** in the root widget of your app.
```Dart Dart wrap theme={null}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State with WidgetsBindingObserver {
final MoEngageFlutter _moengagePlugin = MoEngageFlutter("");
@override
void initState() {
super.initState();
_moengagePlugin.initialise(); // Initialise MoEngage SDK
WidgetsBinding.instance.addObserver(this);
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
if (state == AppLifecycleState.resumed) {
_moengagePlugin.initialise(); //Call initialise() again in on App Resume State
}
}
}
```
Handle the redirection as shown below:
```Dart Dart wrap theme={null}
void _onPushClick(PushCampaignData message) {
if (message.data.selfHandledPushRedirection) {
// Handle Redirection for Deeplinking or ScreenName
} else {
// Callback After SDK Handled Redirection
}
}
```
Add the below Activity to your AndroidManifest.xml under **application** tag.
```xml XML wrap theme={null}
```
# Location Triggered
Source: https://moengage.com/docs/developer-guide/flutter-sdk/push/optional/location-triggered
Add location-triggered geofence push notifications to your Flutter app using the MoEngage plugin.

# Installation
To add MoEngage Geofence SDK to your application, edit the application's **pubspec.yaml** file and add the below dependency to it:
```pubspec.yaml pubspec.yaml theme={null}
dependencies:
moengage_geofence: $latestVersion
```
***\$latestVersion*** refers to the latest version of the plugin.
Post including the dependency, run ***flutter pub get*** command in the terminal to install the dependency.
After installing the plugin, use the following platform-specific configuration.
This plugin is dependent on **moengage\_flutter** plugin. Make sure you have installed the **moengage\_flutter** plugin as well. Refer to the [doc](/developer-guide/flutter-sdk/sdk-integration/sdk-installation/framework-dependency) for the same.
For location-triggered push to work, ensure your Application has:
* Location permission
* Play Services Location Library
* The device's location should be enabled
## Android Installation
Starting *****moengage\_geofence5.0.0***** the plugin includes the native dependency, so there is no need to include any additional native dependency.
## iOS Installation
In the case of iOS, the native dependency is part of the Geofence flutter SDK itself, so there is no need to include any additional dependency for supporting Geofence.
## Configuration
### Start Geofence Monitoring
After integrating the geofence package call **startGeofenceMonitoring()** method to initiate the geofence module, this will fetch the geofences around the current location of the user. Please take a look at the [iOS doc](/developer-guide/ios-sdk/push/optional/location-triggered) and [Android doc](/developer-guide/android-sdk/push/optional/location-triggered) for more information on Geofence. By default, the geofence feature is not enabled. You need to call the \*\*startGeofenceMonitoring()\*\*to receive location-triggered push messages.
```Dart Dart theme={null}
import 'package:moengage_geofence/moengage_geofence.dart';
final MoEngageGeofence _moEngageGeofence = MoEngageGeofence(YOUR_Workspace_ID);
@override
void initState() {
super.initState();
initPlatformState(); ///Starts Geofence Monitoring
_moEngageGeofence.startGeofenceMonitoring();
}
```
### Stop Geofence Monitoring
If you want to stop the geofence monitoring or feature use the **stopGeofenceMonitoring()** API. This API will remove the existing geofences.
```Dart Dart theme={null}
import 'package:moengage_geofence/moengage_geofence.dart';
final MoEngageGeofence _moEngageGeofence = MoEngageGeofence(YOUR_Workspace_ID);
@override
void initState() {
super.initState();
initPlatformState(); ///Stops Geofence Monitoring
_moEngageGeofence.stopGeofenceMonitoring();
}
```
# Notification Center
Source: https://moengage.com/docs/developer-guide/flutter-sdk/push/optional/notification-center
Add a notification center inbox to your Flutter app using the MoEngage inbox plugin.

# Installation
To add the MoEngage Inbox SDK to your application, edit your application's **pubspec.yaml** file and add the below dependency to it:
```pubspec.yaml pubspec.yaml theme={null}
dependencies:
moengage_inbox: $latestVersion
```
Run flutter packages get to install the SDK.
This plugin is dependent on **moengage\_flutter** plugin. Make sure you have installed the **moengage\_flutter** plugin as well. Refer to the [doc](/developer-guide/flutter-sdk/sdk-integration/sdk-installation/framework-dependency) for the same.
## Android Installation
Once you install the Flutter Plugin add MoEngage's native Android SDK dependency to the Android project of your application.
Navigate to **android/app/build.gradle**. Add the MoEngage Android SDK's dependency in the **dependencies** block.
```json build.gradle wrap theme={null}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation("com.moengage:inbox-core:$sdkVersion")
}
```
where **\$sdkVersion** should be replaced by the latest version of the MoEngage SDK.
## iOS Installation
In the case of iOS, the native dependency is part of the core SDK itself, so there is no need to include any additional dependency for supporting Notification Center.
Make sure to configure [AppGroup ID in App Target](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial) and Set up [Notification Service Extension](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial#test-notification-delivery-and-display) in your iOS Project, for the SDK to save the received notifications.
# Fetch Messages
To fetch all the inbox messages use **fetchAllMessages()** method as shown below, where you would get an instance of **InboxData**.
```Dart Dart theme={null}
import 'package:moengage_inbox/moengage_inbox.dart';
MoEngageInbox _moEngageInbox = MoEngageInbox(YOUR_APP_ID);
InboxData data = await _moEngageInbox.fetchAllMessages();
```
## InboxData Payload
InboxData will be received in the below format:
```Dart Dart theme={null}
class InboxData {
/// Native platform from which the callback was triggered.
String platform;
/// List of [InboxMessage]
List messages;
}
class InboxMessage {
/// internal identifier used by the SDK for storage.
int id;
/// Unique identifier for a message.
String campaignId;
/// Text content of the message. Instance of [TextContent]
TextContent textContent;
/// true if the message has been clicked by the user else false
bool isClicked;
/// Media content associated with the message.
Media? media;
/// List of actions to be executed on click.
List action;
/// Tag associated to the message.
String tag;
/// The time in which the message was received on the device.
///
/// Format - ISO-8601 yyyy-MM-dd'T'HH:mm:ss'Z'
String receivedTime;
/// The time at which the message expiry.
///
/// Format - ISO-8601 yyyy-MM-dd'T'HH:mm:ss'Z'
String expiry;
/// Complete message payload.
Map payload;
/// A key representing the group to which the inbox message belongs.
/// @since 9.0.0
String groupKey;
/// Notification Replacement Id.
/// @since 9.0.0
String notificationId;
/// The timestamp indicating when the message was sent.
///
/// Format - ISO-8601 yyyy-MM-dd'T'HH:mm:ss'Z'
/// @since 9.0.0
String sentTime;
}
class TextContent {
/// Title string for the inbox message.
String title;
/// Message string for the inbox message.
String message;
/// Summary string for the inbox message.
///
/// Note: This is present for Android Platform.
String summary;
/// Subtitle string for the inbox message.
///
/// Note: This is present only for the iOS Platform.
String subtitle;
}
class Media {
/// Content type of the Media.
MediaType mediaType;
/// Url for the media content. Generally a http(s) url.
String url;
/// Defines the accessibility properties for the media model
/// @since 9.0.0
AccessibilityData? accessibilityData;
}
class AccessibilityData {
/// Text for the AccessibilityData
String? text;
/// Hint for the AccessibilityData. Applicable only for iOS Platform
String? hint;
}
class Action {
/// ActionType - navigation
ActionType actionType;
}
class NavigationAction extends Action {
///navigation type deepLink/richLanding/screenName
NavigationType navigationType;
String value;
Map kvPair;
}
```
# Get Unclicked Message Count
To obtain the unclicked messages count from the Inbox use **getUnclickedCount()** method as shown below:
```Dart Dart theme={null}
MoEngageInbox _moEngageInbox = MoEngageInbox(YOUR_APP_ID);
int count = await _moEngageInbox.getUnClickedCount();
```
## Track Message Clicks:
To track clicks on the messages inside your Inbox use **trackMessageClicked()** method as shown below:
```Dart Dart theme={null}
MoEngageInbox _moEngageInbox = MoEngageInbox(YOUR_APP_D);
_moEngageInbox.trackMessageClicked(message); //Pass the instance of InboxMessage here
```
## Delete Message:
To delete a particular message from the list of messages use **deleteMessage()** method as shown below:
```Dart Dart theme={null}
MoEngageInbox _moEngageInbox = MoEngageInbox(YOUR_APP_ID);
_moEngageInbox.deleteMessage(message); //Pass the instance of InboxMessage here
```
The hybrid framework does not support the MoEngage default notification center. Only the Self-handled Notification center is supported.
# Flutter Sample App
Source: https://moengage.com/docs/developer-guide/flutter-sdk/sample-app/flutter-sample-app
Explore the MoEngage Flutter sample app on GitHub as a reference for integrating the SDK.
The [MoEngage Flutter Sample application](https://github.com/moengage/Flutter-SDK) offers a useful reference point for integrating MoEngage into your Flutter app.
## Next Steps
* [SDK Installation](/developer-guide/flutter-sdk/sdk-integration/sdk-installation/framework-dependency)
* [Framework Initialization](/developer-guide/flutter-sdk/sdk-integration/sdk-initialization/framework-initialization)
# Limitations
Source: https://moengage.com/docs/developer-guide/flutter-sdk/sdk-integration/limitations
Review unsupported features and native integration requirements when using the MoEngage Flutter plugin.
Compared to the Native Android or iOS SDKs there are a certain set of features we either do not support or require native Android or iOS implementation when using our Flutter plugin.
# Features not supported
* Action Buttons in iOS Notifications
# File Based Initialization
Source: https://moengage.com/docs/developer-guide/flutter-sdk/sdk-integration/sdk-initialization/file-based-initialization/file-based-initialization
Configure MoEngage Flutter SDK initialization using native configuration files instead of code.
## Overview
Starting with v10.5.0, the Flutter SDK supports file-based initialization.
To streamline the integration process and minimize initialization errors, MoEngage supports Script-Based Initialization. This approach allows you to manage App IDs and configuration settings directly within native configuration files, keeping them separate from your application logic.
This article outlines how you can use the form-based interface to generate a validated code snippet for initialization and access module-specific configurations.
Alternatively, the SDK can be initialized manually. If you require this approach, please refer to the guide on [Framework Initialization](/developer-guide/flutter-sdk/sdk-integration/sdk-initialization/framework-initialization).
Follow these steps to generate your initialization script:
1. Navigate to the [Initialization Website.](https://app-cdn.moengage.com/sdk/integration/config/index.html)
2. Configure the values based on your application requirements. Refer to the Configuration Parameters tables below:
* [Android](#h_01KBCZFV92B5XTVYSR70KEH5ZE)
* [iOS](#h_01KBCZFV9289RR4PR4XXCZ1NZP)
3. Click **Generate Code** at the bottom of the form.
## Step 1: Android Configuration (XML)
For Android, initialization is handled by placing an XML configuration file in the application's resource directory.
### Android Configuration Reference
Below is the comprehensive list of keys available for `moengage.xml`.
| Category | XML Key Name | Type | Description |
| :----------- | :---------------------------------------------------- | :------- | :---------------------------------------------------------------------------------------------- |
| **Core** | `com_moengage_core_workspace_id` | String | Specifies your App ID. This field is mandatory. |
| | `com_moengage_core_file_based_initialisation_enabled` | Boolean | Set to `true` to enable this feature. |
| | `com_moengage_core_data_center` | Integer | Default: `1`. For more info, refer [Data Center values](#h_01KBCZFV92YVXMQ8KYY9YKMGX0). |
| | `com_moengage_core_environment` | String | Supported values are: `default`, `live`, or `test`. |
| | `com_moengage_core_custom_base_domain` | String | Specifies the base custom proxy domain to route SDK network traffic through your own subdomain. |
| | `com_moengage_core_integration_partner` | String | Specifies the core integration partner. For example, `segment` or `mparticle`. |
| **Push** | `com_moengage_push_notification_small_icon` | Drawable | Resource ID for small icon. |
| | `com_moengage_push_notification_large_icon` | Drawable | Resource ID for large icon. |
| | `com_moengage_push_notification_color` | Color | Notification accent color. |
| | `com_moengage_push_notification_token_retry_interval` | Integer | Retry interval (in seconds) for token registration. |
| | `com_moengage_push_kit_registration_enabled` | Boolean | If `true`, SDK registers for push token. |
| **Logs** | `com_moengage_core_log_level` | Integer | `0` (No Log) to `5` (Verbose). Default: `3`. |
| | `com_moengage_core_log_enabled_for_release_build` | Boolean | If `true`, prints logs in release builds. |
| **Security** | `com_moengage_core_storage_encryption_enabled` | Boolean | Enables local storage encryption. |
| | `com_moengage_core_network_encryption_enabled` | Boolean | Enables payload encryption over the network. |
| **Sync** | `com_moengage_core_periodic_data_sync_enabled` | Boolean | Enables periodic data sync in the foreground. |
| | `com_moengage_core_background_data_sync_enabled` | Boolean | Enables periodic data sync in the background. |
| **In-App** | `com_moengage_inapp_show_in_new_activity_enabled` | Boolean | Required for specific TV/Android setups. |
**Troubleshooting**
If the XML file is missing or the `com_moengage_core_workspace_id` is empty, the SDK will throw a `ConfigurationMismatchError`.
### Add Configuration File
Place the generated file in `android/app/src/main/res/values/`.
\[placedholder for initialization snippet]
## Step 2: iOS Configuration (Info.plist)
For iOS, initialization is handled by adding a configuration dictionary to your `Info.plist`.
### iOS Configuration Reference
Below is the comprehensive list of keys available for the `MoEngage` dictionary.
| Category | Plist Key | Type | Description |
| :----------- | :----------------------------------- | :--------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Core** | `WorkspaceId` | String | Specifies your App ID. It is a Mandatory field. |
| | `IsSdkAutoInitialisationEnabled` | Boolean | Set to `true` to enable SDK auto initialisation. |
| | `DataCenter` | Integer | Specifies the Data Center value. This is a Mandatory field. The default value is *1*. For more info, refer to [Data Center values](#h_01KBCZFV92YVXMQ8KYY9YKMGX0). |
| | `IsTestEnvironment` | String / Boolean | Customer selected option (`true`/`false`). Default value is: `$(SWIFT_ACTIVE_COMPILATION_CONDITIONS)`. |
| | `CustomBaseDomain` | String | Specifies the base custom proxy domain to route SDK network traffic through your own subdomain. |
| | `IntegrationPartner` | String | Specifies your integration partner. For example, `segment` or `mparticle`.Default value: none. |
| | `AppGroupName` | String | Specifies the App Group name used for sharing SDK data. Default value: `""`. |
| **Logs** | `IsLoggingEnabled` | Boolean | Set to *true* to enable SDK logs. |
| | `Loglevel` | Integer | `0` to `5`. Default: `2`. |
| **Security** | `IsStorageEncryptionEnabled` | Boolean | Enables local storage encryption. Default value: `false`. |
| | `KeychainGroupName` | String | Specifies the keychain group name used for storing encryption keys. This is a mandatory field if `IsStorageEncryptionEnabled` is `true`. Default value: `""`. |
| | `IsNetworkEncryptionEnabled` | Boolean | Enables payload encryption. Default: `false`. |
| | `EncryptionEncodedTestKey` | String | Dashboard auto-populated string. Used if `IsNetworkEncryptionEnabled` is `true`. |
| | `EncryptionEncodedLiveKey` | String | Dashboard auto-populated string. Used if `IsNetworkEncryptionEnabled` is `true`. |
| **Sync** | `AnalyticsEnablePeriodicFlush` | Boolean | Enables periodic data flush. Default: `true`. |
| | `AnalyticsPeriodicFlushDuration` | Integer | Flush interval in seconds. Default: `60`. |
| **In-App** | `InAppDisplaySafeAreaInset` | Real | Decimal value representing safe area padding. Default: `0`. |
| | `InAppShouldProvideDeeplinkCallback` | Boolean | If `true`, provides callback on deeplink. Default: `false`. |
### Data Center Values
Configure the integer corresponding to your region. Incorrect values will result in data loss.
| Data Center | Dashboard host |
| ----------- | ------------------------------------------------------------- |
| 1 | [dashboard-01.moengage.com](http://dashboard-01.moengage.com) |
| 2 | [dashboard-02.moengage.com](http://dashboard-02.moengage.com) |
| 3 | [dashboard-03.moengage.com](http://dashboard-03.moengage.com) |
| 4 | [dashboard-04.moengage.com](http://dashboard-04.moengage.com) |
| 5 | [dashboard-05.moengage.com](http://dashboard-05.moengage.com) |
| 6 | [dashboard-06.moengage.com](http://dashboard-06.moengage.com) |
### Update Info.plist
1. Open your project's `Info.plist` ( found in `ios/Runner/` ).
2. Create a new Top-Level Key named `MoEngage` of type `Dictionary`.
3. Add the configuration file content generated in the [Initialization Website.](https://app-cdn.moengage.com/sdk/integration/config/index.html)
The key `IsSdkAutoInitialisationEnabled` uses the British spelling ('s'). Ensure you use the exact key name shown below, or initialization will fail.
**XML Snippet Representation:**
```xml XML theme={null}
MoEngageWorkspaceIdYOUR_WORKSPACE_IDIsTestEnvironment$(SWIFT_ACTIVE_COMPILATION_CONDITIONS)|$(GCC_PREPROCESSOR_DEFINITIONS)DataCenter1CustomBaseDomaindata.example.comIsLoggingEnabled
```
## Step 3: Framework Level Initialization
After you configure the native files, the initialization code in your hybrid framework is simplified.
Create **MoEngageFlutter(YOUR\_Workspace\_ID)** object and in the project's App Widget call **initialise()** of **MoEngageFlutter** plugin in the **initState()** the method as shown below:
```dart Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
final MoEngageFlutter _moengagePlugin = MoEngageFlutter(YOUR_Workspace_ID);
@override
void initState() {
super.initState();
initPlatformState();
_moengagePlugin.initialise();
}
```
## Step 4: Migration and Precedence
To migrate from manual code-based initialization to file-based approach, refer [here](/developer-guide/flutter-sdk/sdk-integration/sdk-initialization/file-based-initialization/migration-and-precedence).
## Step 5: Environments (Test vs. Live)
You can configure Test/Live environments within these files.
* **Android:** Use the key `test`.
* **iOS:** Use `IsTestEnvironment`
# Migration and Precedence
Source: https://moengage.com/docs/developer-guide/flutter-sdk/sdk-integration/sdk-initialization/file-based-initialization/migration-and-precedence
Migrate your MoEngage Flutter SDK from code-based initialization to file-based configuration.
### Android Migration Steps
To migrate from manual code-based initialization to the XML file-based approach, follow the below steps:
1. **Add Configuration File:** Place the `moengage_config` file in the (`src/main/assets/moengage.xml`) path.
2. **Update Application Class:** Remove the existing initialization code (the manual `MoEngage.Builder` logic) from your Application class and replace it with the default instance initialization to enable reading from the XML file.
| Code Language | Existing Code | Replace with |
| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
| Kotlin | val moEngage: MoEngage.Builder = MoEngage.Builder(this,"YOUR\_Workspace\_ID", DataCenter.DATA\_CENTER\_X) MoEInitializer.initialiseDefaultInstance(context = this, builder = moEngage) | MoEInitializer.initializeDefaultInstance(application) |
| Java | MoEngage.Builder moEngage = new MoEngage.Builder(this, "YOUR\_Workspace\_ID", YOUR\_DATA\_CENTER); MoEInitializer.initialiseDefaultInstance(this, moEngage); | MoEInitializer.INSTANCE.initializeDefaultInstance(this); |
### iOS Migration Steps
To migrate from code-based initialization to the `Info.plist` based approach, follow these steps:
1. **Update Info.plist**: Add the required MoEngage configuration keys (e.g., WorkspaceId, DataCenter) inside the *MoEngage* key in your `Info.plist` file.
2. **Update AppDelegate**: Remove the existing initialization code (the manual MoEngageSDKConfig logic) from your `AppDelegate` class and replace it with the default instance initialization to enable reading from the `Info.plist` file.
| Code Language | Existing Code | Replace with |
| ------------- | ------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------- |
| Swift | MoEngageInitializer.sharedInstance.initializeDefaultInstance(sdkConfig, launchOptions: launchOptions) | MoEngageInitializer.sharedInstance.initializeDefaultInstance() |
| Objective-C | \[\[MoEngageInitializer sharedInstance] initializeDefaultInstance:sdkConfig launchOptions:launchOptions]; | \[MoEngageInitializer.sharedInstance initializeDefaultInstance]; |
### Precedence Rules
The source of configuration is determined by the initialization function called in your native code:
* **Android**:
* **File-Based Init:** Calling `MoEInitializer.initializeDefaultInstance(context)` instructs the SDK to look for and read the `moengage.xml` file.
* **Code-Based Init:** Calling `MoEInitializer.initialize(context, moEngage.Builder)` will initialize the SDK using the configuration object passed in the parameters, ignoring the XML file even if it exists.
* **iOS:** Auto-initialization (via `Info.plist`) occurs first. However, if you subsequently call the manual `initialize` method with a configuration object in your code, it will update the current instance configuration.
# Android SDK Initialization
Source: https://moengage.com/docs/developer-guide/flutter-sdk/sdk-integration/sdk-initialization/manual-initialization/android-sdk-initialization
Initialize the MoEngage Flutter SDK in your Android application class with your workspace ID.
Get the APP ID from the Settings Page \_Dashboard --> Settings --> App --> General Settings on the MoEngage dashboard and initialize the MoEngage SDK in the ***Application*** class's ***onCreate()***.
Initialize the SDK on the main thread inside onCreate() and not create a worker thread and initialize the SDK on that thread.
```kotlin Kotlin theme={null}
import com.moengage.flutter.MoEInitializer
import com.moengage.core.MoEngage
import com.moengage.core.DataCenter
...
// `this` is the instance of the application class and "YOUR_Workspace_ID" is the Workspace ID from the dashboard.
val moEngage: MoEngage.Builder = MoEngage.Builder(this,"YOUR_Workspace_ID", DataCenter.DATA_CENTER_X)
MoEInitializer.initialiseDefaultInstance(context = this, builder = moEngage)
```
```java Java theme={null}
import com.moengage.flutter.MoEInitializer;
import com.moengage.core.MoEngage;
import com.moengage.core.DataCenter;
...
// `this` is the instance of the application class and "YOUR_Workspace_ID" is the Workspace ID from the dashboard.
MoEngage.Builder moEngage = new MoEngage.Builder(this, "YOUR_Workspace_ID", YOUR_DATA_CENTER);
MoEInitializer.initialiseDefaultInstance(this, moEngage);
```
Following details of the different data centers you need to set based on the dashboard hosts
| Data Center | Dashboard host |
| -------------------------- | ------------------------- |
| DataCenter.DATA\_CENTER\_1 | dashboard-01.moengage.com |
| DataCenter.DATA\_CENTER\_2 | dashboard-02.moengage.com |
| DataCenter.DATA\_CENTER\_3 | dashboard-03.moengage.com |
| DataCenter.DATA\_CENTER\_4 | dashboard-04.moengage.com |
| DataCenter.DATA\_CENTER\_5 | dashboard-05.moengage.com |
| DataCenter.DATA\_CENTER\_6 | dashboard-06.moengage.com |
For more information about the detailed list of possible configurations, refer to the [API reference](https://moengage.github.io/android-api-reference/core/com.moengage.core/-mo-engage/-builder/index.html).
**Critical**
All the configurations are added to the builder before initialization. If you are calling initialize at multiple places, ensure that all the required flags and configurations are set each time you initialize to maintain consistency in behavior.
# Exclude MoEngage Storage File from Auto-Backup
This is a mandatory integration step and is very essential to prevent your data from getting corrupted. Android's auto back-up service periodically backs up Shared Preference files, Database files, etc, more details [here](/developer-guide/android-sdk/sdk-integration/manual-initialization/exclude-moengage-storage-file-from-the-auto-backup). This backup results in MoEngage SDK's identifiers being backed up and restored after re-install.This restoration of the identifier results in your data being corrupted and users not being reachable via push notifications.
To ensure data is not corrupted after a backup is restored, opt out of MoEngage SDK's storage files. Refer to [Exclude MoEngage Storage File from the Auto-Backup](/developer-guide/android-sdk/sdk-integration/manual-initialization/exclude-moengage-storage-file-from-the-auto-backup) section of the documentation to learn more about which files to exclude.
# Framework Initialization
Source: https://moengage.com/docs/developer-guide/flutter-sdk/sdk-integration/sdk-initialization/manual-initialization/framework-initialization
Initialize the MoEngage Flutter plugin in your app widget's initState using MoEngageFlutter.
# Initialize Plugin
Create **MoEngageFlutter(YOUR\_Workspace\_ID)** object and in the project's App Widget call **initialise()** of **MoEngageFlutter** plugin in the **initState()** the method as shown below:
```Dart Dart theme={null}
import 'package:moengage_flutter/moengage_flutter.dart';
final MoEngageFlutter _moengagePlugin = MoEngageFlutter(YOUR_Workspace_ID);
@override
void initState() {
super.initState();
initPlatformState();
_moengagePlugin.initialise();
}
```
For more information, refer to [Flutter SDK](https://github.com/moengage/Flutter-SDK).
Refer to the following for platform-specific initialization:
* [Android](/developer-guide/flutter-sdk/sdk-integration/sdk-initialization/manual-initialization/android-sdk-initialization)
* [iOS](/developer-guide/flutter-sdk/sdk-integration/sdk-initialization/manual-initialization/ios-sdk-initialization)
* [Web](/developer-guide/flutter-sdk/sdk-integration/sdk-initialization/manual-initialization/web-sdk-initialization)
# iOS SDK Initialization
Source: https://moengage.com/docs/developer-guide/flutter-sdk/sdk-integration/sdk-initialization/manual-initialization/ios-sdk-initialization
Initialize the MoEngage Flutter SDK in your iOS AppDelegate using the MoEngageInitializer instance.
# Initialization
To initialize the iOS Application with the MoEngage Workspace ID from Settings in the dashboard. In your project, go to the ***AppDelegate*** file and call either of the ***initialize()*** of **\_MoEngageInitializer \_**instance in ***applicationdidFinishLaunchingWithOptions()*** as shown below:
Make sure to set the correct Data Center while initializing the SDK. For more information, refer to the following [link](/developer-guide/flutter-sdk/sdk-integration/sdk-initialization/manual-initialization/data-center).
```swift Swift theme={null}
/// Method to initialize MoEngage SDK
/// - Parameters:
/// - config: MoEngageSDKConfig instance for SDK configuration
/// - launchOptions: Launch Options dictionary
func initializeDefaultInstance(_ config: MoEngageSDKConfig, launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil)
/// Method to initialize MoEngage SDK with SDK state
/// - Parameters:
/// - config: MoEngageSDKConfig instance for SDK configuration
/// - sdkState: Bool indicating if SDK is Enabled/Disabled
/// - launchOptions: Launch Options dictionary
func initializeDefaultInstance(_ config: MoEngageSDKConfig, sdkState: Bool = true, launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil)
```
Sample code to initialize in ***applicationdidFinishLaunchingWithOptions()***
```swift Swift theme={null}
// Import SDK frameworks
import moengage_flutter_ios
import MoEngageSDK
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
//Workspace ID: You can be obtain it from App Settings in MoEngage Dashboard.
let sdkConfig = MoEngageSDKConfig(withAppID: yourWorkspaceIDappId, dataCenter: DATA_CENTER)
sdkConfig.enableLogs = true
MoEngageInitializer.sharedInstance.initializeDefaultInstance(sdkConfig, launchOptions: launchOptions)
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
```
```objectivec Objective-C theme={null}
// Import SDK frameworks
#import
#import
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
MoEngageSDKConfig* sdkConfig = [[MoEngageSDKConfig alloc] initWithAppID:@"Workspace ID"dataCenter: DATA_CENTER];
sdkConfig.enableLogs = true;
[[MoEngageInitializer sharedInstance] initializeDefaultInstance:sdkConfig launchOptions:launchOptions];
[GeneratedPluginRegistrant registerWithRegistry:self];
// Override point for customization after application launch.
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
@end
```
# Data Center
In case your app wants to redirect data to a specific zone due to any data regulation policy please configure the zone in the MOSDKConfig object.
For more information on Data Center, refer [here](/developer-guide/ios-sdk/sdk-integration/basic/data-center).
# Web SDK Initialization
Source: https://moengage.com/docs/developer-guide/flutter-sdk/sdk-integration/sdk-initialization/web-sdk-initialization
Add the MoEngage Web SDK initialization script to your Flutter web application's index.html file.
Get the Workspace ID from the dashboard and replace "XXXXXXXXXXX" in the code below.
And get the Data Center according to your dashboard:
| Data Center | Dashboard host |
| ----------- | ------------------------- |
| dc\_1 | dashboard-01.moengage.com |
| dc\_2 | dashboard-02.moengage.com |
| dc\_3 | dashboard-03.moengage.com |
| dc\_4 | dashboard-04.moengage.com |
| dc\_6 | dashboard-06.moengage.com |
1. Add this initialization script to your `web/index.html` file:
```javascript JavaScript theme={null}
```
2. For web push integration refer this section of the Web Push guide.
# Android
Source: https://moengage.com/docs/developer-guide/flutter-sdk/sdk-integration/sdk-installation/android
Add the required Android dependencies and AndroidX libraries for the MoEngage Flutter SDK.
# Add dependencies
Add the following dependencies to the ***android/app/build.gradle*** file.
## Add Androidx Libraries
The SDK depends on a few Androidx libraries for its functioning, add the below Androidx libraries in your application if not done already.
```groovy build.gradle theme={null}
dependencies {
...
implementation("androidx.core:core:1.6.0")
implementation("androidx.appcompat:appcompat:1.3.1")
implementation("androidx.lifecycle:lifecycle-process:2.7.0")
}
```
The MoEngage SDK depends on the **lifecycle-process** library for a few key features to work and the latest version of **lifecycle-process** depends on the **androidx.startup:startup-runtime** library. Hence do not remove the **InitializationProvider** component from the manifest. When adding other Initializers using the **startup-runtime**, ensure the Initializer for the **lifecycle-process** library is also added. Refer to the [documentation](https://developer.android.com/jetpack/androidx/releases/lifecycle#2.4.0) to know how to add the Initializer.
# Framework Dependency
Source: https://moengage.com/docs/developer-guide/flutter-sdk/sdk-integration/sdk-installation/framework-dependency
Install the MoEngage Flutter SDK by adding moengage_flutter to your pubspec.yaml file.
Flutter is Google’s UI toolkit for building natively compiled applications for iOS and Android from a single codebase.

# Plugin Installation
To add MoEngage's Flutter SDK to your application, edit your ***pubspec.yaml*** to add ***moengage\_flutter*** as a dependency.
```yaml pubspec.yaml theme={null}
dependencies:
moengage_flutter: $lastestVersion
```
***\$latestVersion*** refers to the latest version of the plugin.
Post including the dependency run the following command in terminal to install the dependency.
```yaml pubspec.yaml theme={null}
flutter pub get
```
A working Sample App can be found [here](https://github.com/moengage/Flutter-SDK).
After installing the plugin, use the following platform-specific configuration.
* [Android](/developer-guide/flutter-sdk/sdk-integration/sdk-installation/android)
* [iOS](/developer-guide/flutter-sdk/sdk-integration/sdk-installation/ios)
* [Web](/developer-guide/flutter-sdk/sdk-integration/sdk-installation/web)
# iOS
Source: https://moengage.com/docs/developer-guide/flutter-sdk/sdk-integration/sdk-installation/ios
Set up the MoEngage iOS SDK dependency in your Flutter project using CocoaPods or Swift Package Manager.
We have added our native SDK `MoEngage-iOS-SDK` as a dependency for `moengage_flutter` plugin, hence run `flutter build ios` command once to generate the Pod file for your iOS project and run `pod install` inside your project's `ios` directory to add the plugin and native SDK to your iOS Project.
Support for [Swift Package Manager](https://docs.flutter.dev/packages-and-plugins/swift-package-manager/for-app-developers) is available from version 10.3.0.
# Troubleshooting and FAQs - Flutter
Source: https://moengage.com/docs/developer-guide/flutter-sdk/troubleshooting-and-faqs/troubleshooting-and-faqs-flutter
Find solutions to common MoEngage Flutter SDK issues with notifications, callbacks, and in-app messages.
# Android - Why are notifications not working in the background or killed state?
Ensure that you are initializing MoEngage in the Application class and in the main thread.
Sample code link - [GitHub](https://github.com/moengage/Flutter-SDK/blob/dc4cac19fe9fc04ca4d187265544a6a1e9c04c9e/example/android/app/src/main/java/com/moengage/sampleapp/SampleApplication.kt#L37)
# Android - Why are callbacks not working in the background or killed state?
MoEngage callbacks must be registered in your application's root/App widget, and after setting them up, you must call the MoEngage Plugin's initialize () method. Read more about [it here](/developer-guide/flutter-sdk/push/basic/push-callback).
Sample code link - [GitHub](https://github.com/moengage/Flutter-SDK/blob/master/example/lib/main.dart)
# Android - Why are inapp/nudge deep links not working?
Unilke the push notification handling, MoEngage SDK doesn't handle inapp redirections by default (except for rich landing page), please refer to the [documentation here](/developer-guide/flutter-sdk/in-app-messages/inapp-nativ). You must implement inapp click callback methods in your root/app widget and call moengage plugin initialise() method after registering for callbacks. In these callbacks, you must handle the redirection for deeplink or screen-based redirection. Callback documentation [is given here](/developer-guide/flutter-sdk/in-app-messages/inapp-nativ).
# Android - Why are inapp callbacks not working?
Refer to [this documentation](/developer-guide/flutter-sdk/in-app-messages/inapp-nativ) to set up in-app callbacks. Additionally, you must register the callbacks in your application's root/App widget, and after setting them up, you must call the MoEngage Plugin's initialize () method.
# Developer Guide
Source: https://moengage.com/docs/developer-guide/introduction
Integrate MoEngage SDKs across mobile, web, and cross-platform frameworks for customer engagement.
**Beta**
We are refining the new SDK docs. While exploring them, you may encounter minor issues. We appreciate your patience as we finalize the content.
The [existing SDK docs](https://developers.moengage.com/hc/en-us) will be accessible until the transition is complete.
The MoEngage SDK is a lightweight, modular client library that runs inside your application. It handles event tracking, user identification, push token registration, in-app message rendering, and content card delivery — syncing data to MoEngage servers via batched HTTPS requests with offline queuing.
**Out of the box, the SDK automatically collects:** session start/end, app version, device model, OS version, timezone, and locale. Push tokens are registered automatically when push is configured. All other tracking — events, user attributes — is explicit via your API calls.
## Supported Platforms
### Native
Kotlin and Java. Push (FCM, HMS), in-app messaging, cards, push templates, push amplification, notification center, location triggers, and Android TV support. Modular — add only what you need.
Swift and Objective-C. Push (APNs), in-app messages, cards, push templates, Live Activities, real-time triggers, notification center, and Apple TV support. Available via CocoaPods or SPM.
Framework-agnostic JavaScript SDK. Web push, on-site messaging (OSM), data tracking, cards, and lifecycle callbacks. Works with React, Angular, Vue, Next.js, and any SPA or MPA. Also supports AMP pages, browser extensions, WebView, and Smart TVs.
### Cross-Platform
Cross-platform SDKs provide a unified API that bridges to the native Android and iOS SDKs. You will need to complete platform-specific setup steps for push notifications, in-app rendering, and other native features alongside the framework-level integration.
Supports React Native CLI projects. Push, in-app, cards, and TV support. Android native setup required; iOS auto-links via CocoaPods.
Expo managed workflow support via **react-native-expo-moengage** config plugin. Push, in-app, and cards. Requires EAS Build for native module linking.
Dart plugin with native bindings for iOS, Android, and Web. Push, in-app, cards, geofence, and notification center. Null-safe (Dart 2.12+).
Apache Cordova plugin. Push, in-app, and data tracking. Requires **cordova-ios** 4.3+ for CocoaPods support.
Capacitor plugin (Capacitor 3+). Push, in-app, data tracking, and geofence. TypeScript API.
Ionic uses Cordova or Capacitor as its native runtime. Choose the plugin that matches your Ionic project's native layer — there is no separate Ionic-specific SDK.
Unity plugin with native bindings for iOS and Android. Push, in-app messaging, data tracking, push templates, and location-triggered campaigns.
### Specialty
Android TV (via Android SDK), Apple TV (via iOS SDK), and Smart TV (via Web SDK). Push and in-app support varies by platform.
Shopify 2.0 (app embed block), Magento, and WooCommerce. Auto-tracks ecommerce events and syncs product catalogs.
## Platform Compatibility
| Platform | Languages | Min Version | Package Manager | Install Guide |
| ---------------- | ---------------------- | ------------------------------------------------------------------------------------------------ | --------------- | -------------------------------------------------------------------------------------------------------------------- |
| **Android** | Kotlin, Java | API 23 (Android 6.0), compileSdk 35 | Maven Central | [BOM (recommended)](/developer-guide/android-sdk/sdk-integration/basic-integration/Install-Using-BOM) |
| **iOS** | Swift, Objective-C | iOS 13, Xcode 15+ | CocoaPods, SPM | [SPM](/developer-guide/ios-sdk/sdk-integration/basic/sdk-integration) |
| **Web** | JavaScript | [Browser matrix](/developer-guide/web-sdk/web-sdk-overview/web-sdk-browser-compatibility-matrix) | CDN or npm | [Integration guide](/developer-guide/web-sdk/web-sdk-integration/basic-integration/web-sdk-integration) |
| **React Native** | TypeScript/JS + native | RN 0.60+ (inherits native minimums) | npm | [RN CLI guide](/developer-guide/react-native-sdk/sdk-integration/react-native/sdk-installation/framework-dependency) |
| **Expo** | TypeScript/JS + native | Expo SDK 47+ (inherits native minimums) | npm | [Expo plugin guide](/developer-guide/react-native-sdk/sdk-integration/expo/installation) |
| **Flutter** | Dart + native | Dart 2.12+, Flutter 3.x (inherits native minimums) | pub.dev | [Flutter guide](/developer-guide/flutter-sdk/sdk-integration/sdk-installation/framework-dependency) |
| **Cordova** | JavaScript + native | cordova-ios 4.3+, cordova-cli 6.4+ | npm | [Cordova guide](/developer-guide/cordova-sdk/sdk-integration/sdk-installation/framework-dependency) |
| **Capacitor** | TypeScript + native | Capacitor 3+ (inherits native minimums) | npm | [Capacitor guide](/developer-guide/capacitor-sdk/sdk-integration/sdk-installation/framework-dependency) |
## Quick Start
Pick your platform and follow the integration guide. Estimated time to first event: **15–30 minutes** for native SDKs, **30–60 minutes** for cross-platform (due to additional native configuration).
In the MoEngage Dashboard, go to **Settings → Account → APIs → Workspace ID**. You'll need this to initialize the SDK.
Your data center determines the API endpoint the SDK communicates with. Find your data center from the dashboard URL host (e.g., `dashboard-01.moengage.com` → `dc_1`). This must be configured during SDK initialization.
Follow the platform-specific installation guide from the table above.
Call the initialization method with your Workspace ID and data center. Use the **TEST** environment during development and **LIVE** for production.
Call the event tracking API to send a custom event. Verify it appears in the MoEngage Dashboard under **Analytics → Event Analysis**.
### Prerequisites by platform
Before starting integration, ensure you have:
* **Android:** Firebase project with `google-services.json` configured (required for FCM push). Gradle 7.0+, AGP 7.0+, Java 8+.
* **iOS:** Apple Developer account with push notification entitlement enabled. APNs Authentication Key (`.p8` file) uploaded to MoEngage Dashboard.
* **Web:** HTTPS-enabled domain (required for web push via Service Workers).
* **Cross-Platform (React Native / Expo / Flutter / Cordova / Capacitor):** All of the above native prerequisites, plus the framework-specific toolchain.
## Feature Availability by Platform
Not every feature is available on every platform. Use this matrix to verify support before starting integration.
| Feature | Android | iOS | Web | React Native | Expo | Flutter | Cordova | Capacitor |
| -------------------------------------------- | :--------: | :----: | :--------: | :----------: | :--: | :-----: | :-----: | :-------: |
| **Push Notifications** | ✅ FCM, HMS | ✅ APNs | ✅ Web Push | ✅ | ✅ | ✅ | ✅ | ✅ |
| **Push Templates** | ✅ | ✅ | — | ✅ | ✅ | ✅ | ✅ | ✅ |
| **Push Amplification** | ✅ | — | — | ✅ | ✅ | ✅ | ✅ | ✅ |
| **Device Triggered Push** | ✅ | ✅ | — | ✅ | ✅ | ✅ | ✅ | ✅ |
| **Live Activities** | — | ✅ | — | ✅ | ✅ | ✅ | ✅ | ✅ |
| **HTML In-App Messages (Templates, Nudges)** | ✅ | ✅ | — | ✅ | ✅ | ✅ | ✅ | ✅ |
| **In-App NATIV** | ✅ | ✅ | — | ✅ | ✅ | ✅ | ✅ | ✅ |
| **On-Site Messaging (OSM)** | — | — | ✅ | — | — | — | — | — |
| **Cards** ¹ | ✅ | ✅ | ✅ | ✅ ² | ✅ ² | ✅ ² | — | — |
| **Data Tracking** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| **Location/Geofence** | ✅ | ✅ | — | ✅ | ✅ | ✅ | ✅ | ✅ |
| **Notification Center (Inbox)** | ✅ | ✅ | — | ✅ | ✅ | ✅ | — | — |
| **Web Personalization** | — | — | ✅ | — | — | — | — | — |
| **GDPR Opt-outs** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
¹ Android, iOS, Web, and both UI Cards and Self-Handled Cards.
² Self-handled only.
Some features require additional module dependencies. Check the platform-specific integration guide for exact dependency requirements.
## Common Integration Tasks
| Task | Android | iOS | Web |
| --------------------- | ----------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| Install SDK | [Build settings](/developer-guide/android-sdk/sdk-integration/basic-integration/configuring-build-settings) | [SDK Integration](/developer-guide/ios-sdk/sdk-integration/basic/sdk-integration) | [Web SDK Integration](/developer-guide/web-sdk/web-sdk-integration/basic-integration/web-sdk-integration) |
| Initialize | [Initialization](/developer-guide/android-sdk/sdk-integration/basic-integration/sdk-initialization) | [Initialization](/developer-guide/ios-sdk/sdk-integration/basic/sdk-initialization) | [Integration](/developer-guide/web-sdk/web-sdk-integration/basic-integration/web-sdk-integration) |
| Set up push | [Push Config](/developer-guide/android-sdk/push/basic/push-configuration) | [Push Integration](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial) | [Web Push](/developer-guide/web-sdk/web-push/configure-and-integrate-web-push) |
| Track events | [Track Events](/developer-guide/android-sdk/data-tracking/basic/track-events) | [Track Events](/developer-guide/ios-sdk/data-tracking/basic/tracking-events) | [Events Tracking](/developer-guide/web-sdk/data-tracking/web-sdk-events-tracking) |
| Track user attributes | [User Attributes](/developer-guide/android-sdk/data-tracking/basic/track-user-attributes) | [User Attributes](/developer-guide/ios-sdk/data-tracking/basic/tracking-user-attributes) | [User Attributes](/developer-guide/web-sdk/data-tracking/web-sdk-user-attributes-tracking) |
| Enable in-app / OSM | [In-App NATIV](/developer-guide/android-sdk/in-app-messages/in-app-nativ) | [In-App NATIV](/developer-guide/ios-sdk/in-app-messages/in-app-nativ) | [On-Site Messaging](/developer-guide/web-sdk/onsite-messaging/configure-and-integrate-on-site-messaging) |
| Add cards | [Cards](/developer-guide/android-sdk/cards/cards) | [Cards](/developer-guide/ios-sdk/cards/cards-in-i-os) | [Cards](/developer-guide/web-sdk/cards/cards) |
| Compliance | [Compliance](/developer-guide/android-sdk/compliance/compliance) | [Compliance](/developer-guide/ios-sdk/compliance/compliance) | [Data opt-out](/developer-guide/web-sdk/data-tracking/configure-data-opt-out-in-web-sdk) |
## Upgrading & Migration
[10.x → 11.x](/developer-guide/android-sdk/migration/updating-to-11xxx-from-10xxx) · [11.x → 12.x](/developer-guide/android-sdk/migration/updating-to-12xxx-from-11xxx) · [Manifest → Code-based init](/developer-guide/android-sdk/migration/moving-from-manifest-to-code-based-integration) · [GCM → FCM](/developer-guide/android-sdk/migration/migrating-from-gcm-to-fcm) · [Maven Central migration](/developer-guide/android-sdk/migration/migration-to-maven-central)
[→ v6.0.0](/developer-guide/ios-sdk/migration/migration-to-sdk-version-6-0-0) · [→ v7.0.0](/developer-guide/ios-sdk/migration/migration-to-sdk-version-7-0-0) · [→ v8.2.0](/developer-guide/ios-sdk/migration/migration-to-sdk-version-8-2-0) · [→ v9.0.0](/developer-guide/ios-sdk/migration/migration-to-sdk-version-9-0-0)
## Developer Resources
Working reference implementations: [Android](/developer-guide/android-sdk/sample-app/android-sample-app) · [iOS](/developer-guide/ios-sdk/sample-app/i-os-sample-app) · [React Native](/developer-guide/react-native-sdk/sample-app/react-native-sample-app) · [Flutter](/developer-guide/flutter-sdk/sample-app/flutter-sample-app) · [Capacitor](/developer-guide/capacitor-sdk/sample-app/capacitor-sample-app)
Changelogs for every SDK. [Subscribe to releases](/developer-guide/release-notes/subscribe-to-moengage-sdk-releases/subscribe-to-mo-engage-sdk-releases) via GitHub to get notified of new versions, breaking changes, and security patches.
[Android](/developer-guide/android-sdk/troubleshooting-and-faqs/troubleshooting-and-faqs) · [iOS](/developer-guide/ios-sdk/troubleshooting-and-faqs/troubleshooting-and-faqs-ios) · [React Native](/developer-guide/react-native-sdk/troubleshooting-and-faqs/troubleshooting-and-faqs-react) · [Flutter](/troubleshooting-and-faqs-flutter) · [Capacitor](/troubleshooting-and-faqs-capacitor)
Pre-launch verification: [Android](/developer-guide/android-sdk/checklist/release-checklist) · [iOS](/developer-guide/ios-sdk/checklist/release-checklist)
[Android size](/developer-guide/android-sdk/performance/sdk-size-impact) · [Android performance](/developer-guide/android-sdk/performance/sdk-performance) · [iOS framework size](/developer-guide/ios-sdk/framework-size-impact/framework-size-impact)
[Android compliance](/developer-guide/android-sdk/compliance/compliance) · [iOS compliance](/developer-guide/ios-sdk/compliance/compliance) · [Google Play data disclosure](/developer-guide/android-sdk/compliance/prepare-for-google-plays-data-disclosure-requirements) · [GDPR/CCPA API](/api/gdpr-ccpa/gdpr-ccpa-overview)
Need help? Contact your Customer Success Manager.
# SDK Installation
Source: https://moengage.com/docs/developer-guide/ionic-sdk/sdk-integration/sdk-installation
Add the cordova-moengage-core plugin to your Ionic project and configure your workspace ID.
# Adding MoEngage Plugin
Add `cordova-moengage-core` plugin to Ionic project as shown below :
```Shell Shell theme={null}
$ ionic cordova plugin add cordova-moengage-core --variable APP_ID="[your_workspace_id]"
```
# Variables
* **APP\_ID** = Workspace id found under the settings page on the MoEngage dashboard.
# Plugin Name Update
Starting from version 5.0.2, we have changed the name of our plugin. Earlier it was registered as `moengagesdk` and now it is renamed to `cordova-moengage-core`. In case if you are updating from version 5.0.1 or earlier. Please make sure to remove the older version of the plugin first and then install the newer plugin as shown below:
```Shell Shell theme={null}
$ ionic cordova plugin rm cordova-plugin-moengage
$ ionic cordova plugin add cordova-moengage-core --variable APP_ID="[your_workspace_id]"
```
# MoEngage Declaration
Make sure you add the below line to your typescript files before calling any MoEngage SDK API.
```TypeScript TypeScript theme={null}
declare var MoECordova: any;
```
**Refer Cordova Docs**
As you can see the plugin used here for Ionic is the same which is built by us for Cordova framework, therefore please follow the Cordova SDK Documentation starting from the [SDK Installation](/developer-guide/cordova-sdk/sdk-integration/sdk-installation/framework-dependency) for integrating the plugin to your project and using the different feature provided in the plugin.
# Apple TV
Source: https://moengage.com/docs/developer-guide/ios-sdk/apple-tv/apple-tv
Learn about MoEngage SDK support for Apple TV including data tracking, in-app, and cards features.
MoEngage supports your apps available on Apple TV.
**Prerequisites**
Ensure that the [iOS SDK integration](/developer-guide/ios-sdk/sdk-integration/basic/sdk-integration) is completed.
# Supported Features
| Feature | SDK version | Module Version |
| :------------------------------------------------------------------------------------- | :---------- | :--------------------- |
| [Data tracking](/developer-guide/ios-sdk/data-tracking/basic/tracking-user-attributes) | 8.2.0 | |
| [Self-handled InApp](/developer-guide/ios-sdk/in-app-messages/in-app-nativ) | 9.13.0 | MoEngageInApp - 4.12.1 |
| [Self-handled Cards](/developer-guide/ios-sdk/cards/self-handled-cards) | 9.13.0 | MoEngageCards - 4.12.1 |
# Cards in iOS
Source: https://moengage.com/docs/developer-guide/ios-sdk/cards/cards-in-i-os
Create and display card campaigns in your iOS app using the MoEngage Cards SDK via SPM or CocoaPods.
Create targeted or automated App Inbox/NewsFeed messages that can be grouped into various categories, and target your users with different updates or offers that can stay in the Inbox/Feed over a designated period of time. Refer to the [help article](https://help.moengage.com/hc/en-us/articles/360045074752-Create-Cards-Campaign) to learn more about cards.
# SDK Installation
## Install using Swift Package Manager
MoEngageCards is supported through SPM from SDK version 3.2.0. To integrate use the following GitHub URL link and set the branch as master or version as 4.11.1 and above [https://github.com/moengage/MoEngage-iOS-Cards.git](https://github.com/moengage/MoEngage-iOS-Cards.git)
## Install using CocoaPod
**Information**
CocoaPods is being deprecated. MoEngage recommends using Swift Package Manager for all new integrations. For detailed info on cocoapods, refer to [CocoaPods Integration Guide](/developer-guide/ios-sdk/sdk-integration/basic/integration-through-cocoa-pods).
Integrate the MoEngageCards framework by adding the dependency in the pod file as described in the following image.
```ruby Ruby wrap theme={null}
pod 'MoEngage-iOS-SDK/Cards',
```
Now run `pod install` to install the framework
## Manual Integration
**Manual Integration**
To integrate the `MoEngageCards` SDK manually to your project follow this [doc](/hc/en-us/articles/4404183451412).
# Displaying AppInbox/Feeds
Once the module is integrated, use the below-provided methods to display the `MoEngageCardsListViewController` with the transition:
```swift Swift lines wrap theme={null}
// To Push MoEngageCardsListViewController
MoEngageSDKCards.sharedInstance.pushCardsViewController(toNavigationController: self.navigationController!)
// To Present MoEngageCardsListViewController
MoEngageSDKCards.sharedInstance.presentCardsViewController()
```
```objective-c objective-c theme={null}
// To Push MoEngageCardsListViewController
[[MoEngageSDKCards sharedInstance] pushCardsViewControllerToNavigationController:navigationController withUIConfiguration:nil withCardsViewControllerDelegate:nil forAppID:@"YOUR Workspace ID"];
// To Present MoEngageCardsListViewController
[[MoEngageSDKCards sharedInstance] presentCardsViewControllerWithUIConfiguration:nil withCardsViewControllerDelegate:nil forAppID:@"YOUR Workspace ID"];
```
So as shown above, in the SDK we have provided support for Push and Present transition. In case you want to handle the transition while displaying the Inbox, use the [*getCardsViewController(withUIConfiguration:withCardsViewControllerDelegate:forAppID:withCompletionBlock:)*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKCards.html#/c:@M@MoEngageCards@objc\(cs\)MoEngageSDKCards\(im\)getCardsViewControllerWithUIConfiguration:withCardsViewControllerDelegate:forAppID:withCompletionBlock:) method as shown below to obtain the view controller instance:
```swift Swift wrap theme={null}
MoEngageSDKCards.sharedInstance.getCardsViewController(withUIConfiguration: nil, withCardsViewControllerDelegate: nil, forAppID: "YOUR Workspace ID") { cardsController in
print("fetched CardsController")
}
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKCards sharedInstance] getCardsViewControllerWithUIConfiguration:nil withCardsViewControllerDelegate:nil forAppID:@"YOUR Workspace ID" withCompletionBlock:^(MoEngageCardsListViewController * _Nullable) {
self.cardsController = cardsController;
}];
```
# Customizing Inbox UI
The earlier snapshots indicate what the default UI of the Inbox would look like. But we have also added support for customizing the App Inbox screen according to your App Theme. For customizing the screen make use of [*MoEngageCardsUIConfiguration*](https://moengage.github.io/ios-api-reference/Classes/MoEngageCardsUIConfiguration.html) instance and pass the same in the above-mentioned methods. Refer to the example below:
```swift Swift wrap theme={null}
let uiConfig = MoEngageCardsUIConfiguration()
// Do customization using uiConfig
// provide the argument while obtaining the MoEngageCardsListViewController instance
// Present Cards View Controller
MoEngageSDKCards.sharedInstance.presentCardsViewController(withUIConfiguration: uiConfig)
// Push Cards View Controller
MoEngageSDKCards.sharedInstance.pushCardsViewController(toNavigationController: self.navigationController!, withUIConfiguration: uiConfig)
// Obtaining the ViewController
MoEngageSDKCards.sharedInstance.getCardsViewController(withUIConfiguration: uiConfig, withCardsViewControllerDelegate: uiConfig, forAppID: "YOUR Workspace ID") { cardsController in
self.cardsController = cardsController
}
```
The example of how the UI of Inbox can be completely customized according to your need. Below we have mentioned about what all UI attributes which can be customized using [*MoEngageCardsUIConfiguration*](https://moengage.github.io/ios-api-reference/Classes/MoEngageCardsUIConfiguration.html) instance:
## Customizing Navigation Bar:
Navigation Bar customization includes updating the title, navigation bar color, title color, title font, etc. Create an instance of [*MoEngageCardsNavigationBarStyle*](https://moengage.github.io/ios-api-reference/Classes/MoEngageCardsNavigationBarStyle.html) and set all the attributes as shown below, post that assign the same to your [*MoEngageCardsUIConfiguration*](https://moengage.github.io/ios-api-reference/Classes/MoEngageCardsUIConfiguration.html) instance:
```swift Swift wrap theme={null}
let uiConfig = MoEngageCardsUIConfiguration()
// Navigation Bar Customizations
let navBarStyle = MoEngageCardsNavigationBarStyle()
navBarStyle.navigationBarColor = UIColor(hex: "#0A1D1F")
navBarStyle.navigationBarTitleFont = UIFont.systemFont(ofSize: 20.0, weight: .semibold)
navBarStyle.navigationBarTitleColor = UIColor(hex: "#FFFFFF")
navBarStyle.navigationBarTintColor = UIColor(hex: "#FFFFFF")
navBarStyle.navigationBarTransluscent = true
uiConfig.navigationBarTitle = "Hello!!!"
uiConfig.navigationBarStyle = navBarStyle
```
## Customizing Category TabBar:
Directly set the attributes of [*MoEngageCardsUIConfiguration*](https://moengage.github.io/ios-api-reference/Classes/MoEngageCardsUIConfiguration.html) instance, you would like to change for the Category Tabs Bar view as shown below:
```swift Swift wrap theme={null}
let uiConfig = MoEngageCardsUIConfiguration()
// Category Tabs Customizations
uiConfig.categoryTabsContainerBGColor = UIColor(hex: "#6EA6CF")
uiConfig.categoryTabsBGColor = UIColor(hex: "#6EA6CF")
uiConfig.categoryTabsTextColor = UIColor(hex: "#0A1D1F")
uiConfig.categorySelectedTabBGColor = UIColor(hex: "#BB4D3E")
uiConfig.categorySelectedTabTextColor = UIColor(hex: "#FFFFFF")
uiConfig.categorySelectionIndicatorBarColor = UIColor(hex: "#B0BF40")
uiConfig.categoryTabFont = UIFont.systemFont(ofSize: 12.0, weight: .medium)
uiConfig.categorySelectedTabFont = UIFont.systemFont(ofSize: 16.0, weight: .bold)
```
## Customizing Empty Inbox:
In the case of an empty inbox, we provide the option of setting a message and image. By default, the empty inbox will look as described in the following image:
This can again be customized by using the UI configuration instance as shown below:
```swift Swift wrap theme={null}
let uiConfig = MoEngageCardsUIConfiguration()
// Empty Inbox Customization
uiConfig.emptyInboxText = "No New Messages!!!"
uiConfig.emptyInboxTextColor = UIColor(hex:"#BB4D3E") ?? .white
uiConfig.emptyInboxTextFont = UIFont.systemFont(ofSize: 28.0, weight: .bold)
uiConfig.emptyInboxImage = UIImage(named: "emptyInbox")
```
## Customising Inbox Container:
In case any of the property of `MoEngageCardsListViewController` has to be customized, refer to the below example:
```swift Swift wrap theme={null}
let uiConfig = MoEngageCardsUIConfiguration()
// Cards Container customization
uiConfig.cardsViewControllerBGColor = UIColor(hex:"#0A1D1F")
uiConfig.cardsTableViewBGColor = UIColor(hex:"#0A1D1F")
uiConfig.pullToRefreshTintColor = UIColor(hex:"#BB4D3E")
// To disable Pull to refresh set it to false, set to true by default
uiConfig.enablePullToRefresh = false
// To change the Delete/Cancel text in Action Sheet
uiConfig.actionSheetDeletionText = "Remove"
uiConfig.actionSheetCancelText = "Never Mind" // New Updates Button Customizations
uiConfig.newUpdatesButtonTitle = "Updates Available!!"
uiConfig.newUpdatesButtonFont = UIFont.systemFont(ofSize: 14.0, weight: .semibold)
uiConfig.newUpdatesButtonBGColor = UIColor(hex:"#BB4D3E")
uiConfig.newUpdatesButtonTextColor = UIColor(hex: "#FFFFFF")
```
**Note**
We have supported pull to refresh in the Inbox, the activity indicator color for the same can be updated as shown above.
## Customizing Card Properties:
We have provided options to customize your Card in the dashboard while creating the campaign, but along with it you can also set the default attribute values so that you don't have to set it every time while creating the campaign, refer to the example below:
```swift Swift wrap theme={null}
let uiConfig = MoEngageCardsUIConfiguration()
// Cards Default parameters
uiConfig.defaultCardBackgroundColor = UIColor(hex:"#6EA6CF")
// On highlighting the cell
uiConfig.cardSelectionTintColor = UIColor(hex:"#333333")
// Header Label textcolor and font
uiConfig.cardHeaderLabelFont = UIFont.init(name: "AmericanTypewriter", size: 20.0)!
uiConfig.cardHeaderLabelDefaultTextColor = UIColor(hex:"#0A1D1F")
// Message Label textcolor and font
uiConfig.cardMessageLabelFont = UIFont.init(name: "Baskerville", size: 16.0)!
uiConfig.cardMessageLabelDefaultTextColor = UIColor(hex:"#0F2E2A")
// TimeStamp Date Format, Label textcolor and font
uiConfig.timestampDateFormat = "dd/MM, HH:mm"
uiConfig.cardTimestampLabelFont = UIFont.init(name: "Courier", size: 14.0)!
uiConfig.cardTimestampLabelDefaultTextColor = UIColor(hex:"#0F2E2A")
// CTA Button customizations
uiConfig.cardButtonFont = UIFont.init(name: "SavoyeLetPlain", size: 16.0)!
uiConfig.cardButtonDefaultTextColor = UIColor(hex:"#FFFFFF")
uiConfig.cardButtonDefaultBGColor = UIColor(hex:"#BB4D3E")
// Image Customizations
uiConfig.cardImageBackgroundColor = UIColor.clear
uiConfig.cardPlaceholderImage = UIImage(named: "card-placeholder")
// Card Pinned Indicator
uiConfig.cardPinnedImage = UIImage(named: "pinned")
// Unclicked Indicator
// Either Color OR Image NOT Both, If both are set then image will be considered
uiConfig.cardUnclickedIndicatorColor = UIColor(hex:"#7EC247")
uiConfig.cardUnclickedIndicatorImage = UIImage(named: "unclicked")
// Separator
uiConfig.cardSeparatorBackgroundColor = UIColor(red: 10.0/255.0, green: 90.0/255.0, blue: 190.0/255.0, alpha: 0.30)
```
# Getting Cards Count APIs
## Getting New Cards Count:
A Card is considered new if it's not yet seen by the user. To get the number/count of new cards use the [*getNewCardsCount(forAppID:withCompletionBlock:)*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKCards.html#/c:@M@MoEngageCards@objc\(cs\)MoEngageSDKCards\(im\)getNewCardsCountForAppID:withCompletionBlock:) method as shown below:
```swift Swift wrap theme={null}
MoEngageSDKCards.sharedInstance.getNewCardsCount(forAppID: "YOUR Workspace ID") { count, accountMeta in
print("Card count is \(count)")
})
```
## Getting Unclicked Cards Count:
To get the number/count of cards which are not clicked by the user, use the [*getUnclickedCardsCount(forAppID:withCompetionBlock:)*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKCards.html#/c:@M@MoEngageCards@objc\(cs\)MoEngageSDKCards\(im\)getUnclickedCardsCountForAppID:withCompletionBlock:) method as shown below:
```swift Swift wrap theme={null}
MoEngageSDKCards.sharedInstance.getUnclickedCardsCount(forAppID: "YOUR Workspace ID") { count, accountMeta in
print("UnClicked Card count is \(count)")
}
```
# Callbacks using MoEngageCardsDelegate
Use [*MoEngageCardsDelegate*](https://moengage.github.io/ios-api-reference/Protocols/MoEngageCardsDelegate.html) protocol for getting the callbacks from the Cards Module:
```swift Swift wrap theme={null}
@objc public protocol MoEngageCardsDelegate {
// Called when the Cards data is synced successfully
@objc optional func cardsSyncedSuccessfully(forAccountMeta accountMeta: MoEngageAccountMeta)
}
```
Set [*setCardsDelegate(delegate:forAppID:)*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKCards.html#/c:@M@MoEngageCards@objc\(cs\)MoEngageSDKCards\(im\)setCardsDelegateWithDelegate:forAppID:) property of [*MoEngageSDKCards*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKCards.html) instance as shown below to get the above callbacks:
```swift Swift wrap theme={null}
class DelegateClass: MoEngageCardsDelegate {
// ...
MoEngageSDKCards.sharedInstance.setCardsDelegate(delegate: self)// Pass delegate instance
```
# Callbacks using MoEngageCardsViewControllerDelegate
Use `MoEngageCardsViewControllerDelegate` protocol for getting the callbacks from the Cards Module:
```swift Swift wrap theme={null}
@objc public protocol MoEngageCardsViewControllerDelegate {
// Called when MoEngageCardsListViewController is dismissed after being presented
@objc optional func cardsViewControllerDismissed(forAccountMeta accountMeta: MoEngageAccountMeta)
// Called when a Card is deleted
@objc optional func cardDeleted(withCardInfo card: MoEngageCardCampaign, forAccountMeta accountMeta: MoEngageAccountMeta)
// Called when a Card is clicked by the user
@objc optional func cardClicked(withCardInfo card: MoEngageCardCampaign, andAction action:MoEngageCardAction, forAccountMeta accountMeta: MoEngageAccountMeta) -> Bool
}
```
Set `MoEngageCardsViewControllerDelegate` by passing the delegate as parameter in the below functions:
```swift Swift wrap theme={null}
class DelegateClass: MoEngageCardsViewControllerDelegate {
// ...
//Pass delegate instance when presenting the controller
MoEngageSDKCards.sharedInstance.presentCardsViewController(withUIConfiguration: nil, withCardsViewControllerDelegate: self)
//Pass delegate instance when pushing the controller
MoEngageSDKCards.sharedInstance.pushCardsViewController(toNavigationController: self.navigationController!, withUIConfiguration: nil, withCardsViewControllerDelegate: self)
//Pass delegate instance when fetching the controller
MoEngageSDKCards.sharedInstance.getCardsViewController(withUIConfiguration: uiConfig, withCardsViewControllerDelegate: uiConfig, forAppID: "YOUR Workspace ID") { cardsController in
}
```
# Self Handled Cards
Source: https://moengage.com/docs/developer-guide/ios-sdk/cards/self-handled-cards
Build custom card views in your iOS app using the MoEngage self-handled cards SDK and APIs.
Self-handled cards give you the flexibility to create card campaigns on the MoEngage Platform and display the cards anywhere within the application. The SDK provides APIs to fetch the campaign's data, which allows you to create your own custom view for the cards.
# SDK Installation
## Install using Swift Package Manager
MoEngageCards is supported through SPM from SDK version 3.2.0. To integrate use the following git hub url link and set the branch as master or version as 4.0.0 and above [https://github.com/moengage/MoEngage-iOS-Cards.git](https://github.com/moengage/MoEngage-iOS-Cards.git)
## Install using CocoaPod
**Information**
CocoaPods is being deprecated. MoEngage recommends using Swift Package Manager for all new integrations. For detailed info on cocoapods, refer to [CocoaPods Integration Guide](/developer-guide/ios-sdk/sdk-integration/basic/integration-through-cocoa-pods).
Integrate the MoEngageCards framework by adding the dependency in the podfile as shown below.
```ruby Ruby theme={null}
pod 'MoEngage-iOS-SDK/Cards',
```
Now run `pod install` to install the framework.
## Manual Integration
**Manual Integration**
To integrate the `MoEngageCards` SDK manually to your project follow this [doc](/developer-guide/ios-sdk/manual-integration/manual-integration).
## Notify on Section Load
You can show the cards on a separate screen or a section of the screen. When the cards screen/section is loaded call [*onCardSectionLoaded()*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKCards.html#/c:@M@MoEngageCards@objc\(cs\)MoEngageSDKCards\(im\)onCardSectionLoadedForAppID:withCompletion)
```swift Swift wrap theme={null}
MoEngageSDKCards.sharedInstance.onCardSectionLoaded(forAppID: "Your Workspace Id") { data in
print("Card section loaded, hasUpdates: \(data?.hasUpdates ?? false)")
}
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKCards sharedInstance] onCardSectionLoadedForAppID:@"Your Workspace Id"
withCompletion:^(MoEngageCardSyncCompleteData * _Nullable data) {
NSLog(@"Card section loaded, hasUpdates: %d", data.hasUpdates);
}];
```
Use the below APIs to fetch the card's data and build your own UI.
## Fetch Categories
To fetch all the categories for which cards are configured use the API [*getCardsCategories(forAppID:withCompletionBlock:)*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKCards.html#/c:@M@MoEngageCards@objc\(cs\)MoEngageSDKCards\(im\)getCardsCategoriesForAppID:withCompletionBlock:)
```swift Swift wrap theme={null}
MoEngageSDKCards.sharedInstance.getCardsCategories { categories, accountMeta in
print("Fetched Cards Categories \(categories)")
}
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKCards sharedInstance] getCardsCategoriesForAppID:@"Your Workspace Id" withCompletionBlock:^(NSArray * _Nonnull, MoEngageAccountMeta * _Nullable) {
NSLog(@"Fetched Cards Categories");
}];
```
## Fetch Cards for Categories
To fetch cards eligible for display for a specific category use the API [*getCards(forCategory:forAppID:withCompletionBlock:)*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKCards.html#/c:@M@MoEngageCards@objc\(cs\)MoEngageSDKCards\(im\)getCardsForCategory:forAppID:withCompletionBlock:)
```swift Swift wrap theme={null}
MoEngageSDKCards.sharedInstance.getCards(forCategory: "CATEGORY") { cards, accountMeta in
print("Fetched cards for given category")
}
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKCards sharedInstance] getCardsForCategory:@"CATEGORY" forAppID:@"YOUR Workspace ID" withCompletionBlock:^(NSArray * _Nonnull, MoEngageAccountMeta * _Nullable) {
NSLog(@"Fetched cards for given category");
}];
```
Instead of using separate APIs to fetch the Cards and categories you can use the method [*getCardsData(forAppID:withCompletionBlock:)*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKCards.html#/c:@M@MoEngageCards@objc\(cs\)MoEngageSDKCards\(im\)getCardsDataForAppID:withCompletionBlock:) to fetch all the information in one go.
```swift Swift wrap theme={null}
MoEngageSDKCards.sharedInstance.getCardsData { cardsData, accountMeta in
print("Cards category \(cardsData?.cardCategories)")
print("Cards Data \(cardsData?.cards)")
}
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKCards sharedInstance] getCardsDataForAppID:@"YOUR Workspace ID" withCompletionBlock:^(MoEngageCardsData * _Nullable, MoEngageAccountMeta * _Nullable) {
NSLog(@"Cards category %@", cardsData.cardCategories);
NSLog(@"Cards Data %@", cardsData.cards);
}];
```
## Track Statistics for Cards
Since the UI/display of the cards is controlled by the application to track statistics on delivery, display, click we need the application to notify the SDK.
### Delivered
To track delivery to the card section of the application use the API [*cardDelivered(\_:forAppID:)*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKCards.html#/c:@M@MoEngageCards@objc\(cs\)MoEngageSDKCards\(im\)cardDelivered:forAppID:) when the cards section of the application is loaded by passing the instance of [*MoEngageCardCampaign*](https://moengage.github.io/ios-api-reference/Classes/MoEngageCardCampaign.html).
```swift Swift wrap theme={null}
MoEngageSDKCards.sharedInstance.cardDelivered(cardCampaign, forAppID: "YOUR Workspace ID")
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKCards sharedInstance] cardDelivered:cardCamapigns forAppID:@"YOUR Workspace ID"];
```
### Impression
Call the method [*cardShown(\_:forAppID:)*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKCards.html#/c:@M@MoEngageCards@objc\(cs\)MoEngageSDKCards\(im\)cardShown:forAppID:) when a specific card is visible on the screen.
```swift Swift wrap theme={null}
MoEngageSDKCards.sharedInstance.cardShown(cardCampaign, forAppID: "YOUR Workspace ID")
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKCards sharedInstance] cardShown:cardCamapign forAppID:@"YOUR Workspace ID"];
```
### Click
Call the method [*cardClicked(\_:withWidgetID:forAppID:)*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKCards.html#/c:@M@MoEngageCards@objc\(cs\)MoEngageSDKCards\(im\)cardClicked:withWidgetID:forAppID:) whenever a user clicks on a card, along with the card object widget identifier for the UI element clicked should also be passed.
```swift Swift wrap theme={null}
MoEngageSDKCards.sharedInstance.cardClicked(cardCampaign, withWidgetID: widgetID);
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKCards sharedInstance] cardClicked:cardCamapigns withWidgetID:widgetID forAppID:@"YOUR Workspace ID"];
```
## Delete Card
Call the method [deleteCards(\_:forAppID:andCompletionBlock:)](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKCards.html#/c:@M@MoEngageCards@objc\(cs\)MoEngageSDKCards\(im\)deleteCards:forAppID:andCompletionBlock:) to delete a card by passing an array of [MoEngageCardCampaign](https://moengage.github.io/ios-api-reference/Classes/MoEngageCardCampaign.html) as parameter.
```swift Swift wrap theme={null}
MoEngageSDKCards.sharedInstance.deleteCards([cards]) { isDeleted, accountMeta in
print("Card deletion was \(isDeleted)")
}
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKCards sharedInstance] deleteCards:[cardCamapigns] forAppID:nil andCompletionBlock:^(BOOL isDeleted, MoEngageAccountMeta * _Nullable accountMeta) {
NSLog(@"Card deletion was %d", isDeleted);
}];
```
The above API has an overloaded method that accepts a list of cards to be deleted.
## Refresh Cards from the Server
Use the [*fetchCards(forAppID:withCompletion:)*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKCards.html#/c:@M@MoEngageCards@objc\(cs\)MoEngageSDKCards\(im\)fetchCardsForAppID:withCompletion:) API to refresh cards from the MoEngage server if required, [*MoEngageCardData*](https://moengage.github.io/ios-api-reference/Classes/MoEngageCardData.html) is provided in callback with refreshed [*MoEngageCardCampaign*](https://moengage.github.io/ios-api-reference/Classes/MoEngageCardCampaign.html) in *cards* property and account meta-data [*MoEngageAccountMeta*](https://moengage.github.io/ios-api-reference/Classes/MoEngageAccountMeta.html) in *accountMeta*.
```swift Swift wrap theme={null}
MoEngageSDKCards.sharedInstance.fetchCards { data in
print("Refreshed cards: \(data?.cards) for account \(data?.accountMeta)")
}
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKCards sharedInstance] fetchCardsForAppID:nil withCompletion:^(MoEngageCardData * _Nullable data) {
NSLog(@"Refreshed cards: %@ for account %@", data.cards, data.accountMeta);
}];
```
**Note**
* The SDK automatically refreshes/fetches cards from the MoEngage server whenever the application comes to the foreground.
* This API has a FUP if breached the existing cards i.e. the ones in the local storage of the device will be passed on in the callback.
# Release Checklist
Source: https://moengage.com/docs/developer-guide/ios-sdk/checklist/release-checklist
Verify your MoEngage iOS SDK integration against this checklist before submitting to the App Store.
Before making the AppStore release, make sure you have verified with the release checklist below:
# 1. Update MoEngage SDK
* Update MoEngage SDK to the current version. Check [release notes](/developer-guide/release-notes/ios-sdk/2023-and-older) to know the latest SDK version.
# 2. Set Correct AppID
* In case using multiple MoEngage apps, then make sure before releasing that the correct AppID is set while initializing the SDK.
* Make sure that the initializeProdWithApiKey method is called for the build, which is being submitted to AppStore; this is to make sure that the data is tracked in the Live environment of the MoEngage app. Refer to the [link](/developer-guide/ios-sdk/sdk-integration/basic/sdk-initialization) to know more.
# 3. Test Push Notifications and Verify APNS Certificate
* Make sure that the Production APNS certificate is uploaded to MoEngage dashboard settings in Live environment. And also, test the same by sending a few notifications before going live.
# 4. Tracking App Installs and Updates
* If you wish to run Install/Update campaigns, make sure you track the [same](/developer-guide/ios-sdk/data-tracking/basic/install-update-differentiation) (recommended but optional).
# 5. User Attribute Unique ID
* If the app has a Login feature, then make sure you are tracking the USER\_ATTRIBUTE\_UNIQUE\_ID attribute when the user logs in. Setting USER\_ATTRIBUTE\_UNIQUE\_ID is mandatory to tie a user across devices, installs/uninstalls, and across different platforms. Refer to this [link](/developer-guide/ios-sdk/data-tracking/basic/tracking-user-attributes).
* Also, make sure that the resetUser method is called on user logout. Refer to this [link](/developer-guide/ios-sdk/data-tracking/basic/tracking-user-attributes).
# 6. Setting User Attributes
* Make sure you are setting all the User Attributes required to target users based on these attributes across devices or installs. Also, this will help in the personalization of campaigns. Refer to the [link](/developer-guide/ios-sdk/data-tracking/basic/tracking-user-attributes) to know more.
# 7. Tracking Events
* Make sure you are tracking all the events based on which you can track the user behavior in the app and later use the same to create a campaign targeting appropriate users. Refer to the [link](/developer-guide/ios-sdk/data-tracking/basic/tracking-events) to know more.
# Compliance
Source: https://moengage.com/docs/developer-guide/ios-sdk/compliance/compliance
Manage data tracking opt-outs and IDFA/IDFV privacy controls in your iOS app using the MoEngage SDK.
# Opt-Out of Data Tracking
To disable data tracking by the SDK use [*disableDataTracking()*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKAnalytics.html#/c:@M@MoEngageAnalytics@objc\(cs\)MoEngageSDKAnalytics\(im\)disableDataTracking) method as shown below. Once you have opted out of data tracking you need to explicitly opt-in to start tracking any event OR attributes for the user.
```swift Swift wrap theme={null}
MoEngageSDKAnalytics.sharedInstance.disableDataTracking() //Opt out
MoEngageSDKAnalytics.sharedInstance.enableDataTracking() //Opt in
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKAnalytics sharedInstance] disableDataTracking]; //Opt out
[[MoEngageSDKAnalytics sharedInstance] enableDataTracking]; //Opt in
```
# IDFA and IDFV OptOuts
SDK tracks [IDFA](https://developer.apple.com/documentation/adsupport/asidentifiermanager/1614151-advertisingidentifier)(Advertising Identifier) by default as a UserAttribute, it's tracked only if the AdSupport, AppTrackingTransparency frameworks is included in the project and if the User has not limited Ad Tracking. In case you would want to opt-out of IDFA Tracking call the opt-out method as shown below:
```swift Swift wrap theme={null}
MoEngageSDKAnalytics.sharedInstance.disableIDFATracking() //Opt out
MoEngageSDKAnalytics.sharedInstance.enableIDFATracking() //Opt in
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKAnalytics sharedInstance] disableIDFATracking]; //Opt out
[[MoEngageSDKAnalytics sharedInstance] enableIDFATracking]; // Opt in
```
SDK also tracks [IDFV](https://developer.apple.com/documentation/uikit/uidevice/1620059-identifierforvendor)(Identifier for Vendor) by default as a device Identifier. In case you would want to opt-out of IDFV Tracking call the opt-out method as shown below:
```swift Swift wrap theme={null}
MoEngageSDKAnalytics.sharedInstance.disableIDFVTracking() //Opt out
MoEngageSDKAnalytics.sharedInstance.enableIDFVTracking() //Opt in
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKAnalytics sharedInstance] disableIDFVTracking]; //Opt out
[[MoEngageSDKAnalytics sharedInstance] enableIDFVTracking]; //Opt in
```
IDFA and IDFV opt-outs are available from SDK version 6.1.1
# Enable/Disable SDK
If you don't want the MoEngage SDK to track any user information or send any data to the MoEngage System use the below method:
```swift Swift theme={null}
MoEngage.sharedInstance.disableSDK()
```
```objective-c Objective C theme={null}
[[MoEngage sharedInstance] disableSDK];
```
Once this API is called all the SDK APIs will be non-operational. SDK will be disabled until [*enableSDK()*](https://moengage.github.io/ios-api-reference/Classes/MoEngage.html#/c:@M@MoEngageSDK@objc\(cs\)MoEngage\(im\)enableSDK) is called.
Once you have the user's consent use the below API to enable the SDK.
```swift Swift theme={null}
MoEngage.sharedInstance.enableSDK()
```
```objective-c Objective C theme={null}
[[MoEngage sharedInstance] enableSDK];
```
Enable/Disable SDK methods are available from SDK version 6.3.0.
# Offerings Events Tracking
Source: https://moengage.com/docs/developer-guide/ios-sdk/data-tracking/advanced/offerings-events-tracking
Report impression and click events for offerings from the MoEngage Personalize API in your iOS app.
This document outlines the new methods available in the MoEngage iOS SDK to report impressions and clicks for offerings fetched using the [MoEngage Personalize API](https://www.moengage.com/docs/api/experiences/fetch-experience). These methods are currently available only for the **iOS SDK**.
# Prerequisites
## SDK version
You must update your Native iOS SDK version to **10.01.0** or higher.
## MoEngage Account Configuration
Ensure your MoEngage workspace is enabled to utilize the Personalize API. Refer to [this article](https://help.moengage.com/hc/en-us/articles/24644175705236-Create-Server-side-Personalization-offering) for details on setting up Personalize API offerings.
# Reporting offering Shown events
The SDK provides helper APIs to track shown events, refer the [API documentation](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKAppPersonalization.html) for more details.
Impressions should be reported when an offering is visually presented to the user.
## Single offering
To report an impression for a single offering, pass the **offeringContext** as a map.
```swift Swift wrap theme={null}
MoEngageSDKAppPersonalization.sharedInstance.offeringShown(offeringAttributes: offeringContext)
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKAppPersonalization sharedInstance] offeringShownWithofferingAttributes:offeringContext];
```
## Multiple offerings
To track the offering shown event for multiple offerings use, pass the **list** of **offering\_context** of each offering as a map.
```swift Swift wrap theme={null}
MoEngageSDKAppPersonalization.sharedInstance.offeringShown(offeringAttributes: [offeringContext1, offeringContext2, offeringContext3])
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKAppPersonalization sharedInstance] offeringShownWithofferingAttributes:@[offeringContext1, offeringContext2, offeringContext3]];
```
# Reporting offering Clicked events
The SDK provides helper APIs to track clicked events, refer the [API documentation](https://moengage.github.io/android-api-reference/campaigns-core/com.moengage.campaigns.personalize/-mo-e-personalize-helper/index.html) for more details.
Clicked events should be reported when a user clicks on any offering contained in the response of the Personalize API.
## Single offering
To report a click event for a single offering, pass the **offeringContext** of the experience as a map.
```swift Swift wrap theme={null}
MoEngageSDKAppPersonalization.sharedInstance.offeringClicked(offeringAttributes: offeringAttributes, withExperienceAttributes: experienceAttributes)
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKAppPersonalization sharedInstance] offeringClickedWithofferingAttribute:offeringContext];
```
## Multiple offerings
To track the offering clicked event for multiple experiences, pass the **list** of **offeringContext** as a map.
Clicked events should be reported when a user clicks on any offering contained in the response of the Personalize API. To report a click event for a single offering, pass the **offeringContext** of the offering as a map. When a user clicks on an Offering, we understand that they are also implicitly clicking on the parent Experience. You can now optionally pass the experienceContext to the **offeringClicked** function.
### **What this means**
* **If you pass both contexts:** MoEngage will **automatically** track clicks for **both** the Offering and the Experience. You no longer need to make a second, separate call to track the click event for the parent experience.
* **If you only pass the offeringContext:** The experienceContext is optional. If you don't pass it, we will only track the click for the Offering. You would then need to track the experience click separately, if required.
```swift Swift wrap theme={null}
MoEngageSDKAppPersonalization.sharedInstance.offeringClicked(offeringAttributes: [offeringContext1, offeringContext2, offeringContext3])
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKAppPersonalization sharedInstance] offeringClickedWithofferingAttributes:@[offeringContext1, offeringContext2, offeringContext3]];
```
# Personalize Experience Events tracking
Source: https://moengage.com/docs/developer-guide/ios-sdk/data-tracking/advanced/personalize-experience-events-tracking
Report impression and click events for experiences from the MoEngage Personalize API in your iOS app.
This document outlines the new methods available in the MoEngage iOS SDK to report impressions and clicks for experiences fetched using the [MoEngage Personalize API](https://www.moengage.com/docs/api/experiences/fetch-experience). These methods are currently available only for the **iOS SDK**.
# Prerequisites
## SDK version
You must update your Native iOS SDK version to **10.01.0** or higher.
## MoEngage Account Configuration
Ensure your MoEngage workspace is enabled to utilize the Personalize API. Refer to [this article](https://help.moengage.com/hc/en-us/articles/24644175705236-Create-Server-side-Personalization-Experience) for details on setting up Personalize API experiences.
# Reporting Experience Shown events
The SDK provides helper APIs to track shown events, refer the [API documentation](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKAppPersonalization.html) for more details.
Impressions should be reported when an experience is visually presented to the user.
## Single Experience
To report an impression for a single experience, pass **experience\_context** of the experience as a map.
**experience\_context** is a JSON object that is returned as part of the response [of the Personalize API request](https://www.moengage.com/docs/api/experiences/fetch-experience#response-experiences-additional-properties-experience-context).
```swift Swift wrap theme={null}
MoEngageSDKAppPersonalization.sharedInstance.experienceShown(experienceAttribute: experienceContext)
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKAppPersonalization sharedInstance] experienceShownWithExperienceAttribute:experienceContext];
```
## Mulitple Experiences
To track the experience shown event for multiple experiences use, pass the **list** of **experience\_context** of each experience as a map.
```swift Swift wrap theme={null}
MoEngageSDKAppPersonalization.sharedInstance.experienceShown(experienceAttributes: [experienceContext1, experienceContext2, experienceContext3])
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKAppPersonalization sharedInstance] experienceShownWithExperienceAttributes:@[experienceContext1, experienceContext2, experienceContext3]];
```
# Reporting Experience Clicked events
The SDK provides helper APIs to track clicked events, refer the [API documentation](https://moengage.github.io/android-api-reference/campaigns-core/com.moengage.campaigns.personalize/-mo-e-personalize-helper/index.html) for more details.
Clicked events should be reported when a user clicks on any element that has been personalized using the response of the Personalize API.
## Single Experience
To report a click event for a single experience, pass the **experience\_context** of the experience as a map.
```swift Swift wrap theme={null}
MoEngageSDKAppPersonalization.sharedInstance.experienceClicked(experienceAttribute: experienceContext)
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKAppPersonalization sharedInstance] experienceClickedWithExperienceAttribute:experienceContext];
```
## Multiple Experiences
To track the experience shown event for multiple experiences use, pass the **array** of **experience\_context** of each experience as a map.
```swift Swift wrap theme={null}
MoEngageSDKAppPersonalization.sharedInstance.experienceClicked(experienceAttributes: [experienceContext1, experienceContext2, experienceContext3])
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKAppPersonalization sharedInstance] experienceClickedWithExperienceAttributes:@[experienceContext1, experienceContext2, experienceContext3]];
```
You can optionally include a **b\_id** key in the **experience\_context** object to provide additional context about the click. Its value should describe the specific component or interaction within the experience that was clicked. This is particularly useful for experiences composed of multiple interactive elements, helping to distinguish between clicks on different parts of the same overall experience.
# Session and Source Tracking
Source: https://moengage.com/docs/developer-guide/ios-sdk/data-tracking/advanced/session-and-source-tracking
Track user sessions and deep-link source information in your iOS app using the MoEngage SDK.
From [SDK Version 5.2.2](/developer-guide/release-notes/ios-sdk/2023-and-older) we have started supporting Session and Source Tracking, and this is enabled by default in the SDK.
**Note**
* To view Session And Source information tracked in the dashboard, get the same enabled by contacting the MoEngage support team.
* To track source information accurately, make use of the UTM parameters in your deep links and push notification payloads.
# Capture Deep-link Source
**AppDelegate Swizzling**
Calling of [*processURL(\_:)*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKAnalytics.html#/c:@M@MoEngageAnalytics@objc\(cs\)MoEngageSDKAnalytics\(im\)processURL:) method is not required if AppDelegate Swizzling is enabled for SDK. For more info on AppDelegate Swizzling, refer to this [link](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial##app-delegate-method-swizzling).
For capturing source information via the deep-link call [*processURL(\_:)*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKAnalytics.html#/c:@M@MoEngageAnalytics@objc\(cs\)MoEngageSDKAnalytics\(im\)processURL:) method in all the AppDelegate callbacks that you receive when a link is opened, please refer to the code block below.
```swift Swift wrap theme={null}
//MARK:- Deeplinks Processing
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
MoEngageSDKAnalytics.sharedInstance.processURL(url)
//rest of the implementation
return true
}
func application(_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool
{
if userActivity.activityType == NSUserActivityTypeBrowsingWeb ,
let incomingURL = userActivity.webpageURL{
MoEngageSDKAnalytics.sharedInstance.processURL(incomingURL)
}
//rest of the implementation
return true;
}
//MARK:- Methods Deprecated from iOS9
func application(_ application: UIApplication, handleOpen url: URL) -> Bool {
MoEngageSDKAnalytics.sharedInstance.processURL(url)
//rest of the implementation
return true
}
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
MoEngageSDKAnalytics.sharedInstance.processURL(url)
//rest of the implementation
return true
}
```
# Non-Interactive Event
Events that should not affect the session duration calculation in anyways in MoEngage Analytics should be marked as a Non-Interactive event.
These events:
* Do not start a new session, even when the app is in the foreground
* Do not extend the session
* Do not have information on source and session
For example, events that are tracked when the app is in the background to refresh the app content, are not initiated by users and hence can be marked as non-interactive. To mark an event as non-interactive use [*setNonInteractive()*](https://moengage.github.io/ios-api-reference/Classes/MoEngageProperties.html#/c:@M@MoEngageAnalytics@objc\(cs\)MoEngageProperties\(im\)setNonInteractive) method of [*MoEngageProperties*](https://moengage.github.io/ios-api-reference/Classes/MoEngageProperties.html) while tracking the event as shown below:
```swift Swift wrap theme={null}
//Set Attributes
let dict = ["NewsCategory":"Politics"]
let properties = MoEngageProperties(withAttributes: dict)
properties.addDateAttribute(Date(), withName:"refreshTime")
//Set the Event as Non-Interactive
properties.setNonInteractive()
//Track event
MoEngageSDKAnalytics.sharedInstance.trackEvent("App Content Refreshed", withProperties: properties)
```
```objective-c Objective C wrap theme={null}
//Set Attributes
NSMutableDictionary *eventDict = [NSMutableDictionary dictionary];
eventDict[@"NewsCategory"] = @"Politics";
MoEngageProperties* properties = [[MoEngageProperties alloc] initWithAttributes:eventDict];
[properties addDateAttribute:[NSDate date] withName:@"refreshTime"];
//Set the Event as Non-Interactive
[properties setNonInteractive];
//Track event
[[MoEngageSDKAnalytics sharedInstance] trackEvent:@"App Content Refreshed" withProperties:properties];
```
# Tracking Locale
Source: https://moengage.com/docs/developer-guide/ios-sdk/data-tracking/advanced/tracking-locale
Track the locale settings of your user's device in your iOS app using the MoEngage SDK.
For tracking the locale settings of the user device use [*trackLocale()*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKAnalytics.html#/c:@M@MoEngageAnalytics@objc\(cs\)MoEngageSDKAnalytics\(im\)trackLocale) method as shown below:
```swift Swift wrap theme={null}
MoEngageSDKAnalytics.sharedInstance.trackLocale()
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKAnalytics sharedInstance] trackLocale];
```
# Install/Update differentiation
Source: https://moengage.com/docs/developer-guide/ios-sdk/data-tracking/basic/install-update-differentiation
Differentiate between app installs and updates in your iOS app using the MoEngage appStatus API.
Since you might integrate us when your app is already on the App Store, we would need to know whether your app update would be an actual **UPDATE** or an **INSTALL**. Have a logic in place to differentiate between the two, and use the methods below to let the SDK know about the same:
```swift Swift wrap theme={null}
//For Fresh Install of App
MoEngageSDKAnalytics.sharedInstance.appStatus(.install)
// For Existing user who has updated the app
MoEngageSDKAnalytics.sharedInstance.appStatus(.update)
```
```objective-c Objective C theme={null}
//For Fresh Install of App
[[MoEngageSDKAnalytics sharedInstance]appStatus:MoEngageAppStatusInstall];
// For Existing user who has updated the app
[[MoEngageSDKAnalytics sharedInstance]appStatus:MoEngageAppStatusUpdate];
```
# Setting Unique Id for SDK versions below 9.23.0
Source: https://moengage.com/docs/developer-guide/ios-sdk/data-tracking/basic/setting-unique-id-for-sdk-versions-below-9-23-0
Set a unique user ID for login and logout in MoEngage iOS SDK versions below 9.23.0.
# User Login / Logout
It is important that you handle user login and logout as mentioned below. There is a definite possibility that your data gets corrupted if this is not done properly.
* Make sure to get hold of a `unique id` for your app users and pass that information to our SDK using the [*setUniqueID(\_:)*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKAnalytics.html#/c:@M@MoEngageAnalytics@objc\(cs\)MoEngageSDKAnalytics\(im\)setUniqueID:) \[Link]method. We use this `unique id` to identify a user and also to merge user profiles across installs and platforms.
* And also, once the user logs out of your app, it is necessary to call [*resetUser()*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKAnalytics.html#/c:@M@MoEngageAnalytics@objc\(cs\)MoEngageSDKAnalytics\(im\)resetUser) \[Link]of SDK so that we create a new anonymous user and track the events following this to the new user's profile.
Kindly ensure you call the following methods on user login/logout.
## Login
```swift Swift wrap theme={null}
MoEngageSDKAnalytics.sharedInstance.setUniqueID(UNIQUE_ID) // UNIQUE_ID is used to uniquely identify a user.
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKAnalytics sharedInstance] setUniqueID:UNIQUE_ID]; // UNIQUE_ID is used to uniquely identify a user.
```
The following values are not allowed in the UniqueID field: "unknown", "guest", "null", "0", "1", "true", "false", "user\_attribute\_unique\_id", "(empty)", "na", "n/a", "", "dummy\_seller\_code", "user\_id", "id", "customer\_id", "uid", "userid", "none", "-2", "-1", "2"
**UNIQUE ID chaos**
* When you go live with MoEngage iOS SDK for the first time, please ensure that you are setting the **Unique ID** of the already logged-in user along with other user attributes.
* Kindly make sure that you are not using a single unique id for all the users, this can happen if you hard code the value, instead of fetching it from your servers.
* If you pass 2 different unique id information without calling [*resetUser()*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKAnalytics.html#/c:@M@MoEngageAnalytics@objc\(cs\)MoEngageSDKAnalytics\(im\)resetUser) method in between, the SDK will internally force logout the existing user.
## Logout
```swift Swift wrap theme={null}
MoEngageSDKAnalytics.sharedInstance.resetUser()
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKAnalytics sharedInstance] resetUser];
```
# Updating User Attribute Unique ID
**Important**
Please make sure that you use [*setAlias(\_:)*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKAnalytics.html#/c:@M@MoEngageAnalytics@objc\(cs\)MoEngageSDKAnalytics\(im\)setAlias:)\[Link] for updating the User Attribute Unique ID and not [*setUniqueID(\_:)*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKAnalytics.html#/c:@M@MoEngageAnalytics@objc\(cs\)MoEngageSDKAnalytics\(im\)setUniqueID:) \[Link]as calling [*setUniqueID(\_:)*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKAnalytics.html#/c:@M@MoEngageAnalytics@objc\(cs\)MoEngageSDKAnalytics\(im\)setUniqueID:) \[Link]with a new value will reset the current user and lead to the creation of unintended users in our system.
In a scenario where you have to update the existing user's Unique ID value make use of [*setAlias(\_:)*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKAnalytics.html#/c:@M@MoEngageAnalytics@objc\(cs\)MoEngageSDKAnalytics\(im\)setAlias:) \[Link]method as shown below with the updated Unique ID value:
```swift Swift wrap theme={null}
MoEngageSDKAnalytics.sharedInstance.setAlias(UPDATED_UNIQUE_ID)
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKAnalytics sharedInstance] setAlias:UPDATED_UNIQUE_ID];
```
# Tracking events
Source: https://moengage.com/docs/developer-guide/ios-sdk/data-tracking/basic/tracking-events
Track custom user events and their attributes in your iOS app using the MoEngage SDK.
Event tracking is used to track user behavior in an app. And later based on the same tracked behavior you can target those users for sending relevant notifications. Make sure to track all the events relevant to your business, so that your product managers and marketers can segment your app users and create targeted campaigns. For eg. You can track what a user is purchasing, whether has a user added an item to the cart etc.
**Info**
* We track certain events by default in our SDK, so please make sure to use the default events instead of tracking a new event for the same scenarios. Find the list of default events tracked by SDK [here](https://help.moengage.com/hc/en-us/articles/360042512472-Default-iOS-SDK-Data-Collection#Default-Events-Tracked:).
* SDK adheres to the MoEngage FUP policies. For more information, refer to the [Fair Usage Policy](https://help.moengage.com/hc/en-us/articles/24151864954644-Fair-Usage-Policy-FUP#h_01HQSMZVQWT2KYP0PY1P8GQMRM).
# How to track events?
Every event has 2 parts to it, the "**name**" of the event and the **properties/attributes** of the event. You have to make use of [*MoEngageProperties*](https://moengage.github.io/ios-api-reference/Classes/MoEngageProperties.html) to track events and their attributes.
For eg. The following code tracks a `Successful Purchase` event. We are including attributes like the Product Name, a Brand Name that describes the event we are tracking.
```swift Swift wrap theme={null}
var eventAttrDict : Dictionary = Dictionary()
eventAttrDict["ProductName"] = "iPhone XS Max"
eventAttrDict["BrandName"] = "Apple"
eventAttrDict["Items In Stock"] = 109
let eventProperties = MoEngageProperties(withAttributes: eventAttrDict)
eventProperties.addAttribute(87000.00, withName: "price")
eventProperties.addAttribute("Rupees", withName: "currency")
eventProperties.addAttribute(true, withName: "in_stock")
eventProperties.addDateEpochAttribute(1439322197, withName: "Time added to cart")
eventProperties.addDateISOStringAttribute("2020-02-22T12:37:56Z", withName: "Time of checkout")
eventProperties.addDateAttribute(Date(), withName: "Time of purchase")
eventProperties.addLocationAttribute(MoEngageGeoLocation.init(withLatitude: 12.23, andLongitude: 9.23), withName: "Pickup Location")
/// JSON is supported from MoEngage-iOS-SDK v9.17.5
eventProperties.addAttribute(["merchantId": "abcdef","business_model": [ "admin_email": "abc@email.com","admin_comment": "payment" ]],withName: "merchant")
eventProperties.addAttribute([["merchantId": "abcdef", "business_model": ["admin_email": "abc@email.com", "admin_comment": "first"]], ["merchantId": "ghijk", "business_model": ["admin_email": "def@email.com", "admin_comment": "second"]]], withName: "retries")
MoEngageSDKAnalytics.sharedInstance.trackEvent("Successful Purchase", withProperties: eventProperties)
```
```objective-c Objective C wrap theme={null}
// track event example
NSMutableDictionary* eventAttrDict = [NSMutableDictionary dictionary];
eventAttrDict[@"ProductName"] = @"iPhone XS Max";
eventAttrDict[@"BrandName"] = @"Apple";
eventAttrDict[@"Items In Stock"] = @109;
MoEngageProperties* eventProperties = [[MoEngageProperties alloc] initWithAttributes:eventAttrDict];
[eventProperties addAttribute:@87000.00 withName:@"price"];
[eventProperties addAttribute:@"Rupees" withName:@"currency"];
[eventProperties addAttribute:[NSNumber numberWithBool:true] withName:@"in_stock"];
[eventProperties addDateEpochAttribute:1439322197 withName:@"Time added to cart"];
[eventProperties addDateISOStringAttribute:@"2020-02-22T12:37:56Z" withName:@"Time of checkout"];
[eventProperties addDateAttribute:[NSDate date] withName:@"Time of purchase"];
MoEngageGeoLocation* pickupLocation = [[MoEngageGeoLocation alloc] initWithLatitude:12.23 andLongitude:9.23];
[eventProperties addLocationAttribute:pickupLocation withName:@"Pickup Location"];
/// JSON is supported from MoEngage-iOS-SDK v9.17.5
[eventProperties addAttribute:@{@"merchantId": @"abcdef",@"business_model": @{@"admin_email": @"abc@email.com",@"admin_comment": @"payment"}} withName:@"merchant"];
[eventProperties addAttribute:@[@{@"merchantId":@"abcdef",@"business_model":@{@"admin_email":@"abc@email.com",@"admin_comment":@"first"}},@{@"merchantId":@"ghijk",@"business_model":@{@"admin_email":@"def@email.com",@"admin_comment":@"second"}}] withName:@"retries"];
[[MoEngageSDKAnalytics sharedInstance] trackEvent:@"Successful Purchase" withProperties:eventProperties];
```
**Non-Interactive Events**
Events that should not affect the session duration calculation in anyways in MoEngage Analytics should be marked as a Non-Interactive events. Refer to [this](/developer-guide/ios-sdk/data-tracking/advanced/session-and-source-tracking) for more info on the same.
Ensure that you are tracking event attributes without changing their data types. Also, make sure the attributes have the same data type across platforms. For instance, in the above purchase event, price is tracked in the numeric form, therefore when the same event is tracked in Android SDK make sure to track it as a number and not a string. Our system detects the data type automatically unless you explicitly specify it as a string.
**Restrictions**
* Event names and attributes should not contain any special characters other than "\_". It can contain spaces and underscore.
* In the SDK we reject events with invalid event attributes. Event attribute values can only have Strings, Numbers & an array(strings or numbers), or else events might get rejected.
* Having unique timestamps for events is crucial to maintain accurate and reliable data. Please ensure that events do not share the same timestamp down to the millisecond level.
If you don’t have any attributes, just pass **nil** as the second argument. For eg.
```swift Swift wrap theme={null}
MoEngageSDKAnalytics.sharedInstance.trackEvent("Event Name", withProperties: nil)
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKAnalytics sharedInstance] trackEvent:@"Event Name" withProperties:nil];
```
**Note**
You can not use "moe\_" as a prefix while naming events, event attributes, or user attributes. It is a system prefix and using it might result in periodic blacklisting without prior communication.
# Manual Sync
For syncing the tracked events instantaneously, use the [*flush()*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKAnalytics.html#/c:@M@MoEngageAnalytics@objc\(cs\)MoEngageSDKAnalytics\(im\)flush) method as shown below:
```swift Swift wrap theme={null}
MoEngageSDKAnalytics.sharedInstance.flush()
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKAnalytics sharedInstance] flush];
```
# Testing events after integration
Login to the MoEngage account with the credentials provided for your app.
Look at the top left and Switch to the **Test** environment. Ensure that your testing is done on the test environment to keep the test data separate from the Live data. Ensure you have [Initialized the SDK](/developer-guide/ios-sdk/sdk-integration/basic/sdk-initialization).
After adding event tracking in the app, as shown above, you can visit Dashboard > Recent Events to check whether the events are being tracked.
*Events can take up to 20 minutes to show up in the dashboard*
While testing it is recommended to enable [logs in Debug Mode](/developer-guide/ios-sdk/troubleshooting-and-faqs/troubleshooting-and-faqs-ios).
SDK prints a list of all events which are synced in the current flush, so you can always refer to the logs to check if the events tracked by you are being sent to the backend or not. Also, logs provide info about if the sync with the backend was successful or not. (In case it is unsuccessful, SDK saves all the tracked events and attempts to sync again in the next flush attempt).
# Tracking user attributes
Source: https://moengage.com/docs/developer-guide/ios-sdk/data-tracking/basic/tracking-user-attributes
Track user attributes and set unique identifiers for cross-platform identification in the iOS SDK.
User Attributes are pieces of information you know about a user. They could be demographics like age or gender, account-specific like plan, or whether a user has seen a particular A/B test variation. User attributes are a customer identity you can reference throughout the customer’s lifetime.
# Identifying Users
For SDK versions below 9.23.0 refer to [this document](/developer-guide/ios-sdk/data-tracking/basic/setting-unique-id-for-sdk-versions-below-9-23-0).
Setting identifiers is important to:
* To tie user behavior across platforms, i.e., iOS, Android, Web, etc.
* This is to ensure unnecessary or stale users are not created.
* To identify users across installs/re-installs.
## Single Identifier
Call the API below to pass the identifier on to the MoEngage SDK.
```swift Swift wrap theme={null}
MoEngageSDKAnalytics.sharedInstance.identifyUser(identity: "identifier")
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKAnalytics sharedInstance] identifyUserWithIdentity:@"identifier" workspaceId:nil];
```
This method is a replacement for the deprecated ***setUniqueId()***. If you are using \*\*\*setUniqueId() \*\*\*in your application, consider replacing it with ***identifyUser()**\*\*.*
## Multiple Identifiers
If your application has multiple identifiers using which you identify a user you can pass all the identifiers to the SDK using the below API.
```swift Swift wrap theme={null}
MoEngageSDKAnalytics.sharedInstance.identifyUser(
identities: [
"identifierName1": "identifierValue1", "identifierName2" to "identifierValue2"
]
)
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKAnalytics sharedInstance] identifyUserWithIdentities:@{
"identifierName1": "identifierValue1", "identifierName2" to "identifierValue2"
} workspaceId:nil];
```
If you call `identifyUser()` multiple times with different identifier names, the SDK will append this identifier to the already set identifiers.
**Information**
Updates are made to SDK functions to improve user identification and session management.
* **Forced Logout**: The MoEngage SDK no longer automatically logs out the previous user when a new user is detected on the device. Logout should now be explicitly called for workspaces enabled with Identity resolution to avoid data corruption.
* **SetUniqueID**: *IdentifyUser* function supports multiple identifiers, which replaces the need of using *SetUniqueID* function for user identification. Note that *SetUniqueID* is marked for removal in the future releases of SDK versions - it is important to use *identifyUser* instead especially if you are using Identity resolution in your workspace.
* **SetAlias**: For workspaces with the Identity resolution feature enabled, MoEngage SDK stores the previous identifier values. When *IdentifyUser* function is used to track the new identifier values, MoEngage SDK detects the change in identifier value and reports accordingly.
* If you call the *IdentifyUser* function without logging out, then the existing logged-in user's ID is updated.
Refer to our help [document](https://help.moengage.com/hc/en-us/articles/24050999467284-User-Identity-Management) to learn more about the feature.
## Logout
The application needs to notify the MoEngage SDK whenever the user is logged out of the application. Call the API whenever the user is logged out of the application to notify the SDK.
```swift Swift wrap theme={null}
MoEngageSDKAnalytics.sharedInstance.resetUser()
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKAnalytics sharedInstance] resetUser];
```
# Default User Attributes
Some default SDK User Attribute can be set for eg. email-id, mobile number, gender, user name, birthday. The default attributes tracked by SDK can be set as shown below:
```swift Swift wrap theme={null}
MoEngageSDKAnalytics.sharedInstance.setName(userName)
MoEngageSDKAnalytics.sharedInstance.setLastName(userLastname)
MoEngageSDKAnalytics.sharedInstance.setFirstName(userFirstName)
MoEngageSDKAnalytics.sharedInstance.setEmailID(userEmailID)
MoEngageSDKAnalytics.sharedInstance.setMobileNumber(userPhoneNo)
MoEngageSDKAnalytics.sharedInstance.setGender(.male) //Use UserGender enumerator for this
MoEngageSDKAnalytics.sharedInstance.setDateOfBirth(userBirthdate)//userBirthdate should be a Date instance
MoEngageSDKAnalytics.sharedInstance.setLocation(MoEngageGeoLocation(withLatitude: userLocationLat, andLongitude: userLocationLng)) //userLocationLat and userLocationLng are double values of the location coordinates
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKAnalytics sharedInstance] setName:userName];
[[MoEngageSDKAnalytics sharedInstance] setLastName:userLastname];
[[MoEngageSDKAnalytics sharedInstance] setFirstName:userFirstName];
[[MoEngageSDKAnalytics sharedInstance] setEmailID:userEmailID];
[[MoEngageSDKAnalytics sharedInstance] setMobileNumber:userPhoneNo];
[[MoEngageSDKAnalytics sharedInstance] setGender:UserGenderMale]; // Use UserGender enumerator for this
[[MoEngageSDKAnalytics sharedInstance] setDateOfBirth:userBirthdate];//userBirthdate should be a NSDate instance
[[MoEngageSDKAnalytics sharedInstance] setLocation:[[MoEngageGeoLocation alloc] initWithLatitude:userLocationLat andLongitude:userLocationLng]];//userLocationLat and userLocationLng are double values of the location coordinates
```
**Note**
* We support strings and numbers as values for UserAttributes. NSURL is not supported. If you wish to use it, please convert them to string.
* User Phone No / Mobile Number must be tracked as a string to work properly in MoEngage systems.
* For more information on supported data types and data tracking policies, please refer to [Data Tracking Policies](https://help.moengage.com/hc/en-us/articles/360037314991#h_01H9QNZ61VNHSMFQC28MAZJXS9).
# Custom User Attributes
To set custom attributes just provide custom keys different to the ones present in [here](https://help.moengage.com/hc/en-us/articles/360042512472-Default-iOS-SDK-Data-Collection#%5BhardBreak%5DDefault-User-Attributes-Tracked:). Following is an example:
```swift Swift wrap theme={null}
MoEngageSDKAnalytics.sharedInstance.setUserAttribute("Bengaluru", withAttributeName: "Current_city")
MoEngageSDKAnalytics.sharedInstance.setUserAttribute(["Bengaluru","Delhi","Chennai"], withAttributeName: "Current_cities")
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKAnalytics sharedInstance] setUserAttribute:@"Bengaluru" withAttributeName:@"Current_city"];
NSArray *myArray = @[@"Bengaluru", @"Delhi", @"Chennai"];
[[MoEngageSDKAnalytics sharedInstance] setUserAttribute:myArray withAttributeName:@"Current_cities"];
```
User Attributes have the following restrictions :
* User Attribute Names should not contain dot(.)
* User Attribute Names should not start with dollar sign(\$)
* User Attribute Values should be a String or Number
**Note**
You can not use "moe\_" as a prefix while naming events, event attributes, or user attributes. It is a system prefix and using it might result in periodic blacklisting without prior communication.
## JSON Attributes
From MoEngage-iOS-SDK ***v9.17.5***, we have added support for JSON and array of JSON user attributes. Following is an example:
```swift Swift wrap theme={null}
MoEngageSDKAnalytics.sharedInstance.setUserAttribute(["item-id" : 123,"item-type" : "books","item-cost" : ["amount" : 100,"currency" : "USD"]],withAttributeName: "product")
MoEngageSDKAnalytics.sharedInstance.setUserAttribute([["item-id" : 123,"item-cost" : ["amount" : 100,"currency" : "USD"]],["item-id" : 323,"item-cost" : ["amount" : 90,"currency" : "USD"]]],withAttributeName: "products")
```
```objective-c Objective C wrap theme={null}
[MoEngageSDKAnalytics.sharedInstance setUserAttribute:@{@"item-id" : @123,@"item-type" : @"books",@"item-cost" : @{@"amount" : @100,@"currency" : @"USD"}} withAttributeName:@"product"];
[MoEngageSDKAnalytics.sharedInstance setUserAttribute:@[@{@"item-id" : @123,@"item-cost" : @{@"amount" : @100,@"currency" : @"USD"}} , @{@"item-id" : @323,@"item-cost" : @{@"amount" : @90,@"currency" : @"USD"}}] withAttributeName:@"products"];
```
# Date and Time User Attributes
Date and time attributes can be set as user attributes. For this refer to the methods in the code block below:
```swift Swift wrap theme={null}
//1. Track UserAttribute using Date instance
MoEngageSDKAnalytics.sharedInstance.setUserAttributeDate(Date(), withAttributeName: "Date Attr 1")
//2. Track UserAttribute using ISO Date String in format "yyyy-MM-dd'T'HH:mm:ss'Z'"
MoEngageSDKAnalytics.sharedInstance.setUserAttributeISODate("2020-01-12T18:45:59Z", withAttributeName: "Date Attr 2")
//3. Track UserAttribute using Epoch value
MoEngageSDKAnalytics.sharedInstance.setUserAttributeEpochTime(663333, withAttributeName: "Date Attr 3")
```
```objective-c Objective C wrap theme={null}
//1. Track UserAttribute using Date instance
[[MoEngageSDKAnalytics sharedInstance] setUserAttributeDate:[NSDate date] withAttributeName:@"DateAttr1"];
//2. Track UserAttribute using ISO Date String in format "yyyy-MM-dd'T'HH:mm:ss'Z'"
[[MoEngageSDKAnalytics sharedInstance] setUserAttributeISODate:@"2020-01-12T18:45:59Z" withAttributeName:@"DateAttr2"];
//3. Track UserAttribute using Epoch value
double timestampEpochValue = [[NSDate date] timeIntervalSince1970];
[[MoEngageSDKAnalytics sharedInstance] setUserAttributeEpochTime:timestampEpochValue withAttributeName:@"LastPurchaseDate"];
```
# Location Attributes
The location of a user or any location can be set as user attribute. For this use [*setLocation(\_:withAttributeName:)*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKAnalytics.html#/c:@M@MoEngageAnalytics@objc\(cs\)MoEngageSDKAnalytics\(im\)setLocation:withAttributeName:) method and pass lat, the long value of the location as shown in the following example:
```swift Swift wrap theme={null}
MoEngageSDKAnalytics.sharedInstance.setLocation(MoEngageGeoLocation.init(withLatitude: 72.90909, andLongitude: 12.34567), withAttributeName: "attribute name")
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKAnalytics sharedInstance] setLocation:[[MoEngageGeoLocation alloc] initWithLatitude:23.33 andLongitude:26.22] withAttributeName:@"attribute name"];
```
## Reserved keywords for User Attributes
Below is the list of keys that should not be used when tracking user attributes.
* USER\_ATTRIBUTE\_UNIQUE\_ID
* USER\_ATTRIBUTE\_USER\_EMAIL
* USER\_ATTRIBUTE\_USER\_MOBILE
* USER\_ATTRIBUTE\_USER\_NAME
* USER\_ATTRIBUTE\_USER\_GENDER
* USER\_ATTRIBUTE\_USER\_FIRST\_NAME
* USER\_ATTRIBUTE\_USER\_LAST\_NAME
* USER\_ATTRIBUTE\_USER\_BDAY
* MOE\_TIME\_FORMAT
* MOE\_TIME\_TIMEZONE
* USER\_ATTRIBUTE\_NOTIFICATION\_PREF
* USER\_ATTRIBUTE\_OLD\_ID
* MOE\_TIME\_FORMAT
* MOE\_TIME\_TIMEZONE
* USER\_ATTRIBUTE\_DND\_START\_TIME
* USER\_ATTRIBUTE\_DND\_END\_TIME
* MOE\_GAID
* MOE\_ISLAT
* INSTALL
* UPDATE
* status
* user\_id
# Framework Size Impact
Source: https://moengage.com/docs/developer-guide/ios-sdk/framework-size-impact/framework-size-impact
Review the compressed and uncompressed size impact of each MoEngage iOS SDK framework.
We developed a sample application to evaluate the impact of our SDK size. We then uploaded the application build with various configurations to App Store Connect. This allowed us to estimate both the compressed (the download size of our app) and uncompressed size (the disk space the app occupies on the user's device).
**SDK versions for analysis**
* [MoEngage-iOS-SDK](https://cocoapods.org/pods/MoEngage-iOS-SDK) - 9.14.0
* [MoEngageRichNotification](https://cocoapods.org/pods/MoEngageRichNotification) - 7.13.0
* [MoEngageInApp](https://cocoapods.org/pods/MoEngageInApp) - 4.13.0
* [MoEngageCards](https://cocoapods.org/pods/MoEngageCards) - 4.13.0
* [MoEngageGeofence](https://cocoapods.org/pods/MoEngageGeofence) - 5.13.0
* [MoEngageInbox](https://cocoapods.org/pods/MoEngageInbox) - 2.13.0
* [MoEngageRealTimeTrigger](https://cocoapods.org/pods/MoEngageRealTimeTrigger) - 2.13.0
**iPhone 12 Pro as Reference**
Our analysis excludes the Universal build because Apple doesn't install it on user devices. They optimize each app based on the user's device by installing only the necessary architecture. Therefore, our analysis assumes the iPhone 12 Pro with an operating system version 15.0 as the reference.
# MoEngage SDK Size Impact
The size analysis was done when MoEngage-iOS-SDK was integrated into a dummy sample app.
| Framework | Version | Compressed Size | Uncompressed Size |
| :------------------------------------------ | :-------------- | :-------------- | :---------------- |
| Dummy Sample App | NA | 36 KB | 125 KB |
| MoEngage-iOS-SDK | 9.14.0 | 849 KB | 2.5 MB |
| MoEngage-iOS-SDK + MoEngageInApp | 4.13.0 | 1.1 MB | 3.3 MB |
| MoEngage-iOS-SDK + MoEngageCards | 4.13.0 | 1.2 MB | 3.4 MB |
| MoEngage-iOS-SDK + MoEngageGeofence | 5.13.0 | 898 KB | 2.7 MB |
| MoEngage-iOS-SDK + MoEngageRichNotification | 7.13.0 | 933 KB | 2.8 MB |
| MoEngage-iOS-SDK + MoEngageInbox | 2.13.0 | 1.1 MB | 3.1 MB |
| MoEngage-iOS-SDK + MoEngageRealTimeTrigger | 2.13.0 | 1 MB | 3 MB |
| All Framework | Mentioned above | 1.8 MB | 5.2 MB |
**Overall Size Impact of MoEngage**
* The compressed size is the download size of your app. The uncompressed size is equivalent to the size of the installed app on the device.
* The overall size impact of the [MoEngage-iOS-SDK](https://cocoapods.org/pods/MoEngage-iOS-SDK) (Core SDK) along with [MoEngageInApp](https://cocoapods.org/pods/MoEngageInApp), [MoEngageCards](https://cocoapods.org/pods/MoEngageCards), [MoEngageRichNotification](https://cocoapods.org/pods/MoEngageRichNotification), [MoEngageGeofence](https://cocoapods.org/pods/MoEngageGeofence), [MoEngageInbox](https://cocoapods.org/pods/MoEngageInbox), and [MoEngageRealTimeTrigger](https://cocoapods.org/pods/MoEngageRealTimeTrigger) modules is 1.8 MB on compressed size and 5.2 MB on the install size of the app (uncompressed size).
# Custom Action Handling
Source: https://moengage.com/docs/developer-guide/ios-sdk/in-app-messages/custom-action-handling
Handle deep link callbacks and custom actions from MoEngage in-app messages in your iOS app.
## Deeplink callback in InApp
It is used to navigate users directly to a specific location or content within a mobile app.
### Default Handling
By default, SDK passes the deep link callback to the AppDelegate/SceneDelegate method .
If your application is running below iOS 13, then deep link callback is received in the AppDelegate methods:
```swift Swift wrap theme={null}
import UIKit
// Custom Scheme Link
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
//Call only if MoEngageAppDelegateProxyEnabled is NO in Info.plist
MoEngageSDKAnalytics.sharedInstance.processURL(url)
}
// Universal Links
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
if userActivity.activityType == NSUserActivityTypeBrowsingWeb ,
let incomingURL = userActivity.webpageURL{
//Call only if MoEngageAppDelegateProxyEnabled is NO in Info.plist
MoEngageSDKAnalytics.sharedInstance.processURL(incomingURL)
}
//rest of the implementation
return true
}
```
```objective-c Objective C wrap theme={null}
// Custom Scheme Link
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options {
return true;
}
// Universal Link
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler {
return true;
}
@end
```
If your application is above iOS 13, then a deeplink callback is received in the below ***SceneDelegate*** method:
```swift Swift wrap theme={null}
import UIKit
// Custom Scheme Link
func scene(_ scene: UIScene, openURLContexts URLContexts: Set) {
let url = URLContexts.first?.url
MoEngageSDKAnalytics.sharedInstance.processURL(url)
}
// Universal Scheme Link
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
if let url = userActivity.webpageURL {
MoEngageSDKAnalytics.sharedInstance.processURL(url)
}
}
}
```
### Custom Handling
To receive the deeplink callback in the [*MoEngageInAppNativeDelegate*](https://moengage.github.io/ios-api-reference/Protocols/MoEngageInAppNativeDelegate.html) *,* do pass [MoEngageInAppConfig(shouldProvideDeeplinkCallback: true)](/developer-guide/ios-sdk/sdk-integration/basic/sdk-initialization) while initializing the MoEngageSDKConfig object.
Refer to the [doc](/developer-guide/ios-sdk/in-app-messages/in-app-nativ#non-intrusive-nudges) for callback methods.
**SDK Version**
Custom Deeplink Callback is supported MoEngageInApp @ 6.00.0.
# In-App Nativ
Source: https://moengage.com/docs/developer-guide/ios-sdk/in-app-messages/in-app-nativ
Display contextual in-app messages to your iOS app users using the MoEngage In-App NATIV SDK.
In-App Campaigns are custom views that you can send to a segment of users to show custom messages or give new offers or take to some specific pages. They can be created from your MoEngage account.
**SDK Version**
Follow this doc only if you are using `MoEngage-iOS-SDK` version 8.2.0 and later. If you are using version 5.2.7 or less then follow the doc in this [link](/hc/en-us/articles/4404155414676).
# SDK Installation
## Install using Swift Package Manager
MoEngageInApp is supported through SPM from SDK version 3.2.0. To integrate, use the GitHub url [https://github.com/moengage/apple-sdk.git](https://github.com/moengage/apple-sdk.git) for SDK versions equal and above 9.23.0, or [https://github.com/moengage/MoEngage-iOS-SDK.git](https://github.com/moengage/MoEngage-iOS-SDK.git) for other SDK versions link and set the branch as master or the required version.
## Install using CocoaPod
**Information**
CocoaPods is being deprecated. MoEngage recommends using Swift Package Manager for all new integrations. For more info on CocoaPods, refer to [CocoaPods Integration Guide](/developer-guide/ios-sdk/sdk-integration/basic/integration-through-cocoa-pods).
Integrate the MoEngageInApp framework by adding the dependency in the pod file as described.
```ruby Ruby theme={null}
pod 'MoEngage-iOS-SDK/InApps',
```
Now run `pod install` to install the framework.
## Manual Integration
**Manual Integration:**
To integrate the `MoEngageInApp` SDK manually to your project follow this [doc](/developer-guide/ios-sdk/manual-integration/manual-integration).
# How to show In-App Message?
To use In-app Messaging, import `MoEngageInApps` and then add the code below to the view controller(s) in which you want to show the In-app.
```swift Swift wrap theme={null}
import MoEngageInApps
// Add the below line to show inapp
MoEngageSDKInApp.sharedInstance.showInApp()
```
```objective-c Objective-C wrap theme={null}
@import MoEngageInApps;
// Add the below line to show inapp
[[MoEngageSDKInApp sharedInstance] showInApp];
```
# Non Intrusive Nudges
Starting with version ***5.0.0***, MoEngage InApp SDK supports displaying Non-Intrusive nudges.
SDK can show Nudges in four positions (i.e. at the top, bottom, bottom left, and bottom right of the screen). Call the [*showNudge(atPosition:)*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKInApp.html#/c:@M@MoEngageInApps@objc\(cs\)MoEngageSDKInApp\(im\)showNudgeAtPosition:) in the view controller(s) where you want SDK to show the nudges :
```swift Swift wrap theme={null}
//For showing nudges at Top of the screen
MoEngageSDKInApp.sharedInstance.showNudge(atPosition: NudgePositionTop)
//For showing nudges at Bottom of the screen
MoEngageSDKInApp.sharedInstance.showNudge(atPosition: NudgePositionBottom)
//For showing nudges at BottomLeft of the screen
MoEngageSDKInApp.sharedInstance.showNudge(atPosition: NudgePositionBottomLeft)
//For showing nudges at BottomRight of the screen
MoEngageSDKInApp.sharedInstance.showNudge(atPosition: NudgePositionBottomRight)
//For showing nudges at any above mentioned position
MoEngageSDKInApp.sharedInstance.showNudge()
```
```objective-c Objective-C wrap theme={null}
//For showing nudges at Top of the screen
[[MoEngageSDKInApp sharedInstance] showNudgeAtPosition:NudgePositionTop];
//For showing nudges at Bottom of the screen
[[MoEngageSDKInApp sharedInstance] showNudgeAtPosition:NudgePositionBottom];
//For showing nudges at BottomLeft of the screen
[[MoEngageSDKInApp sharedInstance] showNudgeAtPosition:NudgePositionBottomLeft];
//For showing nudges at BottomRight of the screen
[[MoEngageSDKInApp sharedInstance] showNudgeAtPosition:NudgePositionBottomRight];
//For showing nudges at any above mentioned position.
[[MoEngageSDKInApp sharedInstance] showNudge];
```
# InApp Callbacks
**Note**
Make sure the class is configured with [*MoEngageInAppNativeDelegate*](https://moengage.github.io/ios-api-reference/Protocols/MoEngageInAppNativeDelegate.html) to receive all the callbacks.
To observe callbacks whenever an inApp is shown, dismissed, or clicked implement [*MoEngageInAppNativeDelegate*](https://moengage.github.io/ios-api-reference/Protocols/MoEngageInAppNativeDelegate.html). Set the delegate using the below methods.
```swift Swift wrap theme={null}
MoEngageSDKInApp.sharedInstance.setInAppDelegate(self)
```
```objective-c Objective-C wrap theme={null}
[[MoEngageSDKInApp sharedInstance] setInAppDelegate:self];
```
Once the delegate is set you will receive the following callbacks:
```swift Swift wrap theme={null}
// Called when an inApp is shown on the screen
func inAppShown(withCampaignInfo inappCampaign: MoEngageInAppCampaign, forAccountMeta accountMeta: MoEngageAccountMeta) {
print("InApp shown callback for Campaign ID(\(inappCampaign.campaign_id)) and CampaignName(\(inappCampaign.campaign_name))")
print("Account Meta AppID: \(accountMeta.appID)")
}
// Called when an inApp is dismissed by the user
func inAppDismissed(withCampaignInfo inappCampaign: MoEngageInAppCampaign, forAccountMeta accountMeta: MoEngageAccountMeta) {
print("InApp dismissed callback for Campaign ID(\(inappCampaign.campaign_id)) and CampaignName(\(inappCampaign.campaign_name))")
print("Account Meta AppID: \(accountMeta.appID)")
}
// Called when an inApp is clicked by the user, and it has been configured with a custom action
func inAppClicked(withCampaignInfo inappCampaign: MoEngageInAppCampaign, andCustomActionInfo customAction: MoEngageInAppAction, forAccountMeta accountMeta: MoEngageAccountMeta) {
print("InApp Clicked with Campaign ID \(inappCampaign.campaign_id)")
print("Custom Actions Key Value Pairs: \(customAction.keyValuePairs)")
}
// Called when an inApp is clicked by the user, and it has been configured with a navigation action
// Below InApp version 6.00.0
func inAppClicked(withCampaignInfo inappCampaign: MoEngageInAppCampaign, andNavigationActionInfo navigationAction: MoEngageInAppAction, forAccountMeta accountMeta: MoEngageAccountMeta) {
print("InApp Clicked with Campaign ID \(inappCampaign.campaign_id)")
print("Navigation Action Screen Name \(navigationAction.screenName) Key Value Pairs: \((navigationAction.keyValuePairs))")
}
// Called when an inApp is clicked by the user, and it has been configured with a navigation action (Deeplink , Navigate To Screen)
// From and above InApp version 6.00.0
func inAppClicked(withCampaignInfo inappCampaign: MoEngageInAppCampaign, andNavigationActionInfo navigationAction: MoEngageInAppNavigationAction, forAccountMeta accountMeta: MoEngageAccountMeta) {
print("InApp Clicked with Campaign ID \(inappCampaign.campaign_id)")
print("Navigation Url \(navigationAction.navigationUrl) Key Value Pairs: \((navigationAction.keyValuePairs))")
print("Navigation Action Type : \(navigationAction.navigationType)")
}
```
```objective-c Objective-C wrap theme={null}
// Called when an inApp is shown on the screen
(void)inAppShownWithCampaignInfo:(MoEngageInAppCampaign *)inappCampaign forAccountMeta:(MoEngageAccountMeta *)accountMeta {
NSLog(@"InApp Shown with Campaign ID %@",inappCampaign.campaign_id);
}
// Called when an inApp is dismissed by the user
- (void)inAppDismissedWithCampaignInfo:(MoEngageInAppCampaign *)inappCampaign forAccountMeta:(MoEngageAccountMeta *)accountMeta {
NSLog(@"InApp Dismissed with Campaign ID %@",inappCampaign.campaign_id);
}
// Called when an inApp is clicked by the user, and it has been configured with a custom action
- (void)inAppClickedWithCampaignInfo:(MoEngageInAppCampaign *)inappCampaign andCustomActionInfo:(MoEngageInAppAction *)customAction forAccountMeta:(MoEngageAccountMeta *)accountMeta {
NSLog(@"InApp Clicked with Campaign ID %@",inappCampaign.campaign_id);
NSLog(@"Custom Action Key Value Pairs: %@", customAction.screenName);
}
// Called when an inApp is clicked by the user, and it has been configured with a navigation action
// Below InApp version 5.03.0
- (void)inAppClickedWithCampaignInfo:(MoEngageInAppCampaign *)inappCampaign andNavigationActionInfo:(MoEngageInAppAction *)navigationAction forAccountMeta:(MoEngageAccountMeta *)accountMeta {
NSLog(@"InApp Clicked with Campaign ID %@",inappCampaign.campaign_id);
NSLog(@"Navigation Action Screen Name %@\n Key Value Pairs: %@", navigationAction.screenName,navigationAction.keyValuePairs);
}
// Called when an inApp is clicked by the user, and it has been configured with a navigation action (Deeplink, Navigate To Screen)
// From and above InApp version 5.03.0
-(void)inAppClickedWithCampaignInfo:(MoEngageInAppCampaign*)inappCampaign andNavigationActionInfo:(MoEngageInAppNavigationAction*)navigationAction forAccountMeta:(nonnull MoEngageAccountMeta *)accountMeta {
NSLog(@"InApp Clicked with Campaign ID %@",inappCampaign.campaign_id);
NSLog(@"Navigation Action Screen Name %@\n Key Value Pairs: %@", navigationAction.navigationUrl,navigationAction.keyValuePairs);
}
```
# Context-Based InApps
We have introduced context-based InApps with SDK version 6.0.0. While creating InApp campaigns you can set the contexts OR tags to the campaign. SDK will check with the current context set in the App and show the inApp only when a current set context matches the campaign context.
## Set Current Context:
To set the current context for the InApp module use [*setCurrentInAppContexts(\_):*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKInApp.html#/c:@M@MoEngageInApps@objc\(cs\)MoEngageSDKInApp\(im\)setCurrentInAppContexts:) as shown below:
```swift Swift wrap theme={null}
MoEngageSDKInApp.sharedInstance.setCurrentInAppContexts(["Home","CategoriesScreen"])
```
```objective-c Objective-C wrap theme={null}
[[MoEngageSDKInApp sharedInstance] setCurrentInAppContexts:@[@"Home",@"CategoriesScreen"]];
```
## Reset Context:
To reset the current context for the InApp module call [*invalidateInAppContexts()*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKInApp.html#/c:@M@MoEngageInApps@objc\(cs\)MoEngageSDKInApp\(im\)invalidateInAppContexts) method:
```swift Swift wrap theme={null}
MoEngageSDKInApp.sharedInstance.invalidateInAppContexts()
```
```objective-c Objective-C wrap theme={null}
[[MoEngageSDKInApp sharedInstance] invalidateInAppContexts];
```
# Disable In-Apps in ViewController
If you don't want to show InApp messages in a particular ViewController, use [*blockInApp(forViewController:)*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKInApp.html#/c:@M@MoEngageInApps@objc\(cs\)MoEngageSDKInApp\(im\)blockInAppForViewController:) method as shown below:
```swift Swift wrap theme={null}
//For not showing in apps in viewController
MoEngageSDKInApp.sharedInstance.blockInApp(forViewController: viewController);
```
```objective-c Objective-C wrap theme={null}
//For not showing in apps in viewController
[[MoEngageSDKInApp sharedInstance] blockInAppForViewController:viewController];
```
# Disabling In-Apps for App
If you do not wish to use InApp messaging, set the property disableInApps. The property has to be set before the initial call.
```swift Swift wrap theme={null}
MoEngageSDKInApp.sharedInstance.disableInApps()
```
```objective-c Objective-C wrap theme={null}
[[MoEngageSDKInApp sharedInstance] disableInApps];
```
# Self handled In-Apps
Self handled In-Apps are not shown by the SDK. While creating the campaign, a String payload has to be provided. The same payload will be provided to the application on campaign delivery. InApp Campaigns that have trigger condition as Screen launch can be fetched using [*getSelfHandledInApp(completionBlock:)*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKInApp.html#/c:@M@MoEngageInApps@objc\(cs\)MoEngageSDKInApp\(im\)getSelfHandledInAppWithCompletionBlock:).
```swift Swift wrap theme={null}
MoEngageSDKInApp.sharedInstance.getSelfHandledInApp { campaignInfo, accountMeta
if let campaignInfo = campaignInfo{ print("Self-Hanled InApp Content \(campaignInfo.campaignContent)")
// Update UI with Self Handled InApp Content
} else{
print("No Self Handled campaign available")
}
}
```
```objective-c objective-c wrap theme={null}
[[MoEngageSDKInApp sharedInstance] getSelfHandledInAppWithCompletionBlock:^(MoEngageInAppSelfHandledCampaign * _Nullable, MoEngageAccountMeta * _Nullable) {
if (campaignInfo != nil) {
NSLog(@"Self Handled inApp content : %@", campaignInfo.campaignContent);
// Update UI using the self-handled content
}
else{
NSLog(@"Self-Handled InApp not available");
}
}];
```
For getting the Self-Handled InApp payload in the case of Event-Triggered campaigns, set the [*selfHandledInAppTriggered(withInfo:forAccountMeta:)*](https://moengage.github.io/ios-api-reference/Protocols/MoEngageInAppNativeDelegate.html#/c:@M@MoEngageInApps@objc\(pl\)MoEngageInAppNativeDelegate\(im\)selfHandledInAppTriggeredWithInfo:forAccountMeta:) delegate. SDK will automatically deliver the payload in this delegate if the user is eligible for the campaign.
```swift Swift wrap theme={null}
// This method is called when an event triggers an in-app from the server, which is of type self handled.
func selfHandledInAppTriggered(withInfo inappCampaign: MoEngageInAppSelfHandledCampaign, forAccountMeta accountMeta: MoEngageAccountMeta) {
print("Self Handled InApp Triggered with info:\nCampaign ID:\(inappCampaign.campaign_id) \nContent: \(inappCampaign.campaignContent)")
}
```
```objective-c Objective-C wrap theme={null}
// This method is called when an event triggers an in-app from the server, which is of type self handled.
- (void)selfHandledInAppTriggeredWithInfo:(MoEngageInAppSelfHandledCampaign *)inappCampaign forAccountMeta:(MoEngageAccountMeta *)accountMeta {
NSLog(@"Self Handled InApp Triggered with info:\nCampaign ID: %@ \nContent: %@",inappCampaign.campaign_id, inappCampaign.campaignContent);
}
```
**Note**
The above method will also be called when trying to test the self-handled campaign through a test campaign.
# Self handled multiple In-Apps
Starting with ***MoEngage-iOS-SDK 9.19.0*** version, MoEngage InApp SDK supports displaying Multiple Self Handled InApps. To get multiple self handled inApps for multiple contexts set by the user, use sdk's [*getSelfHandledInApps(completionBlock:)*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKInApp.html#/c:@M@MoEngageInApps@objc\(cs\)MoEngageSDKInApp\(im\)getSelfHandledInAppsFor:completionBlock:).
```swift Swift wrap theme={null}
MoEngageSDKInApp.sharedInstance.getSelfHandledInApps(for: instance) { [weak self] campaignData in
print(campaignData)
}
```
```objective-c Objective-C wrap theme={null}
[[MoEngageSDKInApp sharedInstance] getSelfHandledInAppsForInstance:instance withCompletionBlock:^(MoEngageInAppSelfHandledData * _Nonnull campaignData) {
NSLog(@"%@", campaignData);
}];
```
## Campaign Selection Logic
* **Default Limit**: By default, only 5 campaigns will be fetched.
* **Priority-Based Selection**: Campaigns are delivered based on their priority and last updated time. It checks for priority first and then checks the last updated time on conflicting priorities
* **Exclusion criteria**: Campaigns are only excluded based on specific rules like frequency capping, eligibility criteria, campaign status, or priority limits.
**Example Scenario:** If you have 6 campaigns with different priorities, published time and contexts:
* Context 1: Campaign 1 (P0, T2), Campaign 2 (P1, T3), Campaign 3 (P2, T6)
* Context 2: Campaign 4 (P0, T1), Campaign 5 (P1, T5)
* Context 3: Campaign 6 (P0, T4)
Following campaigns will be delivered in this order: \[Campaign 4, Campaign 1, Campaign 6, Campaign 2, Campaign 5]
**Selection Algorithm:**
1. Filter campaigns by user eligibility and targeting criteria
2. Sort by campaign priority (P0, P1, P2, etc.)
3. For campaigns with same priority, sort by most recent update timestamp
4. Return top 5 campaigns
#### **Best Practices for Campaign Organization for multiple self handled campaigns**
For optimal performance across multiple contexts on a single page, organize your campaigns like this:
* Context 1 (Homepage): Campaign A (P0), Campaign B (P1)
* Context 2 (Product): Campaign C (P0), Campaign D (P1)
* Context 3 (Checkout): Campaign E (P0)
This ensures each context has relevant campaigns without hitting the 5-campaign limit.
Also, make sure that you set the priority of the campaigns you want to fetch accordingly, because the method will fetch all self-handled campaigns regardless of whether they are context-based or not.
## Tracking Self Handled Multiple InApps
The [*getSelfHandledInApps(completionBlock:)*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKInApp.html#/c:@M@MoEngageInApps@objc\(cs\)MoEngageSDKInApp\(im\)getSelfHandledInAppsFor:completionBlock:) method returns [*MoEngageInAppSelfHandledData*](https://moengage.github.io/ios-api-reference/Classes/MoEngageInAppSelfHandledData.html), which contains a list of [*MoEngageInAppSelfHandledCampaign*](https://moengage.github.io/ios-api-reference/Classes/MoEngageInAppSelfHandledCampaign.html) objects. The statistics for each [*MoEngageInAppSelfHandledCampaign*](https://moengage.github.io/ios-api-reference/Classes/MoEngageInAppSelfHandledCampaign.html) object must be tracked individually below APIs.
## Fetching Contextual Multiple Self-Handled InApps
To fetch contextual multiple self-handled inapps, set the inapp contexts using [*setCurrentInAppContexts()*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKInApp.html#/c:@M@MoEngageInApps@objc\(cs\)MoEngageSDKInApp\(im\)setCurrentInAppContexts:) before calling [*getSelfHandledInApps(completionBlock:)*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKInApp.html#/c:@M@MoEngageInApps@objc\(cs\)MoEngageSDKInApp\(im\)getSelfHandledInAppsFor:completionBlock:). This will return a list of contextual and non-contextual inapps(in the order of campaign priority set at the time of campaign creation).
## Tracking InApp Shown And Clicked:
For tracking In-App shown for self-handled in-apps use the [*selfHandledShown(campaignInfo:)*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKInApp.html#/c:@M@MoEngageInApps@objc\(cs\)MoEngageSDKInApp\(im\)selfHandledShownWithCampaignInfo:) and provide campaign instance as a parameter:
```swift Swift wrap theme={null}
// Call this method when you show the self handled in-app so we can update impressions.
MoEngageSDKInApp.sharedInstance.selfHandledShown(campaignInfo: campaignInfo)
```
```objective-c Objective-C wrap theme={null}
// Call this method when you show the self handled in-app so we can update impressions.
[[MoEngageSDKInApp sharedInstance] selfHandledShownWithCampaignInfo:campInfo];
```
For tracking InApp Clicked information for stats, call the following methods :
```swift Swift wrap theme={null}
// Call this method to track if self handled in app widget(other than Primary Widget) is clicked.
MoEngageSDKInApp.sharedInstance.selfHandledClicked(campaignInfo: campaignInfo)
// Call this method to track dismiss actions on the inApp.
MoEngageSDKInApp.sharedInstance.selfHandledDismissed(campaignInfo: campaignInfo)
```
```objective-c Objective-C wrap theme={null}
// Call this method to track if self handled in app widget(other than Primary Widget) is clicked.
[[MoEngageSDKInApp sharedInstance] selfHandledClickedWithCampaignInfo:campaignInfo];
// Call this method to track dismiss actions on the inApp.
[[MoEngageSDKInApp sharedInstance] selfHandledDismissedWithCampaignInfo:campaignInfo];
```
# In-App Messaging Rules
We use the following rules while showing the In-App:
Preconditions for inApp to work:
* If InApp Backend Sync was successful in the current session or not.
* Check if InApp is disabled on the current screen.
The following are checked for each campaign in the list of active campaigns(sorted according to priority and Last Updated Time)
* Check Global Delay has lapsed, skip this if Ignore Global Delay set for the campaign.
* Check if the campaign has expired
* Display Rules
* Check Show Only on Screen
* Check with current contexts
* Delivery Controls
* Persistence Check(If primary action of InApp is done but still want to show the inApp)
* Check if the campaign has been shown the maximum number of times.
* Check if the campaign level delay has crossed.
* Check Device Orientation is Portrait for Native InApp and required Orientation for HTML InApp(as selected during campaign creation).
The first campaign satisfying all the rules is shown to the user.
# Actionable Notifications
Source: https://moengage.com/docs/developer-guide/ios-sdk/integration-with-older-version-of-sdk/push/advanced/actionable-notifications
Add custom action buttons to iOS push notifications using MoEngage SDK for older versions.
Actionable notifications let you add custom action buttons to the standard iOS push notifications. Actionable notifications give the user a quick and easy way to perform relevant tasks in response to a notification. These actionable notifications are available from **iOS 8**onwards.
Actionable Notifications are available from MoEngage SDK version 2.2. And to support using UserNotifications framework from iOS 10 onwards use MoEngage SDK 3.0 and above.
# How to implement Actionable Notifications?
To use actionable notification with MoEngage SDK, you have to define the actions and group them into categories as shown in the example. In the example, you can see that we are getting two different Sets of categories, one for iOS10 and above(i.e, set of UNNotificationCategory instances) and the other for the iOS version below iOS10 (i.e, set of MONotificationCategory instances). And while registering for push provide both the sets in parameters as shown below :
```swift Swift theme={null}
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate{
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
//--- Rest of Implementation
//For registering for remote notification
let categoriesForiOS10 = self.getCategories()
MoEngage.sharedInstance().registerForRemoteNotification(withCategories: categoriesForiOS10, withUserNotificationCenterDelegate: self)
//--- Rest of Implementation
return true
}
//Example to define categories
//This method gives categories for iOS version 10.0 and above
@available(iOS 10.0, *)
func getCategories() -> Set{
let acceptAction = UNNotificationAction.init(identifier: "ACCEPT_IDENTIFIER", title: "Accept", options: .authenticationRequired)
let declineAction = UNNotificationAction.init(identifier: "DECLINE_IDENTIFIER", title: "Decline", options: .destructive)
let maybeAction = UNNotificationAction.init(identifier: "MAYBE_IDENTIFIER", title: "May Be", options: .foreground)
let inviteCategory = UNNotificationCategory.init(identifier: "INVITE_CATEGORY", actions: [acceptAction,declineAction,maybeAction], intentIdentifiers: [], options: .customDismissAction)
let categoriesSet = Set.init([inviteCategory])
return categoriesSet;
}
}
```
```objectivec Objective-C theme={null}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOption
{
---------
NSSet* categorySetForiOS10 = [self getNotificationCategories];
[[MoEngage sharedInstance] registerForRemoteNotificationWithCategories:categorySetForiOS10 withUserNotificationCenterDelegate:self];
}
---------
return YES;
}
//Example to define categories
//This method gives categories for iOS version 10.0 and above
-(NSSet*)getNotificationCategories{
UNNotificationAction *acceptAction = [UNNotificationAction actionWithIdentifier:@"ACCEPT_IDENTIFIER" title:@"Accept" options:UNNotificationActionOptionAuthenticationRequired];
UNNotificationAction *declineAction = [UNNotificationAction actionWithIdentifier:@"DECLINE_IDENTIFIER" title:@"Decline" options:(UNNotificationActionOptionDestructive)];
UNNotificationAction *maybeAction = [UNNotificationAction actionWithIdentifier:@"MAYBE_IDENTIFIER" title:@"May Be" options:UNNotificationActionOptionNone];
UNNotificationCategory* inviteCategory = [UNNotificationCategory categoryWithIdentifier:@"INVITE_CATEGORY"actions:@[acceptAction,maybeAction, declineAction,opt4Action] intentIdentifiers:@[] options:UNNotificationCategoryOptionNone];
NSSet *categories = [NSSet setWithObjects:inviteCategory,nil];
return categories;
}
```
As you can see in the example Accept, Decline, and May Be actions are grouped to a category i.e,"INVITE\_CATEGORY". For declaring categories for iOS8 and iOS9 use **MONotificationCategory** from our SDK.
**Notification Categories**
MoEngage recommended not to change the actions grouped in a category across the app versions, as it will lead to users seeing different actions for the same category across different app versions.
# Tracking User Actions
## FOR iOS10 and Above :
As mentioned earlier, use the delegate methods of **UNUserNotificationCenter** to handle actions of notifications and also call ***userNotificationCenter:didReceiveNotificationResponse:*** of the SDK, to track the actions performed on notifications.
```swift Swift theme={null}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
MoEngage.sharedInstance().userNotificationCenter(center, didReceive: response)
//---
completionHandler()
}
```
```objectivec Objective-C theme={null}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void (^)())completionHandler{
[[MoEngage sharedInstance] userNotificationCenter:center didReceiveNotificationResponse:response];
//---
completionHandler();
}
```
## FOR iOS8 and iOS9
To track the action performed by the user on actionable notifications call *handleActionWithIdentifier:forRemoteNotification:* in *application:handleActionWithIdentifier:forRemoteNotification:completionHandler:* as shown below :
```swift Swift theme={null}
func application(_ application: UIApplication, handleActionWithIdentifier identifier: String?, forRemoteNotification userInfo: [AnyHashable : Any], completionHandler: @escaping () -> Void) {
//---
if let identifier = identifier {
MoEngage.sharedInstance().handleAction(withIdentifier: identifier, forRemoteNotification: userInfo)
}
}
```
```objectivec Objective-C theme={null}
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)notification completionHandler:(void (^)()) completionHandler {
----
[[MoEngage sharedInstance] handleActionWithIdentifier:identifier forRemoteNotification:notification]
completionHandler();
}
```
# Location Triggered
Source: https://moengage.com/docs/developer-guide/ios-sdk/integration-with-older-version-of-sdk/push/advanced/location-triggered
Set up geofence-based location-triggered push notifications in your iOS app with the MoEngage SDK.
[](http://cocoapods.org/pods/MoEngageGeofence)
**Important**
* Starting from **iOS 14.0**, Apple has provided user control to choose the level of precision of location to be shared in App. Now because of this **region monitoring(Geofence feature) will not work in cases where the precise location is disabled by the user**. Refer [link](https://developer.apple.com/videos/play/wwdc2020/10660/) for more info.
* Region monitoring is only supported with **Always authorization**. When-in-use authorization doesn't support this feature. Refer [link](https://developer.apple.com/documentation/corelocation/choosing_the_authorization_level_for_location_services) for more info.
* **Dwell** trigger is **not supported in iOS**, hence the SDK supports only Enter and Exit triggers.
# How to enable Location Triggered?
## Required Permissions:
**Region Monitoring(Geofences) requires Always Authorization and Precise location accuracy to be enabled to work**. Therefore make sure that the app is configured to get these permissions and also it's a good practice to let the user know the context in which these permissions are needed, this will also encourage the user to provide these permissions.
# SDK Installation
## Install using CocoaPod
Integrate the MoEngageGeofence framework by adding the dependency in the podfile as show below.
```Ruby theme={null}
pod 'MoEngageGeofence','~>4.2.0'
```
Now run `pod install` to install the framework
## Install using Swift Package Manager
MoEngageGeofence is supported through SPM from SDK version 4.2.0. To integrate use the following git hub url link and set the branch as master or version as 4.2.0 and above [https://github.com/moengage/MoEngage-iOS-Geofence.git](https://github.com/moengage/MoEngage-iOS-Geofence.git)
## Manual Integration
To integrate the `MoEngageGeofence` SDK manually to your project follow this [doc](https://developers.moengage.com/hc/en-us/articles/4404183451412).
MOGeofence has been renamed to MoEngageGeofence from version 4.2.0.Do update the podfile and import statement accordingly.
## Start Geofence Monitoring:
After integrating the MOGeofence module call `startGeofenceMonitoring()` method to initiate the geofence module. This will fetch the geofences around the current location of the user.
```swift Swift theme={null}
MOGeofence.sharedInstance.startGeofenceMonitoring()
```
```objectivec Objective-C theme={null}
[[MOGeofence sharedInstance] startGeofenceMonitoring];
```
Geofence Handler also has callbacks for `didEnterRegion` and `didExitRegion`. You can get these by confirming to the as `MOGeofence.sharedInstance.setGeofenceDelegate(self)`
```swift Swift theme={null}
extension GeofenceViewController: MOGeofenceDelegate {
func geofenceEnterTriggered(withLocationManager locationManager: CLLocationManager?, andRegion region: CLRegion?, forAccountMeta accountMeta: MOAccountMeta) {
print("Geofence Entered")
}
func geofenceExitTriggered(withLocationManager locationManager: CLLocationManager?, andRegion region: CLRegion?, forAccountMeta accountMeta: MOAccountMeta) {
print("Geofence Exited"
}
}
```
```objectivec Objective-C theme={null}
@interface MyViewController ()
---
- (void)geofenceEnterTriggeredWithLocationManager:(CLLocationManager * _Nullable)locationManager andRegion:(CLRegion * _Nullable)region forAccountMeta:(MOAccountMeta * _Nonnull)accountMeta {
NSLog(@"Geofence Entered");
}
- (void)geofenceExitTriggeredWithLocationManager:(CLLocationManager * _Nullable)locationManager andRegion:(CLRegion * _Nullable)region forAccountMeta:(MOAccountMeta * _Nonnull)accountMeta {
NSLog(@"Geofence Exited");
}
```
# Testing Geofencing
First, create a geofencing campaign on your MoEngage dashboard. You can test geofencing in the following ways:
1. On the simulator:
* You can simulate location as shown below.\\
* Simulate the location for which you have created the campaign on the dashboard.\
If you get the respective call back (the delegate methods in MOGeofenceHandler), you are good to go. On simulator, you will not receive push notifications.
2. On the device:
* You can simulate location for real device from the bar above the console as shown below:\\
* You can add a gpx file with the locations configured. A sample gpx file looks like this:
```XML theme={null}
CustomName
```
On the device, once you get the delegate callback for entering or exit in a region, a notification will be sent to the device. This happens instantly, but the notification might take up to 10 minutes.
# Geo Notifications
Once you have received the notification, to identify geo notifications, there is a custom param “cType” = “geo” in the param app\_extra, as shown below:
```json JSON theme={null}
{
"app_extra" = {
cType = geo;
screenData = {
"" = "";
};
screenName = "";
};
aps = {
alert = "exit london- single fence";
badge = 1;
};
moengage = {
cid = "55a628bcf4c4073bb66a368b_GEO:55a628bcf4c4073bb66a368c_ABab1:2015-07-15_14:11:33.704706";
};
}
```
# Push Notification Implementation
Source: https://moengage.com/docs/developer-guide/ios-sdk/integration-with-older-version-of-sdk/push/advanced/push-notification-implementation
Implement push notifications in your iOS app target and notification service extension using MoEngage.
Make sure you have created the APNS certificate and uploaded it to MoEngage dashboard as mentioned in the [APNS Certificate/ PEM file](https://developers.moengage.com/hc/en-us/articles/4403944011028) before testing the push notification.
# App Target Implementation
# Settings Changes
## Capabilities Tab Changes
First, select your **App Target** and select **Capabilities** do the changes as shown in the image below:
**App Group ID Recommendation**
We recommend having a separate App Group ID set for MoEngage with the format `group.{app bundle id}.moengage`. And make sure the same app group id is enabled for all the targets where MoEngage is being used.
1. Turn **ON** App Groups in for your app target and enable one of the App group ids, in case if you don't have an App Group ID then create one. The name of your app group should be `group.{your_bundle_id}.MoEngage`.
2. Turn **ON** Background mode and set/enable **Remote Notification**.
3. Turn **ON** the **Push Notifications**capability for your app.
On enabling **Remote Notification** background mode, we will be able to track uninstalls even for devices where push notification is disabled by the user.
## Adding UserNotifications framework
In the App's Target add **UserNotifications** framework in **Linked Frameworks and Libraries** and set it **Optional**.
# Code Changes in App Target
## Provide the App Group ID to SDK
Provide the App Group ID selected in **Capabilities** in MOSDKConfig instance while initializing the SDK as shown below:
```swift Swift theme={null}
let sdkConfig = MOSDKConfig(withAppID: "MoEngage Workspace ID")
sdkConfig.appGroupID = "App Group ID"
```
```objectivec Objective-C theme={null}
MOSDKConfig* sdkConfig = [[MOSDKConfig alloc] initWithAppID:"MoEngage Workspace ID"];
sdkConfig.appGroupID = @"App Group ID";
```
## AppDelegate swizzling in SDK
**Segment-MoEngage Integration**
Please note that **AppDelegate Swizzling** doesn't work reliably with [Segment Integration](https://developers.moengage.com/hc/en-us/articles/4405093164692)because of delay in initializing the SDK by Segment, therefore make sure to call the MoEngage SDK methods for all Push related callbacks.
AppDelegate Swizzling is used for intercepting the methods of the AppDelegate class in iOS apps. It allows third-party libraries or SDKs to integrate into the app and handle certain system interactions, such as push notifications and deep linking, without requiring manual setup by developers.
**Default behavior**
By default, the MoEngage SDK swizzles the **AppDelegate** Class to get all the callbacks related to Push Notifications, and also we have applied method swizzling for **UserNotificationCenter** delegate methods. This is to ease the integration of the SDK, and this is introduced from the [SDK version 5.0.0](https://developers.moengage.com/hc/en-us/articles/4404198236564-Change-Log#v5-0-0-0-26).
**Disabling AppDelegate Swizzling in the MoEngage SDK**
You should disable AppDelegate Swizzling if you do not want MoEngage SDK to implicitly handle the callbacks. To disable swizzling, add the flag MoEngageAppDelegateProxyEnabled in the app’s Info.plist file and set it to bool value NO.
In the following sections, we have provided the SDK methods to be called when you get callbacks related to push notifications. Most of them will not be needed in case swizzling is enabled; the same will be mentioned in the description.
## Registering for Push notification
Make sure that class, where UserNotificationCenter delegate methods are implemented, should agree to `UNUserNotificationCenterDelegate` , also set the `UNUserNotificationCenterDelegate` after the app launch in `application:DidFinishLaunchingWithOptions:` as shown below: `(In this case AppDelegate is set to be UserNotificationCenter delegate)` :
Call SDK's `registerForRemoteNotificationWithCategories:` to initiate registration of remote notifications as shown below :
```swift Swift theme={null}
MoEngage.sharedInstance().registerForRemoteNotification(withCategories: nil, withUserNotificationCenterDelegate: self)
```
```objectivec Objective-C theme={null}
[[MoEngage sharedInstance] registerForRemoteNotificationWithCategories:nil withUserNotificationCenterDelegate:self];
```
Now after registering for push, the below-given callback methods will be called. **In case you have disabled swizzling,** call the respective MoEngage SDK methods for the callbacks as shown below :
```swift Swift theme={null}
//Remote notification Registration callback methods
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
//Call only if MoEngageAppDelegateProxyEnabled is NO
MoEngage.sharedInstance().setPushToken(deviceToken)
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
//Call only if MoEngageAppDelegateProxyEnabled is NO
MoEngage.sharedInstance().didFailToRegisterForPush()
}
```
```objectivec Objective-C theme={null}
//Remote notification Registration callback methods
- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken {
//Call only if MoEngageAppDelegateProxyEnabled is NO
[[MoEngage sharedInstance] setPushToken:deviceToken]
}
-(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
//Call only if MoEngageAppDelegateProxyEnabled is NO
[[MoEngage sharedInstance]didFailToRegisterForPush];
}
//This method is for getting the types of notifications that app may use
-(void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings{
//Call only if MoEngageAppDelegateProxyEnabled is NO
[[MoEngage sharedInstance]didRegisterForUserNotificationSettings:notificationSettings];
}
```
**Notification Actions**
You can send the set of categories(**UNNotificationCategory** for supporting Notification actions. Get more info regarding notification actions [here](https://developers.moengage.com/hc/en-us/articles/4403961980308).
## Callback methods on receiving Push Notification:
Below are the callbacks the app would receive on receiving the push notifications. **In case you have disabled swizzling,** include calls to MoEngage SDK methods on receiving notification callbacks as shown below:
```swift Swift theme={null}
// MARK:- UserNotifications Framework callback method
@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void) {
//Call only if MoEngageAppDelegateProxyEnabled is NO
MoEngage.sharedInstance().userNotificationCenter(center, didReceive: response)
//Custom Handling of notification if Any
let pushDictionary = response.notification.request.content.userInfo
print(pushDictionary)
completionHandler();
}
@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
//This is to only to display Alert and enable notification sound
completionHandler([.sound,.alert])
}
// MARK:- Remote notification received callback method for iOS versions below iOS10
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
//Call only if MoEngageAppDelegateProxyEnabled is NO
MoEngage.sharedInstance().didReceieveNotificationinApplication(application, withInfo: userInfo)
}
```
```objectivec Objective-C theme={null}
// UserNotifications Framework Callback for iOS10 and above
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void (^)())completionHandler{
//Call only if MoEngageAppDelegateProxyEnabled is NO
[[MoEngage sharedInstance] userNotificationCenter:center didReceiveNotificationResponse:response];
//Custom Handling of notification if Any
completionHandler();
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler{
//This is to only to display Alert and enable notification sound
completionHandler((UNNotificationPresentationOptionSound
| UNNotificationPresentationOptionAlert ));
}
//Remote notification received callback method for iOS versions below iOS10
- (void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
//Call only if MoEngageAppDelegateProxyEnabled is NO
[[MoEngage sharedInstance]didReceieveNotificationinApplication:application withInfo:userInfo];
}
```
Method ***userNotificationCenter:willPresentNotification:withCompletionHandler:*** is called when the app receives notification in foreground. Here, in the completion handler you can mention how you want to let the user know that the app has received a notification.
Method ***userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler*** is called when the app receives a response from the user. Response can be **Default Click** on the Notification or **Dismissing** the notification or any of the other **custom actions** implemented using UNUserNotificationCategory. Here, call ***userNotificationCenter:didReceiveNotificationResponse:*** of MoEngage class.
* ***userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler*** is the only method called when the user clicks on notification, if implemented. Therefore, include your custom handlers here instead of application:didReceiveRemoteNotification: for iOS10.
* While implementing deep links, make sure that you have added the apps URL Scheme to **LSApplicationQueriesSchemes** array in Info.plist to whitelist your app. Without this, the deep links won't work post iOS9.
# Disable Badge Reset
By default, the SDK sets the notification badge count to **0** on every app launch and this also clears the notifications in the device notification center. In case if you would like to keep the notifications even after the App Launch then disable badge reset by calling the below method
```swift Swift theme={null}
MoEngage.sharedInstance().setDisableBadgeReset(true)
```
```objectivec Objective-C theme={null}
[[MoEngage sharedInstance] setDisableBadgeReset:true];
```
# Custom Sound for Notification
You can have a custom tone for notifications of your app. iOS platform supports .aiff , .caf and .wav files for custom Notification tone. For this make sure the sound file of tone is included in your app bundle. Once this is done make sure to provide the sound filename for Notification Sound(In Rich Content Section) while creating the campaign in the dashboard as shown below, and it should work:
# Silent Push Handling
We make use of silent pushes for uninstall tracking(If opted for in the [dashboard settings](https://help.moengage.com/hc/en-us/articles/360043026012-Uninstall-Tracking)). Our system sends silent pushes to the entire user base of the app for the same. The push payload which is sent from MoEngage for silent pushes would look like below:
```json JSON theme={null}
{
"aps" : {
"content-available" : 1
},
"moengage" : {
"silentPush" : 1
}
}
```
Make sure to check for `silentPush` key inside `moengage` and handle the app launches and notification received callbacks in case of these silent pushes.
**Test Silent Push**
For testing the flow with silent pushes refer to this [link](https://help.moengage.com/hc/en-us/articles/211249403-Test-Silent-Push-Notification-for-Android-iOS).
# Notification Service Extension Target Implementation
# Why add a Notification Service Extension to your project?
Notifications have got a complete revamp after the release of iOS10 with the introduction of new `UserNotifications` and `UserNotificationsUI` framework. And with this we got Notification Service App Extensions, which can be used for following:
1. **Add media support in Notifications:** Post iOS10 Apple has given us the ability to add images, gifs, audio, and video files to the notifications and this can be done using the Notification Service Extension.
2. **For supporting Inbox Feature:** Notification Service Extension is also used to save the received notifications which can later be shown in the App Inbox.
3. **For Updating the Notification Badge count:** MoEngage makes use of the extension to update the notification badge count and doesn't send badge in the notification payload.
4. **For Tracking Notification Impression:** We can track if a Notification is received by the device using the Notification Service Extension.
# Follow the below steps to set up Notification Service Extension:
## 1. Create a Notification Service Extension Target:
Set the name of the extension target and the programing language which you want to use:
After the target is created, Activate the scheme for Extension when prompted for the same. After this, your extension will be added to the project you will see a class with the extension name provided by you while creating and .plist file associated with it.
## 2. Enable Push Notification Capabilities
Then make sure that the Push Notifications Capability is enabled for the Notification Service Extension created:
## 3. Add UserNotifications framework to extension target:
Add `UserNotifications` framework to `Linked Frameworks and Libraries` of notification service extension target as shown below:
## 4. Integrate MoEngageRichNotification framework to Extension:
### Integrate using CocoaPod
For integrating through CocoaPod, include **MoEngageRichNotification** pod for your Notification Service Extension as shown below, and run pod update / install command :
```Ruby theme={null}
target "NotificationServices" do
pod 'MoEngageRichNotification','~>6.2.0'
end
```
### Integrate using Swift Package Manager
MoEngageRichNotification is supported through SPM from SDK version 6.2.0. To integrate use the following github url link and set the branch as master or version as 6.2.0 and above [https://github.com/moengage/MoEngage-iOS-RichNotification.git](https://github.com/moengage/MoEngage-iOS-RichNotification.git)
**Manual Integration**
* To integrate the `MoEngageRichNotification` SDK manually to your project follow this [doc](https://developers.moengage.com/hc/en-us/articles/4404183451412).
* Add `MoEngageRichNotification` to embedded binaries in the App target, and is linked in your Notification Service Extension target.
MORichNotification has been renamed to MoEngageRichNotification from version 6.0.0.Do update the podfile and import statement accordingly.
## 5. Set the App Group ID for Extension:
Turn ON App Groups in for your notification service extension target and enable the same App group id which was selected for the App Target(In the above steps).
## 6. Code Changes in Notification Service Extension:
```swift Swift theme={null}
import UserNotifications
// 1st Step
import MoEngageRichNotification
class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
// 2nd Step
MORichNotification.setAppGroupID()
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
// 3rd Step
MORichNotification.handle(richNotificationRequest: request, withContentHandler: contentHandler)
}
override func serviceExtensionTimeWillExpire() {
// Called just before the extension will be terminated by the system.
// Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
contentHandler(bestAttemptContent)
}
}
}
```
```objectivec Objective-C theme={null}
#import "NotificationService.h"
// 1st Step
#import
@interface NotificationService ()
@property (nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver);
@property (nonatomic, strong) UNMutableNotificationContent *bestAttemptContent;
@end
@implementation NotificationService
- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
@try {
// 2nd Step
[MORichNotification setAppGroupID:];
self.contentHandler = contentHandler;
self.bestAttemptContent = [request.content mutableCopy];
// 3rd Step
[MORichNotification handleWithRichNotificationRequest:request withContentHandler:contentHandler];
} @catch (NSException *exception) {
NSLog(@"MoEngage : exception : %@",exception);
}
}
/// Save the image to disk
- (void)serviceExtensionTimeWillExpire {
// Called just before the extension will be terminated by the system.
// Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
self.contentHandler(self.bestAttemptContent);
}
@end
```
Refer to the code above and do the following changes:
1. Import `MoEngageRichNotification` framework.
2. Set the App Group ID selected in the settings earlier using `setAppGroupID:` method.
3. Call `handleRichNotificationRequest: withContentHandler:` method.
**CriticalRich Notification Media Limitations:**
* Refer to the following [link](https://developer.apple.com/reference/usernotifications/unnotificationattachment) to know about the size and format limitation for attachments(media) supported in Rich Notifications.
* Http URL's aren't supported in iOS10 unless explicitly specified in the plist. You will have include App Transport Security Settings Dictionary in your Notification Service Extension's Info.plist and inside this set Allow Arbitrary Loads to YES.
**Image Guidelines**
* File Size: The maximum file size for image attachments can be 10MB.
* Dimensions: The maximum possible dimensions are 1038 x 1038 pixels. It can be anything smaller than 1038 pixels.
* Landscape vs Portrait: iOS supports both the orientations but we recommend using images that have a landscape orientation this is because depending on the dimensions, portrait images may look too tall.
# Test/Live Builds
* If you are testing the app on **Test Flight or on a live app store build**, make sure you upload the adhoc or production pem to our dashboard. And also in this case you have to send push notifications from **Live environment** of your account.
* For dev build, you can upload development or production certificate in dashboard, but make sure that you create your campaign in **Test environment**, as you cannot send push notifications to dev build from Live environment.
# Notification Payload
An example of the push payload sent to the app:
```json iOS Push Payload theme={null}
{
"aps": {
"alert": {
"title": "Notification Title",
"subtitle": "Notification Subtitle",
"body": "Notification Body"
},
"badge": 1,
"sound": "default",
"category": "INVITE_CATEGORY",
"content-available": 1,
"mutable-content": 1
},
"app_extra": {
"moe_deeplink": "moeapp://screen/settings",
"screenName": "Screen Name",
"screenData": {
"key1": "val1",
"key2": "val2"
}
},
"moengage": {
"silentPush": 1,
"cid": "55f2ba15a4ab4104a287bf88",
"app_id": "DAO6UGZ73D9RTK8B5W96TPYN_DEBUG",
"moe_campaign_id": "55f2ba15a4ab4104a287bf88",
"moe_campaign_name": "Campaign Name",
"inbox_expiry": "1571905058",
"webUrl": "https://google.com",
"couponCode": "APP200",
"media-attachment": "https://image.moengage.com/testImg.png",
"media-type": "image"
}
}
```
Description of different keys in the payload:
* **aps**: This key is used by the iOS to display the notification, and the following are the keys present within it:
* **alert** : Message Content.
* **title** : Gives Notification title.
* **subtitle** : Gives Notification subtitle.
* **body** : Gives the message body of the notification
* **badge**: Gives the badge number to be displayed on top of the App Icon. MoEngage platform supports only two possible values i.e, 0/1. If the value is 1 then the SDK will increment the badge number on the app icon and if it's 0 then the badge number will be reset and there will be no badge displayed on the app icon.
* **sound**: This key gives the filename of the audio file to be played on receiving the notification. If no filename is provided while creating the campaign, to play the os default sound this key is set to the value "default".
* **category**: This key is used by OS for deciding the set of action buttons to be displayed for the notification. Also, the same category is used by OS to decide which Notification Content Extension target to display if present.
* **content-available**: If the value of this key is set to 1, then if the app is present in the background it will get a callback(`application:didReceiveRemoteNotification:fetchCompletionHandle`) to refresh the app content in background. Use this key only if you have to process the push notification in background. By default, this key will be unset.
* **mutable-content**: This key is by default set to 1 for all the campaigns, this is to make sure that the Notification Service Extension target gets the callback on receiving the notification to be processed by MORichNotification. If set to 0 the extension target won't get the callback.
* **app\_extra**: This key will contain the keys which are to be used by App Developers, i.e, Custom key value pairs and screenName for navigation.
* **moe\_deeplink**: This key contains the deeplinking URL if provided during the campaign creation. The SDK will process this key and will attempt to open the deeplink URL if it's valid.
* **screenName**: This key gives screen name where the user has to be navigated on clicking the notification. This navigation is not done by the SDK. The possible values for this parameter are something which app developers will have to define in their project. If provided while creating the campaign, it will be present in the notification payload. And implementing the part to parse and get `screenName` parameter's value and to navigate to the mentioned screen has to be implemented by the app developers.
* **screenData**: This contains the custom key-value pairs entered while creating the campaign, which can be made use by the app developers for any of their use-cases.
* **moengage** : This will contain keys which are to be used by SDK, app developers should not be making any change to this part of the payload and also avoid using this part of the payload, as we may update the structure of this part of payload as per our need. (with the exception being cid, media-attachment, media-type, app\_id which we will not change)
* **silentPush**: This key is present and set to `1` for silent pushes sent from MoEngage.
* **cid**: Unique ID for the campaign.
* **app\_id**: The Workspace ID of the account where the campaign was created.
* **moe\_campain\_id** and **moe\_campaign\_name** : Used by analytics module to track attributes for Notification related events.
* **inbox\_expiry**: This key gives the timestamp at which the notification will be deleted from the app inbox.
* **webUrl**: This key contains the Rich-landing URL if provided during the campaign creation. The SDK will process this key and will open the URL(if valid) in an instance of SFSafariViewController. Use Rich-landing action if you wish to open a web page inside the app on click of the push notification. For e.g. `webUrl` - [https://www.google.com](https://www.google.com/).
* **couponCode**: This key contains the coupon code if provided during the campaign creation. On clicking the notification, if this key is present in the push payload the SDK will display an alert with the coupon code and will give an option to user to copy the coupon to the os clipboard.For e.g. `couponCode` - APP200.
* **media-attachment:** The media-attachment key in the payload gives you the URL of the media which you can download.
* **media-type**: Type of media present in the URL given in media-attachment i.e, image/audio/video.
**Define Valid URL Schemes for DeepLinks (LSApplicationQueriesSchemes)**
**LSApplicationQueriesSchemes**(Array - iOS) Specifies the URL schemes you want the app to be able to use with the `canOpenURL:` method of the UIApplication class(which is being used in our SDK). For each URL scheme you want your app to use with the deeplinks, add it as a string in this array in Info.plist. For more info follow this [link](https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/LaunchServicesKeys.html#//apple_ref/doc/uid/TP40009250-SW14).
**HTTP URLs**
Http URL's aren't supported in iOS9 unless explicitly specified in the plist. You will have include **App Transport Security Settings** Dictionary in your Info.plist and inside this set **Allow Arbitrary Loads** to **YES**.
# Push Templates
Source: https://moengage.com/docs/developer-guide/ios-sdk/integration-with-older-version-of-sdk/push/advanced/push-templates
Customize expanded push notification appearance using Notification Content Extension with MoEngage.
Starting from MoEngage iOS SDK version `6.2.0` and MORichNotification version `4.0.0`, push templates will be supported where you would be able to customize the way notification looks in expanded mode. This feature is supported in**iOS 12.0 and above**. For info on how to create campaigns with templates in the dashboard refer to this [link](https://help.moengage.com/hc/en-us/articles/4415622460948-Push-Templates?_gl=1*1oma0f1*_ga*MTU4NTM0MzI0NS4xNzI3MTcwMzYy*_ga_SEBHW7YTZ7*czE3NzA2OTUzMDIkbzE0NiRnMSR0MTc3MDcxODYxOSRqNjAkbDAkaDA.).
**iOS 15.0 Update**
With iOS 15.0 update, we have released `MORichNotification` version `5.2.0` where for iOS 15.0 and above we have updated the layout to show content at the top and media at bottom, to have it in line with the standard notification layout.
Make sure you have completed the [App Target](https://developers.moengage.com/hc/en-us/articles/43960004257428-iOS-Push-Integration-Tutorial#h_01K4MBZ6WN3PTSSS6N6K2YQ8S2) and [Notification Service Extension](https://developers.moengage.com/hc/en-us/articles/43960004257428-iOS-Push-Integration-Tutorial#h_01K4MBZ6WN3PTSSS6N6K2YQ8S2) Implementation for supporting Rich Push in your project before proceeding with the below steps.
# STEPS:
For supporting these custom push templates, your project needs to have a Notification Content Extension. Follow the below steps to create a Content Extension and to set it up to support MoEngage templates:
## 1. Create a Notification Content Extension
After the target is created, Activate the scheme for Extension when prompted for the same. After this, your extension will be added to the project you will see a class with the extension name provided by you while creating and .plist file associated with it.
## 2. Set deployment target and Add Required frameworks
Now set the deployment target to **iOS 12.0** or above, since we support this feature from iOS 12.0. After that add `UserNotifications.framework` and `UserNotificationsUI.framework` in Frameworks and Libraries as shown:
## 3. Add required Capabilities
In Capabilities Section add **App Groups** and select the same app group id which you have configured in your App target and Notification Service Extension target.
**App Group ID Recommendation**
We recommend having a separate App Group ID set for MoEngage with the format `group.{app bundle id}.MoEngage`. And make sure the same app group id is enabled for all the targets where MoEngage is being used.
## 4. Info.plist changes
Make the changes in the `Info.plist` of your Notification Content Extension, as shown above, set NSExtensionAttributes as following:
| Attribute | Attribute Value |
| ---------------------------------------------- | ------------------- |
| UNNotificationExtensionCategory | MOE\_PUSH\_TEMPLATE |
| UNNotificationExtensionInitialContentSizeRatio | 1.2 |
| UNNotificationExtensionDefaultContentHidden | YES |
| UNNotificationExtensionUserInteractionEnabled | YES |
## 5. Storyboard changes
Select `MainInterface.storyboard` in your Content extension and remove the default label which is placed there and set the background color of the view to clear color, as shown:
## 6. MoEngageRichNotification Integration
### Integration via CocoaPod
For integrating through CocoaPod, include **MoEngageRichNotification** pod for your Notification Content Extension as shown below, and run pod update / install command :
```Ruby theme={null}
target "PushTemplatesExtension" do
pod 'MoEngageRichNotification','~>6.2.0'
end
```
### Integration via Swift Package Manager
For integrating through SPM, use the following github url link and set the branch as master or version as 6.2.0 and above [https://github.com/moengage/MoEngage-iOS-RichNotification.git](https://github.com/moengage/MoEngage-iOS-RichNotification.git)
**Manual Integration**
* To integrate the `MoEngageRichNotification` SDK manually to your project follow this [doc](https://developers.moengage.com/hc/en-us/articles/4404183451412).
* Add `MoEngageRichNotification` to embedded binaries in the App target, and ensure it is linked to your Notification Content Extension target.
## 7. Code Changes in Content Extension:
```swift Swift theme={null}
import UIKit
import UserNotifications
import UserNotificationsUI
import MoEngageRichNotification
class NotificationViewController: UIViewController, UNNotificationContentExtension {
override func viewDidLoad() {
super.viewDidLoad()
// Set App Group ID
MORichNotification.setAppGroupID("Your App Group ID")
}
func didReceive(_ notification: UNNotification) {
// Method to add template to UI
MORichNotification.addPushTemplate(toController: self, withNotification: notification)
}
}
```
```objectivec Objective-C theme={null}
#import "NotificationViewController.h"
#import
#import
#import
@interface NotificationViewController ()
@end
@implementation NotificationViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Set App Group ID
[MORichNotification setAppGroupID:@"Your App Group ID"];
}
- (void)didReceiveNotification:(UNNotification *)notification {
// Method to add template to UI
[MORichNotification addPushTemplateToController:self withNotification:notification];
}
@end
```
As shown above, make these changes in your `NotificationViewController` class:
1. Set the same App Group ID in `viewDidLoad()` method which was enabled in [Capabilities](https://developers.moengage.com/hc/en-us/articles/4403956104084-Push-Templates#3-add-required-capabilities-0-3). `[Recommended: group.{app bundle id}.MoEngage]`
2. Call `addPushTemplateToController:withNotification:` method to add template in `didReceiveNotification()` callback.
## 8. Notification Click callback in App:
In the case of Simple Image Carousel notification, to know which slide was clicked by the user, make use of `MOMessagingDelegate` to get `notificationClicked(withScreenName: andKVPairs:)` callback to get key-value pairs and screen name if set for the clicked slide. Refer to the example below, here we are registering for the callback in AppDelegate:
```swift Swift theme={null}
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate, MOMessagingDelegate{
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Set the delegate
MOMessaging.sharedInstance.setMessagingDelegate(self)
//Rest of the implementation
}
// Notification Clicked Callback
func notificationClicked(withScreenName screenName: String?, andKVPairs kvPairs: [AnyHashable : Any]?) {
if let screenName = screenName {
print("Navigate to Screen:\(screenName)")
}
if let actionKVPairs = kvPairs {
print("Selected Action KVPair:\(actionKVPairs)")
}
}
// Notification Clicked Callback with Push Payload
func notificationClicked(withScreenName screenName: String?, kvPairs: [AnyHashable : Any]?, andPushPayload userInfo: [AnyHashable : Any]) {
print("Push Payload: \(userInfo)")
if let screenName = screenName {
print("Navigate to Screen:\(screenName)")
}
if let actionKVPairs = kvPairs {
print("Selected Action KVPair:\(actionKVPairs)")
}
}
}
```
```objectivec Objective-C theme={null}
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Set the delegate
[[MOMessaging sharedInstance] setMessagingDelegate:self forAppID:@"YOUR WORKSPACE ID"];
//Rest of the implementation
}
// Notification Clicked Callback
-(void)notificationClickedWithScreenName:(NSString *)screenName andKVPairs:(NSDictionary *)kvPairs{
if (screenName) {
NSLog(@"Screen Name : %@",screenName);
}
if (kvPairs) {
NSLog(@"KV Pairs : %@",kvPairs);
}
}
// Notification Clicked Callback with Push Payload
-(void)notificationClickedWithScreenName:(NSString *)screenName KVPairs:(NSDictionary *)kvPairs andPushPayload:(NSDictionary *)userInfo{
NSLog(@"Push Payload: %@",userInfo);
if (screenName) {
NSLog(@"Screen Name : %@",screenName);
}
if (kvPairs) {
NSLog(@"KV Pairs : %@",kvPairs);
}
}
@end
```
This callback will also be called for normal and Stylized Basic Notifications and could be made use of there as well.
# Real-Time Triggers
Source: https://moengage.com/docs/developer-guide/ios-sdk/integration-with-older-version-of-sdk/push/advanced/real-time-triggers
Set up device-triggered push notifications that fire instantly when a user performs an event on iOS.
Real-time device triggers are push notifications that are triggered instantly in the device whenever a trigger event(configured while creating the campaign) is tracked with the SDK [trackEvent:](https://developers.moengage.com/hc/en-us/articles/4403922636308) method. In this case, the notifications are triggered in the device, which enables you to post notifications even in offline scenarios.
Real-Time Triggers are available from SDK version [4.0.0](https://developers.moengage.com/hc/en-us/articles/4404198236564-Change-Log#v4-0-0-0-33)
# SDK Installation
From MoEngage-iOS-SDK version 8.2.0, MoEngageRealTimeTrigger module is separated from the SDK to a separate module as MoEngageRealTimeTrigger and hence has to be added separately.
[](http://cocoapods.org/pods/MoEngageRealTimeTrigger)
## Install using CocoaPod
Integrate the RealTimeTrigger framework by adding the dependency in the podfile as shown below.
```auto Ruby theme={null}
pod 'MoEngageRealTimeTrigger','~>1.2.0'
```
Now run `pod install` to install the framework
## Install using Swift Package Manager
MoEngageRealTimeTrigger is supported through SPM from SDK version 1.2.0. To integrate, use the following github url link and set the branch as master or version as 1.2.0 and above [https://github.com/moengage/MoEngage-iOS-RealTimeTrigger.git](https://github.com/moengage/MoEngage-iOS-RealTimeTrigger.git)
# Manual Syncing
MoEngage SDK syncs all the real-time trigger campaigns whenever the app is **launched OR comes to the foreground**. But in case its needed to manually sync the device triggers for any of the background tasks, use `syncRealTimeTriggersWithCompletionBlock:` as shown below:
```swift Swift theme={null}
MORealTimeTrigger.sharedInstance.syncRealTimeTriggers { (rtSyncCompleted) in
if(rtSyncCompleted){
print("Real-Time trigger sync successfull")
}
}
```
```objectivec Objective-C theme={null}
[[MORealTimeTrigger sharedInstance] syncRealTimeTriggersForAppID:@"YOUR APP ID" andCompletionHandler:^(BOOL rtSyncCompleted) {
if (rtSyncCompleted) {
NSLog(@"Real-Time trigger sync successfull");
}
}];
```
# Additional Callbacks for version below iOS 10
For iOS 10 and above, MoEngage SDK uses the UserNotification framework for triggering notifications and relies on the callbacks from **UNUserNotificationCenter** to obtain and process the notification payload. Therefore, make sure the SDK methods are called in UNUserNotificationCenter delegate callbacks as mentioned in this [doc](https://developers.moengage.com/hc/en-us/articles/43960004257428-iOS-Push-Integration-Tutorial#h_01K45FKD0XDH4X776R47JA04GJ).
For iOS versions below iOS 10 call `didReceieveNotificationinApplication: withInfo:openDeeplinkUrlAutomatically:` method of MoEngage SDK as shown below.
```swift Swift theme={null}
func application(_ application: UIApplication, didReceive notification: UILocalNotification) {
if let userInfo = notification.userInfo {
MoEngage.sharedInstance().didReceieveNotificationinApplication(application, withInfo: userInfo, openDeeplinkUrlAutomatically: true)
}
}
```
```objectivec Objective-C theme={null}
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification{
NSDictionary* userInfo = notification.userInfo;
[[MoEngage sharedInstance]didReceieveNotificationinApplication:application withInfo:userInfo openDeeplinkUrlAutomatically:YES];
}
```
# Manual Integration
Source: https://moengage.com/docs/developer-guide/ios-sdk/manual-integration/manual-integration
Install and configure MoEngage iOS SDK frameworks manually without using a dependency manager.
To install the frameworks manually, follow the steps below:
Download the latest SDKs from our GitHub repository. You can find the download URLs for each SDK in [package.json](https://github.com/moengage/apple-sdk/blob/master/package.json).
# Embedded Frameworks in App Target
Make sure to embed the required frameworks to App Target as described in the following image, set the Embed option to **Embed & Sign** for MoEngage framework files:
Required Frameworks:
| Frameworks | Status | Purpose |
| --------------------- | -------- | --------------------------------------------------------------------------------------------- |
| MoEngageCore | Required | Provides the foundational services, initialization, and lifecycle management for the SDK. |
| MoEngageSDK | Required | Serves as the primary public interface and orchestrator for all MoEngage SDK functionalities. |
| MoEngageSecurity | Required | Enables data protection during access and transmission. |
| MoEngageMessaging | Required | Manages push notification registration, payload handling, and core messaging features. |
| MoEngageCampaignsCore | Required | Manages campaign payload handling and display. |
Add-on Frameworks:
| Frameworks | Status | Purpose |
| ------------------------ | -------- | ---------------------------------------------------------------------------------------------------------------- |
| MoEngageTriggerEvaluator | Optional | Enables the display of in-app messages and device triggered push notifications, based on AND trigger conditions. |
| MoEngageInApps | Optional | Enables the display of in-app messages, such as pop-ups and modals. |
| MoEngageGeofence | Optional | Enables geofence monitoring for location-based campaign triggers. |
| MoEngageInbox | Optional | Enables a persistent notification center (inbox) within the application. |
| MoEngageCards | Optional | Enables the display and management of Content Cards. |
| MoEngageRichNotification | Optional | Enables rich media content (images, video, audio) and templates in push notifications. |
| MoEngageRealTimeTrigger | Optional | Facilitates high-frequency, real-time campaign triggers based on user events. |
| MoEngageLiveActivity | Optional | Manages live activities registration, payload handling, and tracking. |
# Link MoEngageRichNotification framework in App Extensions
This is only required if you are using the `MoEnagageRichNotification` framework in the project. Make sure to link the framework in the Extension targets as shown below and set the **Embed** option to **Do Not Embed** in this case, as it is already embedded in your App Target:
In extension target build settings, add `@executable_path/../../Frameworks` as additional `LD_RUNPATH_SEARCH_PATHS`.
# Migration to SDK version 6.0.0
Source: https://moengage.com/docs/developer-guide/ios-sdk/migration/migration-to-sdk-version-6-0-0
Migrate your MoEngage iOS SDK integration to version 6.0.0 with updated initialization and APIs.
We have made quite a few changes in SDK version 6.0.0 and if you are someone who was using an older version of our SDK and planning to move to version 6.0.0 or above here are the changes to be made while migrating:
# iOS 8.\* Support Removed
From SDK version `6.0.0` we have set the deployment target as `iOS 9.0` and hence have removed support for `iOS 8.*`. We have decided to do this since the user base in iOS 8.0 is very less and most of the developers are already setting their app's deployment target to greater than iOS 9.0.
# Initialization Method Deprecation
We have deprecated the previous initialization methods and have introduced new methods. This is to simplify initialization by reducing the number of arguments in the method:
**Deprecated methods**
```objective-c Objective C wrap theme={null}
/**
For TEST Environment
@warning This method is deprecated and will be removed from SDK Version 7.0.0. Use initializeDevWithAppID:withLaunchOptions instead
*/
-(void)initializeDevWithApiKey:(NSString *_Nonnull)apiKey inApplication:(UIApplication *_Nullable)application withLaunchOptions:(NSDictionary *_Nullable)launchOptions openDeeplinkUrlAutomatically:(BOOL)openUrl __deprecated_msg("Use initializeDevWithAppID:withLaunchOptions instead.");
/**
For LIVE Environment
@warning This method is deprecated and will be removed from SDK Version 7.0.0. Use initializeProdWithAppID:withLaunchOptions: instead
*/
-(void)initializeProdWithApiKey:(NSString *_Nonnull)apiKey inApplication:(UIApplication *_Nullable)application withLaunchOptions:(NSDictionary *_Nullable)launchOptions openDeeplinkUrlAutomatically:(BOOL)openUrl __deprecated_msg("Use initializeProdWithAppID:withLaunchOptions: instead.");
```
**New methods**
```objective-c Objective C wrap theme={null}
// For TEST Environment
-(void)initializeDevWithAppID:(NSString *_Nonnull)appID withLaunchOptions:(NSDictionary *_Nullable)launchOptions;
// For LIVE Environment
-(void)initializeProdWithAppID:(NSString *_Nonnull)appID withLaunchOptions:(NSDictionary *_Nullable)launchOptions;
```
For more info on SDK Initialization, refer to the following [doc](/developer-guide/ios-sdk/sdk-integration/basic/sdk-initialization).
# Analytics Module Changes
## Track Event:
We have Introduced `MOProperties` class to track all the event attributes. And hence we have deprecated the earlier methods and included `trackEvent:withProperties:` to track events. Refer to this [link](/developer-guide/ios-sdk/data-tracking/basic/tracking-events) for more info.
**Deprecated Methods**
```objective-c Objective C wrap theme={null}
/**
@warning This method is deprecated and will be removed in SDK version 7.0.0. Use trackEvent:withProperties: instead.
*/
-(void)trackEvent:(NSString *_Nonnull)name andPayload:(NSMutableDictionary *_Nullable)payload __deprecated_msg("Use trackEvent:withProperties: instead.");
/**
@warning This method is deprecated and will be removed in SDK version 7.0.0. Use trackEvent:withProperties: instead.
*/
-(void)trackEvent:(NSString *_Nonnull)name builderPayload:(MOPayloadBuilder *_Nullable)payload __deprecated_msg("Use trackEvent:withProperties: instead.");
```
**New methods**
```objective-c Objective C wrap theme={null}
/**
Call this method to track events.
@param name Event name to be tracked
@param properties of type MOProperties. See MOProperties for more details.
@version Available from SDK version 6.0.0 and above
*/
-(void)trackEvent:(NSString *_Nonnull)name withProperties:(MOProperties *_Nullable)properties;
```
## User Attribute Tracking:
We have added a couple of additional methods to track date user attributes in the SDK, more info in this [doc](/developer-guide/ios-sdk/data-tracking/basic/tracking-user-attributes) :
```objective-c Objective C wrap theme={null}
/**
Use this method to set a user attribute which is NSDate instance.
@param date The NSDate instance value to track.
*/
-(void)setUserAttributeDate:(NSDate* _Nonnull)date forKey:(NSString *_Nonnull)key;
/**
Use this method to set a user attribute which is NSDate instance.
@param dateStr Date String in ISO date format [yyyy-MM-dd'T'HH:mm:ss'Z'].
*/
-(void)setUserAttributeISODateString:(NSString* _Nonnull)dateStr forKey:(NSString *_Nonnull)key;
```
# Messaging Module Changes
## Notification Received Method Deprecation:
**AppDelegate Swizzling :**
From SDK version 5.0.0, we have implemented Swizzling of AppDelegate inside the SDK, due to which SDK, by default, gets all the callbacks related to Notifications. Therefore, if AppDelegate Swizzling is enabled, then developers can skip calling the SDK methods on Notification Callbacks. For more info on the same, refer to the following [link](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial#verify-dashboard-configuration).
We have deprecated `didReceieveNotificationinApplication:withInfo:openDeeplinkUrlAutomatically:` instead, use `didReceieveNotificationinApplication:withInfo:`.
**Deprecated method**
```objective-c Objective C wrap theme={null}
/**
Call this method in AppDelegate in didReceiveRemoteNotification
@warning This method is deprecated and will be removed from SDK Version 7.0.0. Use didReceieveNotificationinApplication:withInfo: instead
*/
-(void)didReceieveNotificationinApplication:(UIApplication*_Nullable)application withInfo:(NSDictionary* _Nonnull)userInfo openDeeplinkUrlAutomatically:(BOOL)openUrl __deprecated_msg("Use didReceieveNotificationinApplication:withInfo: instead.");
```
**New methods**
```objective-c Objective C wrap theme={null}
/**
Call this method in AppDelegate in didReceiveRemoteNotification
*/
-(void)didReceieveNotificationinApplication:(UIApplication*_Nullable)application withInfo:(NSDictionary* _Nonnull)userInfo;
```
# InApp Module Changes
* The InApp module has been completely revamped and includes a lot of changes, the primary one being we have separated the module from the `MoEngage-iOS-SDK`. Therefore, now to use In-Apps in your app you will have to integrate `MoEngageInApp` module to your project. Refer to this [link](/developer-guide/ios-sdk/in-app-messages/in-app-nativ) for integrating the inApp Module.
* We have **removed support** for InApps in **Landscape Orientation** and **iPads** as the existing templates that we have are not made considering them, and therefore may end up breaking in the said scenarios.
* We have added support for **Context-based InApps** wherein we can tag InApps and show InApps based on the current context set on the SDK. Refer to this [link](/developer-guide/ios-sdk/in-app-messages/in-app-nativ) for more info.
* We have removed support for most of the older methods and replaced them with new ones to have it consistent across platforms. To know the differences in the API to be used refer below links:
* [InApp APIs for SDK version 6.0.0 and above](/developer-guide/ios-sdk/in-app-messages/in-app-nativ)
* [InApp APIs for SDK version 5.2.6 and below](/hc/en-us/articles/4404155414676)
# Migration to SDK version 7.0.0
Source: https://moengage.com/docs/developer-guide/ios-sdk/migration/migration-to-sdk-version-7-0-0
Migrate your MoEngage iOS SDK integration to version 7.0.0 with updated initialization and config.
We have made quite a few changes in SDK version 7.0.0 and if you are someone who was using an older version of our SDK and planning to move to version 7.0.0 or above here are the changes to be made while migrating:
# iOS 9.\* Support Removed
From SDK version `7.0.0` we have set the deployment target as `iOS 10.0` and hence have removed support for `iOS 9.*`. We have decided to do this since the user base in iOS 9.0 is very less and most of the developers are already setting their app's deployment target to greater than iOS 10.0.
# Initialisation Method Changes
We have deprecated the previous initialization methods and have introduced new methods. The new methods accept the MOSDKConfig instance as an argument which can contain multiple parameters along with the Workspace ID required for setting up the SDK on app launch:
**Deprecated methods**
```swift Swift wrap theme={null}
var yourMoEAppID = "Your Workspace ID"
#if DEBUG
MoEngage.sharedInstance().initializeDev(withAppID:yourMoEAppID, withLaunchOptions: nil)
#else
MoEngage.sharedInstance().initializeProd(withAppID:yourMoEAppID, withLaunchOptions: nil)
#endif
```
```objective-c Objective C wrap theme={null}
NSString* yourMoEngageAppID = @"Your Workspace ID";
#ifdef DEBUG
[[MoEngage sharedInstance] initializeDevWithAppID:yourMoEngageAppID withLaunchOptions:launchOptions];
#else
[[MoEngage sharedInstance] initializeProdWithAppID:yourMoEngageAppID withLaunchOptions:launchOptions];
#endif
```
For info on the new initialization methods, refer to this [link](/developer-guide/ios-sdk/sdk-integration/basic/sdk-initialization).
# Setting Region/Data Center
MODataCenter: We’ve introduced new APIs to set up the Data center in the SDK, earlier API which made use of `DataRedirectionRegion` Enumerator is no longer supported, instead the same has to be configured using MOSDKConfig and provided during Initialization, refer [doc](/developer-guide/ios-sdk/sdk-integration/basic/data-center) for info on how to configure in the latest SDK versions.
**Older method \[6.3.1 and below]**
```swift Swift wrap theme={null}
/*
DataRedirectionRegion Enum Values:
MOE_REGION_SERV3
MOE_REGION_EU
MOE_REGION_DEFAULT
*/
// Eg to redirect data to EU Data Center
MoEngage.redirectData(to: MOE_REGION_EU)
```
```objective-c Objective C wrap theme={null}
/*
DataRedirectionRegion Enum Values:
MOE_REGION_SERV3
MOE_REGION_EU
MOE_REGION_DEFAULT
*/
// Eg to redirect data to EU Data Center
[MoEngage redirectDataToRegion:MOE_REGION_EU];
```
# App Target: Setting App Group ID
App Group ID for App target was earlier set using `setAppGroupID:`, which is no longer supported. Make use of the MOSDKConfig to configure the same in the latest SDK versions (Refer [link](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial#step-1-implement-notification-service-extension-nse) for more info)
**Older method \[6.3.1 and below]**
```swift Swift theme={null}
MoEngage.setAppGroupID("AppGroupID")
```
```objective-c Objective C wrap theme={null}
[MoEngage setAppGroupID:@"AppGroupID"];
```
# Enable Logs Changes
For troubleshooting, the method to enable SDK logs has been changed from `debug:` to `enableSDKLogs:`. The earlier method was used as shown below, and for the updated implementation in the latest SDK versions refer to the following [doc](/hc/en-us/articles/4404197969812-Troubleshooting-And-FAQs#enable-sdk-logs-0-0):
**Older method \[6.3.1 and below]**
```swift Swift theme={null}
MoEngage.debug(LOG_ALL)
```
```objective-c Objective C wrap theme={null}
[MoEngage debug:LOG_ALL];
```
# Migration to SDK version 8.2.0
Source: https://moengage.com/docs/developer-guide/ios-sdk/migration/migration-to-sdk-version-8-2-0
Migrate your MoEngage iOS SDK to version 8.2.0 with updated pod names, imports, and initialization.
We have made some major changes in SDK version 8.2.0, and if you are someone who was using an older version of our SDK and planning to move to version 8.2.0 or above, here are the changes to be made while migrating:
# Update the Pod names
From SDK version `8.2.0` , we have updated some of the pod names. Refer to the table below to update the podfile.
| SDK Version 7.0.0 | SDK Version 8.2.0 |
| :------------------------ | :------------------------------ |
| import MOGeofence | import MoEngageGeofence |
| import MORichNotification | import MoEngageRichNotification |
# Update the Import
From SDK version `8.2.0` , we have updated some of the framework names. Refer to the table below to update the import statement for the modules.
| SDK Version 7.0.0 | SDK Version 8.2.0 |
| :------------------------ | :------------------------------ |
| import MoEngage | import MoEngageSDK |
| import MOInApp | import MoEngageInApps |
| import MOCards | import MoEngageCards |
| import MOGeofence | import MoEngageGeofence |
| import MORichNotification | import MoEngageRichNotification |
# Initialisation Method Changes
We have deprecated the previous initialization methods and have introduced new methods.
**Deprecated methods**
```swift Swift wrap theme={null}
let sdkConfig = MOSDKConfig(withAppID: "YOUR Workspace ID")
#if DEBUG
MoEngage.sharedInstance().initializeTest(with: sdkConfig, andLaunchOptions: launchOptions)
#else
MoEngage.sharedInstance().initializeLive(with: sdkConfig, andLaunchOptions: launchOptions)
#endif
```
```objective-c Objective C wrap theme={null}
MOSDKConfig* sdkConfig = [[MOSDKConfig alloc] initWithAppID:@"YOUR Workspace ID"];
#ifdef DEBUG
[[MoEngage sharedInstance] initializeTestWithConfig:sdkConfig andLaunchOptions:launchOptions];
#else
[[MoEngage sharedInstance] initializeLiveWithConfig:sdkConfig andLaunchOptions:launchOptions];
#endif
```
For info on the new initialization methods, refer to this [link](/developer-guide/ios-sdk/sdk-integration/basic/sdk-initialization).
# Setting Region/Data Center
MODataCenter: DataCenter names have been updated in the SDK version `8.2.0`. Following are the existing ones used in the SDK version in `7.0.0` and above.
```swift Swift theme={null}
typedef enum {
DATA_CENTER_01,
DATA_CENTER_02,
DATA_CENTER_03
}MODataCenter;
```
```objective-c Objective C theme={null}
typedef enum {
DATA_CENTER_01,
DATA_CENTER_02,
DATA_CENTER_03
}MODataCenter;
```
For info on the new DataCenter value, refer to this [link](/developer-guide/ios-sdk/sdk-integration/basic/data-center).
# App Target: Setting App Group ID
App Group ID for App target was earlier set using `setAppGroupID:`, which is no longer supported. Make use of the MOSDKConfig to configure the same in the latest SDK versions(Refer to the [link](/developer-guide/ios-sdk/sdk-integration/basic/sdk-initialization) for more info)
**Older method\[6.3.1 and below]**
```swift Swift theme={null}
MoEngage.setAppGroupID("AppGroupID")
```
```objective-c Objective C theme={null}
[MoEngage setAppGroupID:@"AppGroupID"];
```
# Enable Logs Changes
For troubleshooting, the method to enable SDK logs has been changed from `debug:` to `enableSDKLogs :`. The earlier method was used, as shown below, and for the updated implementation in the latest SDK versions, refer to the following [doc](/developer-guide/ios-sdk/troubleshooting-and-faqs/troubleshooting-and-faqs-ios):
**Older method\[6.3.1 and below]**
```swift Swift theme={null}
MoEngage.debug(LOG_ALL)
```
```objective-c Objective C theme={null}
[MoEngage debug:LOG_ALL];
```
# Tracking User Attributes
From SDK version `8.2.0` , we have deprecated a couple of UserAttribute methods. Refer to the table below to get the updated method
| SDK Version 7.0.0 | SDK Version 8.2.0 |
| :------------------------------------------------------------------ | :---------------------------------------------------------------------------------------------------------------------------------------------- |
| MoEngage.sharedInstance().setUserUniqueID(UNIQUE\_ID) | MOAnalytics.sharedInstance.setUniqueID(UNIQUE\_ID) |
| MoEngage.sharedInstance().setUserName(userName) | MOAnalytics.sharedInstance.setName(userName) |
| MoEngage.sharedInstance().setUserLastName(userLastname) | MOAnalytics.sharedInstance.setLastName(userLastname) |
| MoEngage.sharedInstance().setUserFirstName(userFirstName) | MOAnalytics.sharedInstance.setFirstName(userFirstName) |
| MoEngage.sharedInstance().setUserEmailID(userEmailID) | MOAnalytics.sharedInstance.setEmailID(userEmailID) |
| MoEngage.sharedInstance().setUserMobileNo(userPhoneNo) | MOAnalytics.sharedInstance.setMobileNumber(userPhoneNo) |
| MoEngage.sharedInstance().setUserGender(MALE) | MOAnalytics.sharedInstance.setGender(.male) |
| MoEngage.sharedInstance().setUserDateOfBirth(userBirthdate) | MOAnalytics.sharedInstance.setDateOfBirth(userBirthdate) |
| MoEngage.sharedInstance().setUserLocationLatitude | MOAnalytics.sharedInstance.setLocation(MOGeoLocation(withLatitude: userLocationLat, andLongitude: userLocationLng)) |
| (userLocationLat, andLongitude: userLocationLng) | |
| MoEngage.sharedInstance().setUserAttributeISODateString | MOAnalytics.sharedInstance.setUserAttributeISODate("2020-01-12T18:45:59Z", withAttributeName: "Date Attr 2")e |
| ("2020-01-12T18:45:59Z", forKey: "DateAttr2") | |
| MoEngage.sharedInstance().setUserAttributeTimestamp | MOAnalytics.sharedInstance.setUserAttributeEpochTime(663333, withAttributeName: "Date Attr 3") |
| (NSDate().timeIntervalSince1970, forKey:"DateAttr3") | |
| MoEngage.sharedInstance().setUserAttributeLocationLatitude | MOAnalytics.sharedInstance.setLocation(MOGeoLocation.init(withLatitude: 72.90909, andLongitude: 12.34567), withAttributeName: "attribute name") |
| (12.98798, longitude: 34.98789, forKey:"location\_attribute\_name") | |
For more information on tracking user attributes methods, refer to this [doc](/developer-guide/ios-sdk/data-tracking/basic/tracking-user-attributes).
# Push Notification
From SDK version `8.2.0` , we have updated methods related to Push Notification.Refer to the table below to use the updated one.
| SDK Version 7.0.0 | SDK Version 8.2.0 |
| :----------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------- |
| MoEngage.sharedInstance().disableBadgeReset = true | MoEngage.sharedInstance().setDisableBadgeReset(true) |
| MORichNotification.handle(request, withContentHandler: contentHandler) | MORichNotification.handle(richNotificationRequest: request, withContentHandler: contentHandler) |
| MOPushTemplateHandler.sharedInstance().addPushTemplate(to: self, with: notification) | MORichNotification.addPushTemplate(toController: self, withNotification: notification) |
| //Set messaging delegate | //Set messaging delegate |
| MOMessaging.sharedInstance().messagingDelegate = self | MOMessaging.sharedInstance.setMessagingDelegate(self) |
# RealTimeTrigger and Inbox Module
From SDK version 8.0.0, RealTimeTrigger and Inbox Module are separated from the MoEngage-iOS-SDK.Hence, they must be integrated explicitly. Refer to the [link](/developer-guide/ios-sdk/push/advanced) for the document.
# Location Triggered
From SDK version `8.2.0` , we have updated methods related to Geofence. Refer to the table below to use the updated one.
| SDK Version 7.0.0 | SDK Version 8.2.0 |
| :------------------------------------------------------------ | :-------------------------------------------------- |
| MOGeofenceHandler.sharedInstance()?.startGeofenceMonitoring() | MOGeofence.sharedInstance.startGeofenceMonitoring() |
| MOGeofenceHandler.sharedInstance().delegate = self | MOGeofence.sharedInstance.setGeofenceDelegate(self) |
For more info on the Geofence feature, refer to this [doc](/developer-guide/ios-sdk/push/optional/location-triggered).
# InApp
From SDK version `8.2.0` , we have updated methods related to InApp.Refer to the table below to use the updated one.
| SDK Version 7.0.0 | SDK Version 8.2.0 |
| :--------------------------------------------- | :---------------------------------------------- |
| MOInApp.sharedInstance().show() | MOInApp.sharedInstance().showCampaign() |
| MOInApp.sharedInstance().inAppDelegate = self; | MOInApp.sharedInstance().setInAppDelegate(self) |
For more info on the InApp feature, refer to this [doc](/developer-guide/ios-sdk/in-app-messages/in-app-nativ).
# Cards
From SDK version `8.0.0` , we have updated methods related to Cards. Refer to the table below to use the updated one.
| SDK Version 7.0.0 | SDK Version 8.2.0 |
| :-------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| MoEngageCards.sharedInstance.pushCardsViewController | MOCards.sharedInstance.pushCardsViewController |
| (toNavigationController: self.navigationController!) | (toNavigationController: self.navigationController!) |
| MoEngageCards.sharedInstance.presentCardsViewController() | MOCards.sharedInstance.presentCardsViewController() |
| MoEngageCards.sharedInstance.getCardsViewController() | MOCards.sharedInstance.getCardsViewController(withUIConfiguration: nil, withCardsViewControllerDelegate: self, forAppID: "YOUR Workspace ID") cardsController in print("fetched CardsController") |
| MoEngageCards.sharedInstance.getNewCardsCount() | MOCards.sharedInstance.getNewCardsCount(forAppID: "YOUR Workspace ID", withCompletionBlock: count, accountMeta in print("Card count is (count)") ) |
| MoEngageCards.sharedInstance.getUnclickedCardsCount() | MOCards.sharedInstance.getUnclickedCardsCount(forAppID: "YOUR Workspace ID") count, accountMeta in print("UnClicked Card count is (count)") |
| MoEngageCards.sharedInstance.cardsDelegate = delegate | MOCards.sharedInstance.setCardsDelegate(delegate: self) |
For more info on the Cards feature, refer to this [doc](/developer-guide/ios-sdk/cards/cards-in-i-os).
# Migration to SDK version 9.0.0
Source: https://moengage.com/docs/developer-guide/ios-sdk/migration/migration-to-sdk-version-9-0-0
Migrate your MoEngage iOS SDK to version 9.0.0 with updated class names and initialization methods.
We have made some class name updates in SDK version 9.0.0 and if you are someone who was using an 8.2.0 and above version of our SDK and planning to move to version 9.0.0 or above, here are the changes to be made while migrating.
# Initialization Method Changes
We have updated the initialization method of SDK with SDKConfig as the required parameter and sdkState as an optional parameter.
### Deprecated methods
```swift file name wrap theme={null}
let sdkConfig = MOSDKConfig(withAppID: "YOUR Workspace ID")
#if DEBUG
MoEngage.sharedInstance().initializeDefaultTestInstance(with: sdkConfig, andLaunchOptions: launchOptions)
#else
MoEngage.sharedInstance().initializeDefaultLiveInstance(with: sdkConfig, andLaunchOptions: launchOptions)
#endif
```
```objective-c Objective C wrap theme={null}
MOSDKConfig* sdkConfig = [[MOSDKConfig alloc] initWithAppID:@"YOUR Workspace ID"];
#ifdef DEBUG
[[MoEngage sharedInstance] initializeDefaultTestInstanceWithConfig:sdkConfig andLaunchOptions:launchOptions];
#else
[[MoEngage sharedInstance] initializeDefaultLiveInstanceWithConfig:sdkConfig andLaunchOptions:launchOptions];
#endif
```
For information on the new initialization methods, refer to this [link](/developer-guide/ios-sdk/sdk-integration/basic/sdk-initialization).
# Setting Region/Data Center
MoEngageDataCenter: DataCenter class name has been updated in the SDK version `9.0.0`. Following are the existing ones used in the SDK version in `8.2.0` and above.
| SDK Version 8.2.0 | SDK Version 9.0.0 |
| :---------------- | :----------------- |
| MODataCenter | MoEngageDataCenter |
For information on the new DataCenter value, refer to this [link](/developer-guide/ios-sdk/sdk-integration/basic/data-center).
# Install/Update differentiation
| SDK Version 8.x.x | SDK Version 9.0.0 |
| :-------------------------------------------- | :------------------------------------------------------ |
| MoEngage.sharedInstance().appStatus(.install) | MoEngageSDKAnalytics.sharedInstance.appStatus(.install) |
For information on the new DataCenter value, refer to this [document](/developer-guide/ios-sdk/data-tracking/basic/install-update-differentiation).
# Analytics:
From SDK version `9.0.0`, we have updated methods related to Analytics. Refer to the table below to use the updated one.
| SDK Version 8.x.x | SDK Version 9.0.0 |
| :---------------- | :------------------- |
| MOAnalytics | MoEngageSDKAnalytics |
For information on tracking user attributes methods, refer to this [document](/developer-guide/ios-sdk/data-tracking/basic/tracking-events).
# Inapps
From SDK version `9.0.0`, we have updated methods related to Inapps. Refer to the table below to use the updated one.
| SDK Version 8.x.x | SDK Version 9.0.0 |
| :--------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| MOInapp | MoEngageSDKInApp |
| MOInApp.sharedInstance().showCampaign() | MoEngageSDKInApp.sharedInstance.showInApp() |
| MOInApp.sharedInstance().showNudge(at: NudgePositionTop) | MoEngageSDKInApp.sharedInstance.showNudge(atPosition: NudgePositionTop) |
| MOInAppNativeDelegate | MoEngageInAppNativeDelegate |
| func inAppShown(withCampaignInfoinappCampaign: MOInAppCampaign, foraccountMeta: MOAccountMeta) | func inAppShown(withCampaignInfoinappCampaign: MoEngageInAppCampaign, forAccountMetaaccountMeta: MoEngageAccountMeta) |
| `func inAppDismissed(withCampaignInfoinappCampaign: MOInAppCampaign, foraccountMeta: MOAccountMeta)` | `func inAppDismissed(withCampaignInfoinappCampaign: MoEngageInAppCampaign,forAccountMetaaccountMeta: MoEngageAccountMeta)` |
| `func inAppClicked(withCampaignInfoinappCampaign: MOInAppCampaign, andCustomActionInfocustomAction: MOInAppAction, foraccountMeta: MOAccountMeta)` | `func inAppClicked(withCampaignInfoinappCampaign: MoEngageInAppCampaign, andCustomActionInfocustomAction: MoEngageInAppAction, forAccountMetaaccountMeta: MoEngageAccountMeta)` |
| `func inAppClicked(withCampaignInfoinappCampaign: MOInAppCampaign, andNavigationActionInfonavigationAction: MOInAppAction, foraccountMeta: MOAccountMeta)` | `func inAppClicked(withCampaignInfoinappCampaign: MoEngageInAppCampaign, andNavigationActionInfonavigationAction: MoEngageInAppAction, forAccountMetaaccountMeta: MoEngageAccountMeta)` |
| `func selfHandledInAppTriggered(withInfoinappCampaign: MOInAppSelfHandledCampaign, foraccountMeta: MOAccountMeta)` | `func selfHandledInAppTriggered(withInfoinappCampaign: MoEngageInAppSelfHandledCampaign, forAccountMetaaccountMeta: MoEngageAccountMeta)` |
For more details, refer to the [InApp Native developer documentation](/developer-guide/ios-sdk/in-app-messages/in-app-nativ).
# Cards
From SDK version `9.0.0`, we have updated methods related to Cards. Refer to the table below to use the updated one.
| SDK Version 8.x.x | SDK Version 9.0.0 |
| :--------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------- |
| MOCards | MoEngageSDKCards |
| MOCardsDelegate | MoEngageCardsDelegate |
| MOCardsViewControllerDelegate | MoEngageCardsDelegate |
| `@objc optional func cardsSyncedSuccessfully(forAccountMeta accountMeta: MOAccountMeta)` | `@objc optional func cardsSyncedSuccessfully(forAccountMeta accountMeta: MoEngageAccountMeta)` |
# Push Notification
From SDK version `9.0.0`, we have updated methods related to Push Notifications. Refer to the table below to use the updated one.
| SDK Version 8.x.x | SDK Version 9.0.0 |
| :----------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------- |
| MORichNotification | MoEngageSDKRichNotification |
| `MoEngage.sharedInstance().registerForRemoteNotification(withCategories: nil, withUserNotificationCenterDelegate: self)` | `MoEngageSDKMessaging.sharedInstance.registerForRemoteNotification(withCategories: nil, andUserNotificationCenterDelegate: self)` |
| `MoEngage.sharedInstance().setPushToken(deviceToken)` | `MoEngageSDKMessaging.sharedInstance.setPushToken(deviceToken)` |
| `MoEngage.sharedInstance().didFailToRegisterForPush()` | `MoEngageSDKMessaging.sharedInstance.didFailToRegisterForPush()` |
| `MoEngage.sharedInstance().userNotificationCenter(center, didReceive: response)` | `MoEngageSDKMessaging.sharedInstance.userNotificationCenter(center, didReceive: response)` |
| `MoEngage.sharedInstance().didReceieveNotificationinApplication(application, withInfo: userInfo)` | `MoEngageSDKMessaging.sharedInstance.didReceieveNotification(inApplication: application, withInfo: userInfo)` |
| `MoEngage.sharedInstance().setDisableBadgeReset(true)` | `MoEngageSDKMessaging.sharedInstance.disableBadgeReset(true)` |
| `MOMessaging.sharedInstance.setMessagingDelegate(self)` | `MoEngageSDKMessaging.sharedInstance.setMessagingDelegate(self)` |
# RealTimeTrigger:
From SDK version `9.0.0`, we have updated methods related to RealTime Trigger. Refer to the table below to use the updated one.
| SDK Version 8.x.x | SDK Version 9.0.0 |
| :---------------- | :------------------------- |
| MORealTimeTrigger | MoEngageSDKRealTimeTrigger |
For more details, refer to [Real-Time Triggers.](/developer-guide/ios-sdk/push/optional/real-time-triggers)
# Location Triggered
From SDK version `9.0.0`, we have updated methods related to Location Trigger. Refer to the table below to use the updated one.
| SDK Version 8.x.x | SDK Version 9.0.0 |
| :--------------------------------------------------- | :------------------------------------------------------------- |
| MOGeofence | MoEngageSDKGeofence |
| `MOGeofenceHandler.sharedInstance().delegate = self` | `MoEngageSDKGeofence.sharedInstance.setGeofenceDelegate(self)` |
For more info on the Geofence feature, refer to our documentation [here.](/developer-guide/ios-sdk/push/optional/location-triggered)
# Inbox
| SDK Version 8.x.x | SDK Version 9.0.0 |
| :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| MOInbox | MoEngageSDKInbox |
| MOInboxViewController | MoEngageInboxViewController |
| `func getInboxViewController(withUIConfiguration uiConfig: MOInboxUIConfiguration? = nil, withInboxWithControllerDelegate delegate: MOInboxViewControllerDelegate? = nil, forAppID appID: String? = nil, withCompletionBlock completionBlock: @escaping (MOInboxViewController?)->())` | `func getInboxViewController(withUIConfiguration uiConfig: MoEngageInboxUIConfiguration? = nil, withInboxWithControllerDelegate delegate: MoEngageInboxViewControllerDelegate? = nil, forAppID appID: String? = nil, withCompletionBlock completionBlock: @escaping (MoEngageInboxViewController?)->())` |
For more information on the Geofence feature, refer to this [document.](/developer-guide/ios-sdk/push/basic/actionable-notifications)
# iOS 15
Source: https://moengage.com/docs/developer-guide/ios-sdk/os-updates/i-os-15
Review iOS 15 behavior changes that affect push notification appearance and MoEngage SDK features.
The following are the major behavior changes impacting the MoEngage Platform or MoEngage iOS SDK.
# Behavior Changes: Visual Updates to notifications
iOS 15 has brought in some new and exciting visual changes to the push notifications.
* Bigger App Icon
* Media can be placed below the text content compared to the previous version
* Smaller action buttons with support for icons
## What is MoEngage doing about it?
* We have released an SDK update (MORichNotification [5.2.0](/developer-guide/release-notes/ios-sdk/2023-and-older)) to have the current layout of Push template notifications similar to the native notification layout of iOS 15.
* Update the ‘preview’ capabilities during the campaign creation.
# Custom Notification Handling
Source: https://moengage.com/docs/developer-guide/ios-sdk/push/advanced/custom-notification-handling
Customize badge reset, notification sounds, and action handling in iOS push with the MoEngage SDK.
# Disable Badge Reset
By default, the SDK sets the notification badge count to **0** on every app launch and this also clears the notifications in the device notification center. In case if you would like to keep the notifications even after the App Launch then disable badge reset by calling the below method before MoEngage SDK is initialized.
```swift Swift wrap theme={null}
MoEngageSDKMessaging.sharedInstance.disableBadgeReset(true)
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKMessaging sharedInstance] disableBadgeReset:true];
```
# Custom Sound for Notification
You can have a custom tone for notifications of your app. iOS platform supports .aiff , .caf and .wav files for custom Notification tone. For this make sure the sound file of tone is included in your app bundle. Once this is done make sure to provide the sound filename for Notification Sound(In Rich Content Section) while creating the campaign in the dashboard as shown below, and it should work:
# Notification Actions
MoEngage provides several actions that can be included in push notifications to enhance user engagement and interaction. Here are some of the actions provided by MoEngage push notifications:
1. RichLanding: The provided URL will be opened within the app using the Safari View Controller, which ensures that the user remains within the application while accessing the URL. This functionality is handled by the SDK.
2. Navigate To Screen: Implement the callback method mentioned in the **Notification Click Callback in the App** of the [doc](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial#step-1-implement-notification-service-extension-nse) to perform the required action.
3. Deeplink: It is used to navigate users directly to a specific location or content within a mobile app.
If your application is below iOS 13, then a deeplink callback is received in the below ***AppDelegate*** method:
```swift Swift wrap theme={null}
import UIKit
// Custom Scheme Link
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
//Call only if MoEngageAppDelegateProxyEnabled is NO in Info.plist
MoEngageSDKAnalytics.sharedInstance.processURL(url)
}
// Universal Links
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
if userActivity.activityType == NSUserActivityTypeBrowsingWeb ,
let incomingURL = userActivity.webpageURL{
//Call only if MoEngageAppDelegateProxyEnabled is NO in Info.plist
MoEngageSDKAnalytics.sharedInstance.processURL(incomingURL)
}
//rest of the implementation
return true
}
```
```objective-c Objective C wrap theme={null}
// Custom Scheme Link
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options {
return true;
}
// Universal Link
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler {
return true;
}
@end
```
If your application is above iOS 13, then a deeplink callback is received in the below ***SceneDelegate*** method:
```swift Swift wrap theme={null}
import UIKit
// Custom Scheme Link
func scene(_ scene: UIScene, openURLContexts URLContexts: Set) {
let url = URLContexts.first?.url
MoEngageSDKAnalytics.sharedInstance.processURL(url)
}
// Universal Scheme Link
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
if let url = userActivity.webpageURL {
MoEngageSDKAnalytics.sharedInstance.processURL(url)
}
}
}
```
**Note**
* While implementing deep links, make sure that you have added the apps URL Scheme to **LSApplicationQueriesSchemes** array in Info.plist to whitelist your app. Without this, the deep links won't work post iOS9.
# Notification Payload
An example of the push payload sent to the app:
```json iOS Push Payload wrap theme={null}
{
"aps": {
"alert": {
"title": "Notification Title",
"subtitle": "Notification Subtitle",
"body": "Notification Body"
},
"badge": 1,
"sound": "default",
"category": "INVITE_CATEGORY",
"content-available": 1,
"mutable-content": 1
},
"app_extra": {
"moe_deeplink": "moeapp://screen/settings",
"screenName": "Screen Name",
"screenData": {
"key1": "val1",
"key2": "val2"
}
},
"moengage": {
"silentPush": 1,
"cid": "55f2ba15a4ab4104a287bf88",
"app_id": "DAO6UGZ73D9RTK8B5W96TPYN_DEBUG",
"moe_campaign_id": "55f2ba15a4ab4104a287bf88",
"moe_campaign_name": "Campaign Name",
"inbox_expiry": "1571905058",
"webUrl": "https://google.com",
"couponCode": "APP200",
"media-attachment": "https://image.moengage.com/testImg.png",
"media-type": "image"
}
}
```
Description of different keys in the payload:
* **aps**: This key is used by the iOS to display the notification, and the following are the keys present within it:
* **alert** : Message Content.
* **title** : Gives Notification title.
* **subtitle** : Gives Notification subtitle.
* **body** : Gives the message body of the notification
* **badge**: Gives the badge number to be displayed on top of the App Icon. MoEngage platform supports only two possible values i.e, 0/1. If the value is 1 then the SDK will increment the badge number on the app icon and if it's 0 then the badge number will be reset and there will be no badge displayed on the app icon.
* **sound**: This key gives the filename of the audio file to be played on receiving the notification. If no filename is provided while creating the campaign, to play the os default sound this key is set to the value "default".
* **category**: This key is used by OS for deciding the set of action buttons to be displayed for the notification. Also, the same category is used by OS to decide which Notification Content Extension target to display if present.
* **content-available**: If the value of this key is set to 1, then if the app is present in the background it will get a callback(`application:didReceiveRemoteNotification:fetchCompletionHandle`) to refresh the app content in background. Use this key only if you have to process the push notification in background. By default, this key will be unset.
* **mutable-content**: This key is by default set to 1 for all the campaigns, this is to make sure that the Notification Service Extension target gets the callback on receiving the notification to be processed by MORichNotification. If set to 0 the extension target won't get the callback.
* **app\_extra**: This key will contain the keys which are to be used by App Developers, i.e, Custom key value pairs and screenName for navigation.
* **moe\_deeplink**: This key contains the deeplinking URL if provided during the campaign creation. The SDK will process this key and will attempt to open the deeplink URL if it's valid.
* **screenName**: This key gives screen name where the user has to be navigated on clicking the notification. This navigation is not done by the SDK. The possible values for this parameter are something which app developers will have to define in their project. If provided while creating the campaign, it will be present in the notification payload. And implementing the part to parse and get `screenName` parameter's value and to navigate to the mentioned screen has to be implemented by the app developers.
* **screenData**: This contains the custom key-value pairs entered while creating the campaign, which can be made use by the app developers for any of their use-cases.
* **moengage** : This will contain keys which are to be used by SDK, app developers should not be making any change to this part of the payload and also avoid using this part of the payload, as we may update the structure of this part of payload as per our need. (with the exception being cid, media-attachment, media-type, app\_id which we will not change)
* **silentPush**: This key is present and set to `1` for silent pushes sent from MoEngage.
* **cid**: Unique ID for the campaign.
* **app\_id**: The App ID of the account where the campaign was created.
* **moe\_campain\_id** and **moe\_campaign\_name** : Used by analytics module to track attributes for Notification related events.
* **inbox\_expiry**: This key gives the timestamp at which the notification will be deleted from the app inbox.
* **webUrl**: This key contains the Rich-landing URL if provided during the campaign creation. The SDK will process this key and will open the URL(if valid) in an instance of SFSafariViewController. Use Rich-landing action if you wish to open a web page inside the app on click of the push notification. For e.g. `webUrl` - [https://www.google.com](https://www.google.com/).
* **couponCode**: This key contains the coupon code if provided during the campaign creation. On clicking the notification, if this key is present in the push payload the SDK will display an alert with the coupon code and will give an option to user to copy the coupon to the os clipboard.For e.g. `couponCode` - APP200.
* **media-attachment:** The media-attachment key in the payload gives you the URL of the media which you can download.
* **media-type**: Type of media present in the URL given in media-attachment i.e, image/audio/video.
**HTTP URLs**
Http URL's aren't supported unless explicitly specified in the plist. You will have to include ***App Transport Security Setting*** **s** Dictionary in your Info.plist and inside this set ***Allow Arbitrary Loads*** to ***YES***.
# Actionable Notifications
Source: https://moengage.com/docs/developer-guide/ios-sdk/push/basic/actionable-notifications
Add custom action buttons to standard iOS push notifications using the MoEngage SDK.
Actionable notifications let you add custom action buttons to the standard iOS push notifications. It also gives the user a quick and easy way to perform relevant tasks in response to a notification.
# How to implement Actionable Notifications?
## Define a category
To use actionable notifications with MoEngage SDK, you have to define the actions, group them into categories, as shown in the example, and pass them as a parameter while registering for push notifications.
```swift Swift wrap theme={null}
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate{
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
//--- Rest of Implementation
//For registering for remote notification
let categories = self.getCategories()
MoEngageSDKMessaging.sharedInstance.registerForRemoteNotification(withCategories: categories, andUserNotificationCenterDelegate:self)
//--- Rest of Implementation
return true
}
//Example to define categories
//This method gives categories
func getCategories() -> Set{
let acceptAction = UNNotificationAction.init(identifier: "ACCEPT_IDENTIFIER", title: "Accept", options: .authenticationRequired)
let declineAction = UNNotificationAction.init(identifier: "DECLINE_IDENTIFIER", title: "Decline", options: .destructive)
let maybeAction = UNNotificationAction.init(identifier: "MAYBE_IDENTIFIER", title: "May Be", options: .foreground)
let inviteCategory = UNNotificationCategory.init(identifier: "INVITE_CATEGORY", actions: [acceptAction,declineAction,maybeAction], intentIdentifiers: [], options: .customDismissAction)
let categoriesSet = Set.init([inviteCategory])
return categoriesSet;
}
}
```
```objective-c Objective C wrap theme={null}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOption
{
---------
NSSet* categories = [self getNotificationCategories];
[[MoEngageSDKMessaging sharedInstance] registerForRemoteNotificationWithCategories:categories andUserNotificationCenterDelegate:self];
}
---------
return YES;
}
//Example to define categories
//This method gives categories
-(NSSet*)getNotificationCategories{
UNNotificationAction *acceptAction = [UNNotificationAction actionWithIdentifier:@"ACCEPT_IDENTIFIER" title:@"Accept" options:UNNotificationActionOptionAuthenticationRequired];
UNNotificationAction *declineAction = [UNNotificationAction actionWithIdentifier:@"DECLINE_IDENTIFIER" title:@"Decline" options:(UNNotificationActionOptionDestructive)];
UNNotificationAction *maybeAction = [UNNotificationAction actionWithIdentifier:@"MAYBE_IDENTIFIER" title:@"May Be" options:UNNotificationActionOptionNone];
UNNotificationCategory* inviteCategory = [UNNotificationCategory categoryWithIdentifier:@"INVITE_CATEGORY"actions:@[acceptAction,maybeAction, declineAction,opt4Action] intentIdentifiers:@[] options:UNNotificationCategoryOptionNone];
NSSet *categories = [NSSet setWithObjects:inviteCategory,nil];
return categories;
}
```
**Notification Categories**
MoEngage recommended not to change the actions grouped in a category across the app versions, as it will lead to users seeing different actions for the same category across different app versions.
# APNS Authentication Key
Source: https://moengage.com/docs/developer-guide/ios-sdk/push/basic/apns-authentication-key
Generate and upload an APNs Authentication Key to the MoEngage Dashboard for iOS push delivery.
# APNS Auth Keys
APNS Auth keys are the recommended method to enable sending push notifications to your app installed on iOS devices.
To send push notifications to iOS users, it is required to generate the APNs Auth Key file for your application and upload it to the MoEngage dashboard.
# Steps to create APNS Auth Key
To create an APNS auth key, you will need to do the following:
Visit the [Apple Developer Member Center](https://idmsa.apple.com/IDMSWebAuth/signin?appIdKey=891bd3417a7776362562d2197f89480a8547b108fd934911bcbea0110d07f757\&path=%2Faccount%2F\&rv=1) and sign in with your credentials.
Select the Certificates, Identifiers & Profiles on the left pane.
On the certificates page, click on 'Keys' on the left pane as shown below.
In the Keys page that opens, click on the '+' icon to create a new auth key.
In the 'Register a New Key' page that opens, enter the key name and choose the Apple Push Notifications Service (APNS) in the list available below.
Click on the Register Button.
The Download your Keys page opens.
Click on Download to download your Auth key file. Please note that you can download the auth key file only once.
Copy the Key ID (highlighted in the image above) available on the download page. This is required to configure push notifications in the MoEngage dashboard.
Once added, the Auth Key is listed under Keys as shown below.
# Configuring the Auth key in the Dashboard
The following details are necessary to configure the APNS authentication key in the MoEngage Dashboard.
1. Navigate to **Settings > Channels > Push > App Push**.
2. Select iOS (APNS) in the Platforms available on the menu at the top.
## APNS Authentication Key File
The APNS Authentication Key File downloaded using the steps mentioned above needs to be uploaded to the dashboard.
## Team ID
To get the Team ID details, click on the account name in the top right corner, then select **View Account**. The following screen is displayed. Copy the Team ID from here.
## Key ID
As explained in step 8 above, the Key ID is available when you generate the APNS auth key.
## Bundle ID
The App Bundle Identifier is case-sensitive and available in Xcode. Refer to the screenshot below to get the Bundle ID in Xcode.
## Bundle ID for iPad
If you have different apps for iPhone and iPad, upload a different bundle ID for iPad. It is available in the Xcode for the iPad app.
# APNS Certificate/PEM file (legacy)
Source: https://moengage.com/docs/developer-guide/ios-sdk/push/basic/apns-certificate-pem-file-legacy
Create and upload a legacy APNs certificate in PEM format for iOS push notifications with MoEngage.
**Note**
Effective January 15, 2026, MoEngage will deprecate the legacy APNs Provider Certificate (.pem) method. After this date, existing certificates cannot be renewed, and all new uploads must use the [APNs Authentication Key (.p8)](/developer-guide/ios-sdk/push/basic/apns-authentication-key).
MoEngage strongly recommends migrating to the .p8 Auth Key as soon as possible to ensure uninterrupted service. This upgrade offers the following benefits:
* **Permanent validity**: Auth Keys never expire, eliminating the need for annual certificate renewals.
* **Faster delivery**: Stateless token-based authentication provides faster communication than certificate-based methods.
* **Modern feature support:** The new standard supports exclusive iOS capabilities, such as Live Activities.
In order to send push notifications to your app, an APNS certificate is needed for your app, and the same has to be converted to a `.pem` format and uploaded to our dashboard. Follow the steps below to do the same:
# Creating APNS Certificate
## Generating the Certificate Signing Request (CSR)
First Open **Keychain Access** on your Mac and choose the menu option **Request a Certificate from a Certificate Authority** as shown below:
You should now see the window shown below. Enter your email address here and your app name for Common Name. Check `Saved to disk` and click Continue. Save the file as “.certSigningRequest”:
## Create an APNS Certificate in Developer Account
Log-in to your developer account and go to **Certificates, Identifiers and Profiles**. Select **Certificates** Section and click on the *+* icon to create a new certificate. In **Create a New Certificate** screen select `Apple Push Notification service SSL(Sandbox & Production)` and click Continue as shown below:
Next, select the App ID(App Bundle ID) for which you are creating the APNS certificate and click Continue
**APP ID Selection Note**
Ensure **Push Notification** capability is enabled for the App(App ID selected) you are creating an APNS certificate for.
Now choose the `certificate signing request` file created in the first step and click Continue as shown below:
That's it! Your APNS certificate has been successfully created. Go ahead and download the same and open it to include it in your Mac `Keychain Access`
# Converting Certificate to PEM format
Follow the below steps to convert the APNS certificate obtained in the previous step to `.pem` file:
1. First, go to **Keychain Access** and select your APNS certificate, then right-click on it select **Export** option. Now export your certificate in `.p12` format. You will be prompted to provide a password for `.p12`, do the same.
2. Convert the `.p12` file obtained in the previous step into a `.pem` file by using **openssl** commands as shown below, here you will have to provide the `Import Password`:
```ruby Ruby wrap theme={null}
openssl pkcs12 -in p12Cert.p12 -out pemAPNSCert.pem -nodes -legacy
Enter Import Password:
MAC verified OK
```
**Note**
You can also go the SSL Converter [here](https://www.sslshopper.com/ssl-converter.html) and convert your `.p12` file to `.pem`.
# Verify .pem file
Before uploading the certificate to MoEngage Dashboard, verify the `.pem` file obtained:
1. First, open the `.pem` in a text editor to view its content. The certificate content should be in format as shown below. Make sure the pem file contains both Certificate content(from `BEGIN CERTIFICATE` to `END CERTIFICATE`) as well as Certificate Private Key (from `BEGIN PRIVATE KEY` to `END PRIVATE KEY`)
```text Text theme={null}
Bag Attributes
friendlyName: Apple Push Services:
localKeyID: <>
subject=<>
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
Bag Attributes
friendlyName: <>
localKeyID: <>
Key Attributes:
-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----
```
2. Also, you check the validity of the certificate by going to SSLShopper [Certificate Decoder](https://www.sslshopper.com/certificate-decoder.html) and pasting the Certificate Content (from `BEGIN CERTIFICATE` to `END CERTIFICATE`) to get all the info about the certificate as shown below:
As you can see, the Common Name should contain **Apple Push Services** and the App's Bundle ID. Confirm the organization's information and also the **Validity** of the Certificate. Once everything is verified, upload the certificate to our dashboard.
# Uploading PEM file to MoEngage Dashboard
1. Navigate to **Settings > Channels > Push > App Push**.
2. Select iOS (APNS) in the Platforms available on the menu at the top.
3. Click on **APNS provider certificate**.
4. Upload the *.pem* file. Enter the password for the *.pem* file, or leave it blank if there isn't any.
**iPad Support**
In case you have different apps for iPhones and iPads(Different Bundle IDs), set up certificates for both iOS and iPad separately in the dashboard in order to be able to send the messages to all the devices.
# Test/Live Builds
* If you are testing the app on **Test Flight or a live app store build**, make sure you upload the ad-hoc or production pem to our dashboard. And also in this case you have to send push notifications from the **Live environment** of your account.
* For the dev build, you can upload the development or production certificate in the dashboard, but make sure that you create your campaign in the **Test environment**, as you cannot send push notifications to the dev build from the Live environment.
# iOS Push Integration Tutorial
Source: https://moengage.com/docs/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial
Step-by-step instructions for integrating the MoEngage iOS SDK to send, receive, and track rich push notifications.
This article provides step-by-step instructions for integrating the MoEngage iOS SDK, enabling your application to send, receive, and track rich push notifications. By following these instructions, you will implement a comprehensive setup that supports rich media content, including images and GIFs, and ensures reliable analytics.
This article covers the following essential topics:
* **Setting up the Notification Service Extension (NSE)**: Enable rich media content (images, GIFs) and reliable impression tracking across all app states.
* **Configuring the AppDelegate**: Implement push notification registration, device token handling, and user interaction callbacks.
* **Validating the Integration**: Follow a process to test notification delivery, rich media display, and analytics tracking.
* **Implementing Advanced Features**: Enhance notifications with custom push templates, actionable buttons, and badge count control.
**Prerequisites**
To enable push notifications:
1. **Integrate the MoEngage iOS SDK**: Use CocoaPods, Swift Package Manager (SPM), or manual framework import as detailed in the [MoEngage documentation](/developer-guide/ios-sdk/sdk-integration/basic).
2. **Configure APNs credentials in the MoEngage UI**:
* MoEngage requires either an APNs Authentication Key (.p8) or an [APNs Certificate](/developer-guide/ios-sdk/push/basic/apns-certificate-pem-file-legacy) (.pem) to communicate with Apple Push Notification Service (APNs).
* **Recommendation**: Use an APNs Authentication Key because it is non-expiring. Refer to the [APNs Authentication Key Setup Guide](/developer-guide/ios-sdk/push/basic/apns-authentication-key).
3. Ensure you have added **Push Notifications** capability in the main target by navigating to **Target** -> **Signing & Capabilities**.
## Step 1: Implement Notification Service Extension (NSE)
NSE enables rich push notifications (including images, video, and GIFs) and tracks notification impressions across all app states.
1. In Xcode, navigate to **File** > **New** > **Target**… > **Notification Service Extension**.
2. Enter a name for your NSE target.
To install the `MoEngageRichNotification` through SPM, perform the following steps:
1. Navigate to **File** > **Add Package**.
2. Enter the appropriate repository URL:
* [https://github.com/moengage/apple-sdk.git](https://github.com/moengage/apple-sdk.git) (for MoEngage-iOS-SDK versions 9.23.0 and above)
* [https://github.com/moengage/MoEngage-iOS-SDK.git](https://github.com/moengage/MoEngage-iOS-SDK.git) (for other versions)
3. Select the master branch or your desired version.
4. Click **Add Package**.
5. Target the installed package to your NSE file.
**Information** CocoaPods is being deprecated. MoEngage recommends using Swift Package Manager for all new integrations. For more info, refer [here](/developer-guide/ios-sdk/sdk-integration/basic/sdk-integration).
Add the following to your `Podfile`:
```ruby Ruby wrap theme={null}
target 'YourApp' do
use_frameworks!
pod 'MoEngage-iOS-SDK'
end
target 'MoEngageNotificationService' do
use_frameworks!
pod 'MoEngage-iOS-SDK/RichNotification'
end
```
Then run:
```shellscript Shell wrap theme={null}
pod repo update
pod install
```
To set up an App Group for seamless communication between your main app and NSE, perform the following steps:
1. **Enable App Groups**:
* For both your main application target and your NSE target, navigate to **Signing and Capabilities**.
* Click **+ Capability** and select **App Groups**.
2. **Create App Group ID**:
* Create a new App Group ID (for example, `group.com.yourcompany.appname`).
* **Crucially**, ensure this exact App Group ID is enabled for both the main app and the NSE targets.
3. **Update AppDelegate**: Modify your `AppDelegate.swift` in your iOS application to set the App Group ID as shown below:
```swift Swift wrap theme={null}
// In your main AppDelegate.swift - didFinishLaunchingWithOptions
let sdkConfig = MoEngageSDKConfig(appId: "YOUR_APP_ID", dataCenter: .data_center_01)
sdkConfig.appGroupId = "group.com.yourcompany.appname" // Your App Group ID
```
```objective-c Objective C wrap theme={null}
MoEngageSDKConfig *sdkConfig = [[MoEngageSDKConfig alloc] initWithAppId:@"YOUR_APP_ID" dataCenter:MoEngageDataCenterData_center_01];
sdkConfig.appGroupID = @"group.com.yourcompany.appname"; // Add your App Group ID here
[[MoEngage sharedInstance] initializeDefaultTestInstance:sdkConfig];
```
Replace the entire content of the generated `NotificationService.swift` file with the following:
```swift Swift wrap theme={null}
import UserNotifications
import MoEngageRichNotification
class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
//Tell the MoEngage SDK about the App Group ID
MoEngageSDKRichNotification.setAppGroupID("group.com.yourcompany.appname")
// Step 2: Pass the notification to the MoEngage SDK
// The SDK will download rich media and track the impression before calling your completion handler
MoEngageSDKRichNotification.handle(richNotificationRequest: request, withContentHandler: contentHandler)
}
}
```
```objective-c Objective C wrap theme={null}
#import
@import MoEngageRichNotification;
@interface NotificationService ()
@property (nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver);
@property (nonatomic, strong) UNMutableNotificationContent *bestAttemptContent;
@end
@implementation NotificationService
- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
@try {
self.contentHandler = contentHandler;
self.bestAttemptContent = [request.content mutableCopy];
[MoEngageSDKRichNotification setAppGroupID:@"group.com.yourcompany.appname"];
[MoEngageSDKRichNotification handleWithRichNotificationRequest: request withContentHandler:contentHandler];
} @catch (NSException *exception) {
NSLog(@"MoEngage : exception : %@",exception);
}
}
@end
```
## Step 2: Implement Push Handling in AppDelegate
Integrate push notification registration and token management within your `AppDelegate` to ensure proper communication with Apple Push Notification service (APNs) and MoEngage. This setup allows MoEngage to effectively map APNs tokens with your users.
### Choose a Notification Registration Method
To register for remote notifications at launch, call exactly one of the following methods based on your desired user experience:
* **Standard Notifications (Direct Opt-In)**: Presents a system prompt for permission to deliver full notifications with banners and sounds upon user approval. Calling `registerForRemoteNotification()` displays a permission pop-up to the user if they are not already opted in.
* **Provisional Notifications (Quiet Opt-In)**: Delivers notifications silently to the Notification Center without an initial prompt, allowing the user to opt into full delivery later.
For more information, refer to [iOS Push Permission and Reachability](https://help.moengage.com/hc/en-us/articles/22865898059668-iOS-Push-Permission-and-Reachability#h_01HBT39SSW9ZXJ705WSD2DKYPP).
```swift Swift wrap theme={null}
import UIKit
import MoEngageSDK
import UserNotifications
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) - Bool {
// method to use provisional push
MoEngageSDKMessaging.sharedInstance.registerForRemoteProvisionalNotification()
return true
}
}
// To display standard notifications later in the user's journey, call the following method after the app starts.
MoEngageSDKMessaging.sharedInstance.registerForRemoteNotification()
```
```objective-c Objective C wrap theme={null}
#import AppDelegate.h
#import UIKiUIKit.h
#import MoEngageSDK/MoEngageSDKMessaging.h
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// method to use provisional push
[[MoEngageSDKMessaging sharedInstance] registerForRemoteProvisionalNotificationWithCategories:nil andUserNotificationCenterDelegate:nil];
return YES;
}
@end
// To display standard notifications later in the user's journey, call the following method after the app starts.
[[MoEngageSDKMessaging sharedInstance] registerForRemoteNotificationWithCategories:nil andUserNotificationCenterDelegate:nil];
```
To register for standard push notifications, use the following MoEngage SDK code:
```swift Swift wrap theme={null}
import UIKit
import MoEngageSDK
import UserNotifications
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
MoEngageSDKMessaging.sharedInstance.registerForRemoteNotification()
return true
}
}
```
```objective-c Objective C wrap theme={null}
#import AppDelegate.h
#import UIKiUIKit.h
#import MoEngageSDK/MoEngageSDKMessaging.h
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
[[MoEngageSDKMessaging sharedInstance] registerForRemoteNotificationWithCategories:nil andUserNotificationCenterDelegate:nil];
return YES;
}
@end
```
### App Delegate Method Swizzling
App Delegate Method Swizzling, a runtime technique utilized by the MoEngage SDK, streamlines integration by automating push notification callback handling within the AppDelegate. The MoEngage SDK enables Method Swizzling by default to offer the quickest and most straightforward initial integration experience.
To ensure maximum compatibility in applications that use other push-enabled SDKs, MoEngage provides a manual forwarding method. If you encounter conflicts, MoEngage recommends disabling the default Method Swizzling in the SDK settings.
This manual approach requires you to forward the push payload directly to our SDK, giving you explicit control and ensuring that critical features like foreground notifications, click tracking, and deep links function reliably across all services.
To resolve conflicts, disable MoEngage's App Delegate Swizzling and manually forward push notification callbacks to the SDK.
1. **Disable Swizzling**: Add the following entry to your `Info.plist` file:
```xml Info.plist wrap theme={null}
MoEngageAppDelegateProxyEnabled
false
```
2. **Manual forwarding in AppDelegate**: After disabling swizzling, implement the following code within your `AppDelegate.swift` file to manually pass notification events to the MoEngage SDK:
```swift Swift wrap theme={null}
import UIKit
import MoEngageSDK
import UserNotifications
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
// Set up MoEngage SDK and notification delegates when the app launches.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Set the UNUserNotificationCenter delegate to enable handling notification-related events.
UNUserNotificationCenter.current().delegate = self
// Register for push notifications. This prompts the user for permission and gets the device token from Apple.
// Below code you can ignore if you don't want prompt on app launch and want to use provisional push in starting of app and further at some instance in app you can prompt for permission.
MoEngageSDKMessaging.sharedInstance.registerForRemoteNotification(withCategories: nil, andUserNotificationCenterDelegate: self)
// This is for requesting provisional authorization for notifications.
// Use only if MoEngageSDKMessaging.sharedInstance.registerForRemoteNotification() is not used on app launch
MoEngageSDKMessaging.sharedInstance.registerForRemoteProvisionalNotification(withCategories: nil,
andUserNotificationCenterDelegate: self)
return true
}
// Called after a successful push token registration with Apple. Pass the token to MoEngage.
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
// Essential: Pass the device token to MoEngage to enable sending push campaigns.
MoEngageSDKMessaging.sharedInstance.setPushToken(deviceToken)
}
// Handles user interaction with a notification (e.g., a tap).
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
// Forward the notification response to MoEngage for automatic click tracking, deep linking, and rich landing page handling.
MoEngageSDKMessaging.sharedInstance.userNotificationCenter(center, didReceive: response)
completionHandler()
}
// Handles notifications that are received while the app is in the foreground.
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
// Decide how the notification should be presented in the foreground (e.g., with a banner and sound).
if #available(iOS 14.0, *) {
completionHandler([.sound, .badge, .banner, .list])
} else {
completionHandler([.alert, .sound, .badge])
}
}
// This method is called if push token registration fails.
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
// Forward the registration failure to the MoEngage SDK. This helps in tracking and diagnosing push delivery issues.
MoEngageSDKMessaging.sharedInstance.didFailToRegisterForPush()
}
```
```objective-c Objective C wrap theme={null}
#import
#import
#import
@interface AppDelegate : UIResponder
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Other app setup code...
[UNUserNotificationCenter currentNotificationCenter].delegate = self;
[[MoEngageSDKMessaging sharedInstance] registerForRemoteNotificationWithCategories:nil andUserNotificationCenterDelegate:self];
return YES;
}
// Forward the device token
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
[[MoEngageSDKMessaging sharedInstance] setPushToken:deviceToken];
// Forward to other SDKs if necessary
}
// Forward notification clicks/responses
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void (^)(void))completionHandler {
[[MoEngageSDKMessaging sharedInstance] userNotificationCenter:center didReceive:response];
// Forward to other SDKs if necessary
completionHandler();
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
if (@available(iOS 14.0, *)) {
completionHandler(UNNotificationPresentationOptionBanner | UNNotificationPresentationOptionList | UNNotificationPresentationOptionSound | UNNotificationPresentationOptionBadge);
} else {
completionHandler(UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge | UNNotificationPresentationOptionSound);
}
}
@end
```
## Step 3: Validate Notifications
To ensure your MoEngage iOS Push Notification integration is fully functional, perform the following validation steps:
### Verify Dashboard Configuration
Before sending a test notification, first verify the integration status on your MoEngage dashboard. Navigate to the iOS Push section of your profile and confirm the following:
* The integration status icon is green.
* For provisional authorization, the **Opt-In Status** is *Unknown*.
* For standard permission, the **Opt-In Status** is *True*.
For more information, refer to [iOS Push Notifications Integration Validation](https://help.moengage.com/hc/en-us/articles/360052433591-iOS-Push-Notifications-Integration-Validation).
### Test Notification Delivery and Display
Send a Test Notification: From your MoEngage dashboard, create and send a test push notification that includes rich media (e.g., an image, GIF, or video).
* **Observe Device Behavior**:
* **Foreground**: When your application is active (in the foreground), the notification should be displayed as a banner and accompanied by a sound.
* **Background**: If your application is in the background, the notification should still be delivered to the device and appear in the notification center.
* **Killed State**: Even when your application is force-closed or not running, the notification must be delivered and visible in the notification center.
* **Rich Media Rendering**: Verify that the rich media content within the notification (for example, the image) renders correctly across all app states (foreground, background, killed).
### Tracking and Analytics Verification
* **Access Campaign Analytics**: Navigate to the analytics section of the push notification campaign you just sent within the MoEngage UI.
* **Validate Impressions**: Confirm that the "Impressions" metric for your campaign is incrementing. This indicates that the MoEngage SDK is successfully tracking when notifications are delivered and displayed on the device.
You have successfully integrated MoEngage iOS Push Notifications, encompassing:
* **Standard and Provisional Push Registration**: Correct handling of user consent for push notifications.
* **Reliable Delivery**: Notifications are delivered and tracked in all application states: foreground, background, and killed.
* **Rich Media Support**: Enhanced notification experiences via the NSE, allowing for visually engaging content.
* **Comprehensive Tracking**: Accurate click and impression tracking across all app states, facilitated by the NSE, providing valuable campaign performance data.
## Optional
After basic push notifications are implemented, enhance them with the following features.
### Push Templates
Create interactive, visually rich notifications by implementing two app extensions:
* **Notification Service Extension**: Intercepts and modifies the notification payload before it is displayed. Use this to download and attach rich media, such as images or GIFs.
* [**Notification Content Extension**](/developer-guide/ios-sdk/push/optional/push-templates): Renders a custom UI for the notification. Use this to create interactive experiences, such as image carousels or custom layouts.
### Actionable Buttons
Embed buttons within a notification to allow users to perform tasks directly from the notification interface, such as "Reply" or "Archive." For more information, refer [here](/developer-guide/ios-sdk/push/basic/actionable-notifications).
### Configure Push Notification Badge Behavior
With `disableBadgeReset(true)` enabled, the SDK won't reset the badge to 0 on app launch. Instead, clicking a notification decrements the badge by 1, maintaining accurate counts when multiple notifications are present. Add the code snippet below post SDK initialization in `AppDelegate.swift` file:
```swift Swift wrap theme={null}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
MoEngageSDKMessaging.sharedInstance.disableBadgeReset(true)
return true
}
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKMessaging sharedInstance] disableBadgeReset:YES];
```
## Best Practices
Adhering to these best practices will ensure a robust and reliable push notification experience for your users and accurate data for your campaigns.
* **Test across all app states (Foreground, Background, Killed)**: This ensures consistent notification delivery, correct rich media rendering, and accurate tracking regardless of how the user is interacting with their device.
* **If using provisional push, verify settings**: Confirm the device's notification settings show *Deliver Quietly* initially. Request the standard push permission and allow it. Then, go to **Settings** to confirm that the permission status is *Authorized*.
* **Validate rich media URLs**: Always check image/video URLs to prevent broken media displays and ensure the NSE can successfully attach content to your notifications.
## FAQs
These symptoms typically indicate a "swizzling conflict" in your AppDelegate. This can happen if another third-party SDK is also managing push notification callbacks. To resolve this, you can disable MoEngage's automatic swizzling and implement manual forwarding instead. Refer to the detailed instructions for the correct implementation.
This issue is commonly caused by an incorrect configuration of the NSE. Verify these three key areas:
* **NSE Target Configuration:** Ensure the `MoEngageNotificationService` target is correctly added to your project and is properly configured.
* **App Group ID:** Confirm that the same App Group ID is enabled for both your main app and the NSE target, and that it has been correctly set in your code.
* **Media URL Reachability:** Check that the URLs for your images, GIFs, or videos are public and accessible. A broken URL will prevent the media from being downloaded and displayed.
* Ensure the deployment target of the extension matches the main app.
Verify the Bundle ID in Xcode matches the MoEngage UI. Ensure the APNs environment (Development or Production) matches the uploaded certificate type. Confirm your APNs certificate or auth key is valid. Test on a physical device; push notifications do not work on simulators.
Enable the Push Notifications capability in Xcode. Check for a stable internet connection and ensure no MDM or VPN profiles are blocking APNs ports. Verify another SDK is not intercepting APNs delegate callbacks.
Avoid requesting both standard and provisional authorization at launch. In the device's Settings for your app, confirm "Deliver Quietly" is not enabled. By design, provisional notifications are delivered silently to the Notification Center without an alert or sound.
# Push Notifications
Source: https://moengage.com/docs/developer-guide/ios-sdk/push/basic/push-notifications
Set up push notifications in your iOS app with MoEngage including APNS, templates, and geofencing.
Push Notifications are a great way to keep your users engaged and informed about your app. You can reach your app users quickly and effectively. This guide will help you through the setup process for using MoEngage SDK to send push notifications.
Follow these steps for setting up your app for Push Notifications :
* [Create an APNS Certificate for your app in .pem format and upload it to iOS Push Settings](/developer-guide/ios-sdk/push/basic/apns-certificate-pem-file-legacy)
* [Add support for custom push templates](/developer-guide/ios-sdk/push/optional/push-templates)
* [Make changes for supporting Actionable Notifications](/developer-guide/ios-sdk/push/basic/actionable-notifications)
* [Add Notification center to show all or filtered list of notifications to your users](/developer-guide/ios-sdk/push/optional/i-os-notification-center)
* [Support Geofence based push notifications in your app](/developer-guide/ios-sdk/push/optional/location-triggered)
# Transactional Live Activity
Source: https://moengage.com/docs/developer-guide/ios-sdk/push/optional/Transactional-Live-Activity
Display real-time transactional updates on the iPhone Lock Screen using MoEngage Live Activities.
# Overview
[iOS Live Activities](https://developer.apple.com/design/human-interface-guidelines/live-activities) display your app's most current data as real-time, interactive updates on the iPhone Lock Screen and in the [Dynamic Island](https://support.apple.com/en-in/guide/iphone/iph28f50d10d/ios). Transactional Live Activities are specifically designed for unique, user-specific events such as order tracking, ride-hailing updates, or personalized transaction states.
**Information**
Live Activities and push notifications have different user permission models. By default, Live Activities are enabled for an app. Users can manage permissions for each app individually in their device settings.
**Prerequisites**
Before you begin, ensure your project and accounts are configured correctly.
1. **Apple Developer Account Configuration**:
* In your Apple Developer account, navigate to **Certificates**, **IDs & Profiles** > **Identifiers** and select your app's identifier.
* Under the **Capabilities** tab, ensure that **Push Notifications** checkbox is selected. This is mandatory for the Apple Push Notification service (APNs) to deliver activity updates.
* **APNs Authentication Key**: To authorize MoEngage to send push notifications on your behalf, you must configure an APNs Authentication Key. For detailed steps on how to upload the .p8 file to the MoEngage dashboard, please refer to the [documentation](/developer-guide/ios-sdk/push/basic/apns-authentication-key) on APNs Authentication Key.
2. **SDK version:** MoEngage iOS SDK 10.09.0 or higher is required to support Transactional Live Activities.
3. **MoEngage Live Activity Module**: The MoEngageLiveActivity module is required to handle transactional updates.
4. **Xcode and iOS Version**:
* **Xcode**: Use Xcode 14.1 or later.
* **iOS Target**: Your Live Activity must target iOS 18 and later.
# Implementing a Transactional Live Activity
This section covers the client-side setup required within your Xcode project for Transactional Live Activities.
## Step 1: Add a Widget Extension
1. In Xcode, navigate to **File** > **New** > **Target**.
2. Select **Widget Extension** and click **Next**.
3. Enter a product name for your widget.
4. Select the **Include Live Activities** checkbox.
5. Click **Finish**.
## Step 2: Configure App's Info.plist
Add Live Activities support to your main app's Info.plist.
```xml XML wrap theme={null}
NSSupportsLiveActivities
```
## Step 3: MoEngageLiveActivity integration
**Information**
To integrate the MoEngageLiveActivity framework, ensure you are using MoEngage iOS SDK version 10.09.0 or higher.
#### **Install using Swift Package Manager (Recommended )**
The MoEngageLiveActivity framework is supported via SPM from SDK version 10.09.0. To integrate, use the GitHub URL [https://github.com/moengage/apple-sdk.git](https://github.com/moengage/apple-sdk.git) and set the branch as master or the required version.
#### **Install using CocoaPod**
**Information**
CocoaPods is being deprecated. MoEngage recommends using Swift Package Manager for all new integrations. For more info on CocoaPods, refer to [CocoaPods Integration Guide](/developer-guide/ios-sdk/sdk-integration/basic/integration-through-cocoa-pods).
To integrate the MoEngageLiveActivity framework, add the following dependency to your Podfile:
```ruby Ruby wrap theme={null}
target 'MoETest' do
use_frameworks!
# Pods for app target
pod 'MoEngage-iOS-SDK' # specify version constraint
pod 'MoEngage-iOS-SDK/LiveActivity'
target 'LiveActivity' do
use_frameworks!
inherit! :search_paths
# Pods for live activity extension target
pod 'MoEngage-iOS-SDK/LiveActivity'
end
end
```
## Step 4: Define the Live Activity Attributes
In the Swift file generated for your widget extension, define the data structure for your Transactional Live Activity (e.g., a Food Delivery order).
1. Configure ActivityAttributes: Create a struct that conforms to [ActivityAttributes](https://developer.apple.com/documentation/activitykit/activityattributes). This struct will contain:
* **Static Data**: Attributes that are set once and do not change (e.g., Order Number).
* **ContentState**: A nested struct for dynamic data that will be updated in real-time (e.g., Delivery Status).
```swift Swift wrap theme={null}
import Foundation
import ActivityKit
import WidgetKit
import SwiftUI
struct FoodOrderAttributes: ActivityAttributes {
public struct ContentState: Codable, Hashable {
// Dynamic stateful properties about your order go here!
var status: String // e.g., "Out for Delivery"
var estimatedMinutes: Int
}
// Fixed non-changing properties about your order go here!
var orderNumber: String
var restaurantName: String
}
```
2. When creating ActivityConfiguration, use *MoEngageTransactionActivityAttributes\* instead of FoodOrderAttributes as your ActivityAttributes type for transactional support.
3. Track widget clicks by configuring the deeplink and widget ID with the moengageWidgetClickURL API.
```swift Swift wrap theme={null}
import ActivityKit
import WidgetKit
import SwiftUI
import MoEngageLiveActivity
struct FoodOrderWidget: Widget {
var body: some WidgetConfiguration {
ActivityConfiguration(for: MoEngageTransactionActivityAttributes.self) { context in
// Lock screen/banner UI goes here
VStack(spacing: 12) {
Text(context.attributes.appAttributes.restaurantName)
Text(context.state.appContent.status)
}
.moengageWidgetClickURL(URL(string: "moeapp://order-tracking"), context: context, widgetId: 2)
} dynamicIsland: { context in
DynamicIsland {
// Expanded UI goes here
} compactLeading: {
Text("Preparing")
} compactTrailing: {
Text("\(context.state.appContent.estimatedMinutes)m")
} minimal: {
Text("Preparing")
}
.moengageWidgetClickURL(URL(string: "moeapp://order-tracking"), context: context, widgetId: 1)
}
}
}
```
4. **Ensure Target Membership**: Make your ActivityAttributes struct accessible to your main app target.
1. Select the Swift file where you defined your ActivityAttributes.
2. Open the **File Inspector** (Option + Command + 1).
3. In the **Target Membership** section, check the box for your main app target.
## Step 5: Monitor Live Activities
Call the `monitorLiveActivities` method to register the `ActivityAttributes` types that the SDK should monitor for real-time updates. **`This method must be invoked within your app's didFinishLaunchingWithOptions method.`** This registration is mandatory for the SDK to successfully track and manage the short tokens required for transactional activity updates.
```swift Swift wrap theme={null}
Task {
if #available(iOS 18, *) {
await MoEngageSDKLiveActivity.monitorLiveActivities(types: [ FoodOrderAttributes.self]) { data in
print("Push token generated for live activity",data)
}
}
}
public struct MoEngageTransactionCampaignData {
public struct MoEngageTokenData {
public let transactionId: String
public let shortToken: String
}
public let accountMeta: MoEngageAccountMeta
public let tokenData: MoEngageTokenData
}
public class MoEngageAccountMeta {
/// Account identifier, APP ID on the MoEngage Dashboard.
public let appID: String
}
```
# Managing the Live Activity Lifecycle
Once your app is configured, you can start, update, and end Transactional Live Activities using a combination of local app code and MoEngage APIs.
## Step 6: Start a Transactional Live Activity
A Transactional Live Activity is typically started locally from the app when an end user initiates a transaction (e.g., placing a food order) or you can initiate it remotely via the Inform API (Server-side).
### Push-to-Start (Remote)
Start a live activity for a user using the Inform API. For more information, refer [here](https://www.moengage.com/docs/api/live-activities/start-broadcast-live-activity).
### Click-to-Start (Local)
Start an activity from within the app, triggered by a user action.
Get Live Activity data from the [createAttributes(withCampaign:completion:)](https://moengage.github.io/ios-api-reference/Enums/MoEngageSDKLiveActivity.html#/s:20MoEngageLiveActivity0ab7SDKLiveD0O16createAttributes12withCampaign4file0J2Id6method4line6column10completionyAC0I0Vy_xG_s12StaticStringVA2PS2uyAM6ResultVy_x_GSgScMYcct0D3Kit0dG0RzlFZ) or [createAttributes(withCampaign:) async](https://moengage.github.io/ios-api-reference/Enums/MoEngageSDKLiveActivity.html#/s:20MoEngageLiveActivity0ab7SDKLiveD0O16createAttributes12withCampaign4file0J2Id6method4line6columnAC0I0V6ResultVy_x_GSgALy_xG_s12StaticStringVA2SS2utYa0D3Kit0dG0RzlFZ) SDK APIs by combining your application's ActivityAttributes data with mandatory MoEngage metadata (retrieved from your server). Use Apple's Activity.request() method with pushType as `.token` to start Live Activity. This links the locally started activity to your campaign.
```swift Swift wrap theme={null}
MoEngageSDKLiveActivity.createAttributes(
withCampaign: .init(
campaignId: campaignId,
campaignName: "Order Tracking \(orderId)",
transactionId: transactionId,
attributeType: "\(FoodOrderAttributes.self)",
instanceId: instanceId,
appAttributes: FoodOrderAttributes(orderNumber: "ORD-123", restaurantName: "Pizza Palace"),
appContent: FoodOrderAttributes.ContentState(status: "Preparing", estimatedMinutes: 30)
)
) { [weak self] result in
guard let result = result else {
self?.view.makeToast("No Live Activity creation result")
return
}
do {
let activity = try MoEngageTransactionActivity.request(
attributes: result.attributes,
content: .init(
state: result.content,
staleDate: .distantFuture,
relevanceScore: 10
),
pushType: .token,
style: .standard
)
MoEngageSDKLiveActivity.trackStarted(activity: activity)
self?.view.makeToast("Order Tracking Live Activity started successfully")
} catch {
self?.view.makeToast("Activity request error: \"\(error.localizedDescription)\"")
}
}
```
**Information**
By using `pushType: .token,`the Live Activity is configured to receive transactional updates specifically targeted to this activity instance via its unique push token.
## Step 7: Update a Live Activity
Update the transactional activity status using a push notification targeted at the activity's push token. Updates must be performed exclusively via the Inform API. For more information, refer to the [Inform API](https://www.moengage.com/docs/api/transactional-alerts/send-transactional-alert).
## Step 8: End a Live Activity
Ending an activity must be performed exclusively through the Inform API; otherwise, it will terminate automatically upon reaching the configured `dismissal_date`.
For more information, refer to the [Inform API](https://www.moengage.com/docs/api/transactional-alerts/send-transactional-alert).
# Broadcast Live Activity
Source: https://moengage.com/docs/developer-guide/ios-sdk/push/optional/broadcast-live-activity
Display real-time broadcast updates on the iPhone Lock Screen using MoEngage Broadcast Live Activities.
# Overview
[iOS Live Activities](https://developer.apple.com/design/human-interface-guidelines/live-activities) display your app's most current data as real-time, interactive updates on the iPhone Lock Screen and in the [Dynamic Island](https://support.apple.com/en-in/guide/iphone/iph28f50d10d/ios). This allows users to track events like sports scores, order status, or flight updates without opening your app, significantly boosting engagement and user experience.
**Information**
Live Activities and push notifications have different user permission models. By default, Live Activities are enabled for an app. Users can manage permissions for each app individually in their device settings.
**Prerequisites**
Before you begin, ensure your project and accounts are configured correctly.
1. **Apple Developer Account Configuration**:
* In your Apple Developer account, navigate to **Certificates**, **IDs & Profiles** > **Identifiers** and select your app's identifier.
* Under the **Capabilities** tab, ensure that **Push Notifications** and **Broadcast Capability** checkboxes are selected. This is mandatory for the Apple Push Notification service (APNs) to deliver activity updates.
* **APNs Authentication Key**: To authorize MoEngage to send push notifications on your behalf, you must configure an APNs Authentication Key. For detailed steps on how to upload the .p8 file to the MoEngage dashboard, please refer to the [documentation](/developer-guide/ios-sdk/push/basic/apns-authentication-key) on APNs Authentication Key
2. **Xcode and iOS Version**:
* **Xcode**: Use Xcode 14.1 or later.
* **iOS Target**: Your Live Activity must target iOS 18 and later.
# Implementing a Live Activity
This section covers the client-side setup required within your Xcode project.
## Step 1: Add a Widget Extension
1. In Xcode, navigate to **File** > **New** > **Target**.
2. Select **Widget Extension** and click **Next**.
3. Enter a product name for your widget.
4. Select the **Include Live Activities** checkbox.
5. Click **Finish**.
## Step 2: Configure App's Info.plist
Add Live Activities support to your main app's Info.plist.
```xml XML wrap theme={null}
NSSupportsLiveActivities
```
## Step 3: MoEngageLiveActivity integration
**Information**
To integrate the MoEngageLiveActivity framework, ensure you are using the appropriate MoEngage-iOS-SDK version.
#### **Install using Swift Package Manager (Recommended )**
MoEngageLiveActivity framework is supported through SPM from SDK version 10.02.1 To integrate, use the GitHub url [https://github.com/moengage/apple-sdk.git](https://github.com/moengage/apple-sdk.git) and set the branch as master or required version.
#### **Install using CocoaPod**
**Information**
CocoaPods is being deprecated. MoEngage recommends using Swift Package Manager for all new integrations. For more info on CocoaPods, refer to [CocoaPods Integration Guide](/developer-guide/ios-sdk/sdk-integration/basic/integration-through-cocoa-pods).
To integrate the MoEngageLiveActivity framework, add the following dependency to your Podfile:
```ruby Ruby wrap theme={null}
target 'MoETest' do
use_frameworks!
# Pods for app target
pod 'MoEngage-iOS-SDK' # specify version constraint
pod 'MoEngage-iOS-SDK/LiveActivity'
target 'LiveActivity' do
use_frameworks!
inherit! :search_paths
# Pods for live activity extension target
pod 'MoEngage-iOS-SDK/LiveActivity'
end
end
```
## Step 4: Define the Live Activity Attributes
In the Swift file generated for your widget extension, define the data structure for your Live Activity.
1. Configure ActivityAttributes: Create a struct that conforms to [ActivityAttributes](https://developer.apple.com/documentation/activitykit/activityattributes). This struct will contain:
* **Static Data**: Attributes that are set once and do not change.
* **ContentState**: A nested struct for dynamic data that will be updated in real-time.
```swift Swift wrap theme={null}
import Foundation
import ActivityKit
import WidgetKit
import SwiftUI
struct FootballActivityAttributes: ActivityAttributes {
public struct ContentState: Codable, Hashable {
// Dynamic stateful properties about your activity go here!
var teamOneScore: Int
var teamTwoScore: Int
}
// Fixed non-changing properties about your activity go here!
var team1Name: String
var team2Name: String
}
```
2. When creating ActivityConfiguration, use *MoEngageActivityAttributes\* instead of FootballActivityAttributes as your ActivityAttributes type.
3. Track widget clicks by configuring the deeplink and widget ID with the moengageWidgetClickURL API.
```swift Swift wrap theme={null}
import ActivityKit
import WidgetKit
import SwiftUI
import MoEngageLiveActivity
struct FootballActivityWidget: Widget {
var body: some WidgetConfiguration {
ActivityConfiguration(for: MoEngageActivityAttributes.self) { context in
// Lock screen/banner UI goes here
VStack(spacing: 12) {
// UI elements
}
.moengageWidgetClickURL(URL(string: "moeapp://game"), context: context, widgetId: 2)
} dynamicIsland: { context in
DynamicIsland {
// Expanded UI goes here
} compactLeading: {
// Compact Leading UI goes here
} compactTrailing: {
// Compact Trailing UI goes here
} minimal: {
// Minimal UI goes here
}
.moengageWidgetClickURL(URL(string: "moeapp://game"), context: context, widgetId: 1)
}
}
}
```
**Information**
MoEngage recommends that you acquaint yourself with Apple's Live Activities [prerequisites and limitations](https://developer.apple.com/documentation/activitykit/displaying-live-data-with-live-activities#Understand-constraints), as these are distinct from those of MoEngage.
4. **Ensure Target Membership**: Make your ActivityAttributes struct accessible to your main app target.
1. Select the Swift file where you defined your ActivityAttributes.
2. Open the **File Inspector** (Option + Command + 1).
3. In the **Target Membership** section, check the box for your main app target.
# Managing the Live Activity Lifecycle
Once your app is configured, you can start, update, and end Live Activities using a combination of local app code and MoEngage APIs.
## Step 5: Create a Live Activity Campaign (One-Time Setup)
Before you can start a Live Activity, you must first [create a campaign](https://developers.moengage.com/hc/en-us/articles/38466364097044-Create-Push-Campaigns) on the MoEngage platform. This one-time API call defines the campaign's properties, such as the target audience and conversion goals.
Upon successful creation, the API returns a channel\_id. This ID is essential for two reasons:
* It identifies the campaign you want to start remotely for a target segment.
* It allows users outside the original target segment to start the same Live Activity locally from within your app (e.g., by tapping a button).
For more information, refer [here](https://developers.moengage.com/hc/en-us/articles/38466364097044-Create-Push-Campaigns).
**Success/Developer Info**
Your server should store the returned channel\_id, MoEngage metadata, and make it available to your mobile app. Your app will need this data to initiate the Live Activity locally.
## Step 6: Start a Live Activity
A Live Activity instance can be started remotely via a push or locally from the app.
### Push-to-Start (Remote)
Start an activity for your defined audience using a push notification. For more information, refer [here](https://www.moengage.com/docs/api/live-activities/start-broadcast-live-activity).
### Click-to-Start (Local)
Start an activity from within the app, triggered by a user action.
Get Live Activity data from the [createAttributes(withCampaign:completion:)](https://moengage.github.io/ios-api-reference/Enums/MoEngageSDKLiveActivity.html#/s:20MoEngageLiveActivity0ab7SDKLiveD0O16createAttributes12withCampaign4file0J2Id6method4line6column10completionyAC0I0Vy_xG_s12StaticStringVA2PS2uyAM6ResultVy_x_GSgScMYcct0D3Kit0dG0RzlFZ) or [createAttributes(withCampaign:) async](https://moengage.github.io/ios-api-reference/Enums/MoEngageSDKLiveActivity.html#/s:20MoEngageLiveActivity0ab7SDKLiveD0O16createAttributes12withCampaign4file0J2Id6method4line6columnAC0I0V6ResultVy_x_GSgALy_xG_s12StaticStringVA2SS2utYa0D3Kit0dG0RzlFZ) SDK APIs by combining your application's ActivityAttributes data with mandatory MoEngage metadata (retrieved from your server). Use Apple's Activity.request() method with channel\_id (retrieved from your server) to start Live Activity. This links the locally started activity to your campaign.
**Information**
Once Live Activity is started, the Live Activity Started event needs to be tracked using the [trackStarted(activity:)](https://moengage.github.io/ios-api-reference/Enums/MoEngageSDKLiveActivity.html#/s:20MoEngageLiveActivity0ab7SDKLiveD0O12trackStarted8activity4file0I2Id6method4line6columny0D3Kit0D0CyAA0abD10AttributesVyxGG_s12StaticStringVA2SS2utAK0dO0RzlFZ) API.
```swift Swift wrap theme={null}
import MoEngageLiveActivity
guard #available(iOS 18, *) else { return }
guard let result = await MoEngageSDKLiveActivity.createAttributes(
withCampaign: MoEngageSDKLiveActivity.Campaign(
campaignId: "Your Campaign Id", campaignName: "Your Campaign Name",
deliveryType: "Broadcast Live Activity",
attributeType: "\(FootballActivityAttributes.self)",
instanceId: "Your Instance Id",
appAttributes: FootballActivityAttributes(team1Name: "Chiefs", team2Name: "Bills"),
appContent: FootballActivityAttributes.ContentState(teamOneScore: 0, teamTwoScore: 0)
)
) else { return }
do {
let activity = try MoEngageActivity.request(
attributes: result.attributes,
content: .init(
state: result.content, staleDate: .distantFuture,
relevanceScore: 10
),
pushType: .channel("Your channel Id"), style: .standard
)
// Track started event
MoEngageSDKLiveActivity.trackStarted(activity: activity)
} catch {
// log error
}
```
## Step 7: Update a Live Activity
Update an activity for your defined audience using a push notification. For more information, refer [here](https://www.moengage.com/docs/api/live-activities/update-broadcast-live-activity).
## Step 8: End a Live Activity
A Live Activity can end through user dismissal, a system timeout, or a command from your server. For more information, refer [here](https://www.moengage.com/docs/api/live-activities/end-broadcast-live-activity).
# iOS Notification Center
Source: https://moengage.com/docs/developer-guide/ios-sdk/push/optional/i-os-notification-center
Add an inbox view controller to your iOS app to display read and unread push notifications.
Inbox is a drop-in view controller which contains the read and unread push notifications. Even if the user has not clicked on a notification, it will be present in the Inbox and will be highlighted to signify it is unread status. The title and the look and feel of the view are also customisable.
Inbox view controller is added as a child view controller to your own controller. This helps you get the delegate callback in the same controller, which you can further use for navigation to different screens.
# SDK Installation
## Install using Swift Package Manager
MoEngageInbox is supported through SPM from SDK version 1.2.0. To integrate, use the GitHub url [https://github.com/moengage/apple-sdk.git](https://github.com/moengage/apple-sdk.git) for SDK versions equal and above 9.23.0, or [https://github.com/moengage/MoEngage-iOS-SDK.git](https://github.com/moengage/MoEngage-iOS-SDK.git) for other SDK versions link and set the branch as master or required version.
## Install using CocoaPod
**Information**
CocoaPods is being deprecated. MoEngage recommends using Swift Package Manager for all new integrations. For more info on CocoaPods, refer to [CocoaPods Integration Guide](/developer-guide/ios-sdk/sdk-integration/basic/integration-through-cocoa-pods).
From MoEngage-iOS-SDK version 8.2.0 ,Inbox module is separated from the SDK to a separate module as MoEngageInbox and hence has to be added separately.
Integrate MoEngageInbox framework by adding the dependency in the podfile as show below.
```ruby Ruby wrap theme={null}
pod 'MoEngage-iOS-SDK/Inbox',
```
Now run `pod install` to install the framework
# Inbox Setup Checklist
Make sure the following items are implemented before using the Inbox Module:
1. Update the MoEngage-iOS-SDK to version >= 9.0.0
2. Integrate the MoEngageInbox module of version >= 2.0.0
3. [Implement Notification Service Extension](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial#tracking-and-analytics-verification) and Integrate [MoEngageRichNotifcation](https://cocoapods.org/pods/MORichNotification)(>= 7.0.0).
4. AppGroupID is set in **App Target** [Capabilities](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial#step-1-implement-notification-service-extension-nse) and the [same is passed to the SDK](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial#step-1-implement-notification-service-extension-nse).
5. AppGroupID is set in **Notification Service Extension Target** [Capabilities](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial#step-1-implement-notification-service-extension-nse) and the [same is passed to the MoEngageRichNotification SDK](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial#step-1-implement-notification-service-extension-nse).
**App Group ID**
Make sure the App Group ID configured for both the **App Target** and the **Notification Service Extension Target** are the **same**.
# How to use Inbox?
1. Import `MoEngageInbox` in your View Controller.
2. Create a property - @property(nonatomic, strong) MoEngageInboxViewController \*inboxController.
3. In viewDidLoad, add the below code to fetch MoEngageInboxViewController
```swift Swift wrap theme={null}
MoEngageSDKInbox.sharedInstance.getInboxViewController(withUIConfiguration: nil, withInboxWithControllerDelegate: nil, forAppID: "YOUR Workspace ID") { inboxController in
self.inboxController = inboxController
}
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKInbox sharedInstance] getInboxViewControllerWithUIConfiguration:nil withInboxWithControllerDelegate:nil forAppID:@"YOUR Workspace ID" withCompletionBlock:^(MoEngageInboxViewController * _Nullable) {
self.inboxController = inboxController;
}];
```
# Push/Present the MoEngageInboxViewController
In order for the SDK to handle the transition, use one of the methods.
```swift Swift wrap theme={null}
MoEngageSDKInbox.sharedInstance.pushInboxViewController(toNavigationController: self.navigationController!, withUIConfiguration: nil)
// Present
MoEngageSDKInbox.sharedInstance.presentInboxViewController(withUIConfiguration: nil)
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKInbox sharedInstance] pushInboxViewControllerToNavigationController:navigationController withUIConfiguration:nil withInboxWithControllerDelegate:nil forAppID:@"YOUR Workspace ID"];
// Present
[[MoEngageSDKInbox sharedInstance] presentInboxViewControllerWithUIConfiguration:nil withInboxWithControllerDelegate:nil forAppID:@"YOUR Workspace ID"];
```
# MoEngageInboxViewControllerDelegate Methods
Use [*MoEngageInboxViewControllerDelegate*](https://moengage.github.io/ios-api-reference/Protocols/MoEngageInboxViewControllerDelegate.html) protocol for getting the callbacks from the Inbox Module:
```swift Swift wrap theme={null}
extension NotificationsViewController: MoEngageInboxViewControllerDelegate {
//Called when inbox cell is selected
func inboxEntryClicked(_ inboxItem: MoEngageInboxEntry) {
print("Inbox Clicked")
}
//Called when inbox item is deleted
func inboxEntryDeleted(_ inboxItem: MoEngageInboxEntry) {
print("Inbox item deleted")
}
// Called when MoEngageInboxViewController is dismissed after being presented
func inboxViewControllerDismissed() {
print("Dismissed")
}
}
```
```objective-c Objective-C wrap theme={null}
//Called when inbox cell is selected
- (void)inboxEntryClicked:(MoEngageInboxEntry *)inboxItem {
NSLog(@"Inbox item Clicked");
}
//Called when inbox item is deleted
- (void)inboxEntryDeleted:(MoEngageInboxEntry *)inboxItem {
NSLog(@"Inbox item Deleted");
}
// Called when MoEngageInboxViewController is dismissed after being presented
- (void)inboxViewControllerDismissed {
NSLog(@"Inbox Dismissed");
}
```
Set [*MoEngageInboxViewControllerDelegate*](https://moengage.github.io/ios-api-reference/Protocols/MoEngageInboxViewControllerDelegate.html) by passing the delegate as parameter in the below functions.
```swift Swift wrap theme={null}
//Push
MoEngageSDKInbox.sharedInstance.pushInboxViewController(toNavigationController: self.navigationController!, withUIConfiguration: nil, withInboxWithControllerDelegate: self)
//Present
MoEngageSDKInbox.sharedInstance.presentInboxViewController(withUIConfiguration: nil, withInboxWithControllerDelegate: self)
//Fetch MoEngageInboxViewController
MoEngageSDKInbox.sharedInstance.getInboxViewController(withUIConfiguration: nil, withInboxWithControllerDelegate: self, forAppID: "YOUR Workspace ID") { inboxController in
self.inboxController = inboxController
}
```
```objective-c Objective C wrap theme={null}
//Push
[[MoEngageSDKInbox sharedInstance] pushInboxViewControllerToNavigationController:navigationController withUIConfiguration:nil withInboxWithControllerDelegate:self forAppID:@"YOUR Workspace ID"];
//Present
[[MoEngageSDKInbox sharedInstance] presentInboxViewControllerWithUIConfiguration:nil withInboxWithControllerDelegate:self forAppID:@"YOUR Workspace ID"];
//Fetch MoEngageInboxViewController
[[MoEngageSDKInbox sharedInstance] getInboxViewControllerWithUIConfiguration:nil withInboxWithControllerDelegate:self forAppID:@"YOUR Workspace ID" withCompletionBlock:^(MoEngageInboxViewController * _Nullable inboxController) {
self.inboxController = inboxController;
}];
}
```
# Customizing Appearance
1. You can push/present your controller. If you push your controller, make sure to add “Done” or “Cancel” button as a UIBarButtonItem to dismiss your View Controller.
2. You can get the delegate callback of the click action on inbox cells.
3. You can use this data for tracking events or navigation to another screen.
4. You can customize the look and feel of the inbox view controller using the method:
```swift Swift wrap theme={null}
let configuration = MoEngageInboxUIConfiguration()
configuration.cellDefaultBackgroundColor = .red
configuration.cellHeaderLabelFont = UIFont.systemFont(ofSize: 15)
configuration.cellMessageLabelFont = UIFont.systemFont(ofSize: 13)
configuration.cellSelectionTintColor = .red
configuration.cellHeaderLabelTextColor = .white
configuration.cellMessageLabelTextColor = .white
configuration.cellUnreadBackgroundColor = .blue
let navigationBarStyle = MoEngageInboxNavigationBarStyle()
navigationBarStyle.navigationBarColor = .black
navigationBarStyle.navigationBarTintColor = .blue
navigationBarStyle.navigationBarTitleColor = .blue
navigationBarStyle.navigationBarTransluscent = false
configuration.navigationBarStyle = navigationBarStyle
//Present
MoEngageSDKInbox.sharedInstance.presentInboxViewController(withUIConfiguration: configuration, forAppID: "YOUR Workspace ID")
//Push
MoEngageSDKInbox.sharedInstance.pushInboxViewController(toNavigationController: self.navigationController!, withUIConfiguration: configuration, forAppID: "Workspace ID")
//Fetch MoEngageInboxViewController
MoEngageSDKInbox.sharedInstance.getInboxViewController(withUIConfiguration: configuration, forAppID: "YOUR Workspace ID") { controller in
}
```
```objective-c Objective C wrap theme={null}
MoEngageInboxUIConfiguration* configuration = [[MoEngageInboxUIConfiguration alloc] init];
configuration.cellDefaultBackgroundColor = [UIColor redColor];
configuration.cellHeaderLabelFont =[UIFont fontWithName:@"AvenirNext-Bold" size:18];
configuration.cellMessageLabelFont = [UIFont fontWithName:@"AvenirNext-Bold" size:15];
configuration.cellHeaderLabelTextColor = [UIColor whiteColor];
configuration.cellMessageLabelTextColor =[UIColor whiteColor];
configuration.cellUnreadBackgroundColor = [UIColor blueColor];
MoEngageInboxNavigationBarStyle* navigationBarStyle = [[MoEngageInboxNavigationBarStyle alloc] init];
navigationBarStyle.navigationBarColor = [UIColor blackColor];
navigationBarStyle.navigationBarTintColor = [UIColor blueColor];
navigationBarStyle.navigationBarTitleColor = [UIColor blueColor];
navigationBarStyle.navigationBarTransluscent = true;
configuration.navigationBarStyle = navigationBarStyle;
//Present
[[MoEngageSDKInbox sharedInstance] presentInboxViewControllerWithUIConfiguration:configuration withInboxWithControllerDelegate:self forAppID:@"YOUR Workspace ID"];
//Push
[[MoEngageSDKInbox sharedInstance] pushInboxViewControllerToNavigationController:navigationController withUIConfiguration:configuration withInboxWithControllerDelegate:nil forAppID:@"YOUR Workspace ID"];
//Fetch MoEngageInboxViewController
[[MoEngageSDKInbox sharedInstance] getInboxViewControllerWithUIConfiguration:configuration withInboxWithControllerDelegate:nil forAppID:@"YOUR Workspace ID" withCompletionBlock:^(MoEngageInboxViewController * _Nullable inboxController) {
}];
```
# Self Handled Inbox
## Fetch Inbox Messages:
Inbox can be completely customized now. Use [*getInboxMessages(forAppID:withCompletionBlock:)*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKInbox.html#/c:@M@MoEngageInbox@objc\(cs\)MoEngageSDKInbox\(im\)getInboxMessagesForAppID:withCompletionBlock:) to fetch the inbox messages.
```swift Swift wrap theme={null}
MoEngageSDKInbox.sharedInstance.getInboxMessages(forAppID: "YOUR Workspace ID") { inboxMessages, account in
print("Received Inbox messages")
}
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKInbox sharedInstance] getInboxMessagesForAppID:@"YOUR Workspace ID" withCompletionBlock:^(NSArray * _Nonnull inboxEntry, MoEngageAccountMeta * _Nullable accountMeta) {
NSLog(@"Received Inbox messages");
}];
```
## Mark a notification as Read:
An inbox notification can be marked as read with the method [*markInboxNotificationClicked(withCampaignID:forAppID:completionHandler)*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKInbox.html#/c:@M@MoEngageInbox@objc\(cs\)MoEngageSDKInbox\(im\)markInboxNotificationClickedWithCampaignID:forAppID:completionHandler:) by providing the campaign ID of the notification while calling the method. The method will return the updated notification payload where the `isRead` key will be set to true.
```swift Swift wrap theme={null}
//Get the MoEngageInboxEntry instance
let pushModel = inboxMessages[]
if !pushModel.isRead {
MoEngageSDKInbox.sharedInstance.markInboxNotificationClicked(withCampaignID: pushModel.campaignID)
}
```
```objective-c Objective C wrap theme={null}
//An example of marking the inbox message as read
MOInboxModel *pushDataObj = [self.inboxMessagesArray objectAtIndex:];
if (!pushDataObj.isRead){
[[MOInboxHandler sharedInstance] markInboxNotificationReadForCampaignID:pushDataObj.campaignID];
//Rest of the implementation
}
```
## Track Inbox Notification Clicks:
An inbox notification click can be tracked by using method [*trackInboxClick(withCampaignID:forAppID:)*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKInbox.html#/c:@M@MoEngageInbox@objc\(cs\)MoEngageSDKInbox\(im\)trackInboxClickWithCampaignID:forAppID:) by providing the campaign ID of the notification while calling the method.
```swift Swift wrap theme={null}
//Get the MoEngageInboxEntry instance
let pushModel = inboxMessages[]
MoEngageSDKInbox.sharedInstance.trackInboxClick(withCampaignID: pushModel.campaignID)
```
```objective-c Objective C wrap theme={null}
//An example of marking the inbox message as read
MOInboxModel *pushDataObj = [self.inboxMessagesArray objectAtIndex:];
[[MOInboxHandler sharedInstance] trackInboxNotificationClickForCampaignID:pushDataObj.campaignID];
```
## Process the Inbox Clicks:
If you want to perform the actions supported by the SDK(i.e, rich landing, deep linking, coupon code etc) associated with the notifications on clicking the entry in Inbox call [*processInboxNotification(withCampaignID:forAppID:)*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKInbox.html#/c:@M@MoEngageInbox@objc\(cs\)MoEngageSDKInbox\(im\)processInboxNotificationWithCampaignID:forAppID:) method as shown below.
```swift Swift wrap theme={null}
//Get the MoEngageInboxEntry instance
let pushModel = inboxMessages[]
MoEngageSDKInbox.sharedInstance.processInboxNotification(withCampaignID: pushModel.campaignID)
```
```objective-c Objective C wrap theme={null}
//An example of process the notification actions
MOInboxModel *pushDataObj = [self.inboxMessagesArray objectAtIndex:];
[[MoEngageSDKInbox sharedInstance] processInboxNotificationWithCampaignID:pushDataObj.campaignID forAppID:@"YOUR Workspace ID"];
```
## Get Unread Notifications count:
You can obtain the unread notifications count from the Inbox by using [*getUnreadNotificationCount(forAppID:withCompletionBlock:)*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKInbox.html#/c:@M@MoEngageInbox@objc\(cs\)MoEngageSDKInbox\(im\)getUnreadNotificationCountForAppID:withCompletionBlock:) method as shown below:
```swift Swift wrap theme={null}
//Get Unread Notifications count
MoEngageSDKInbox.sharedInstance.getUnreadNotificationCount() { count, accountMeta in
print("Unread message count is \(count)")
}
```
```objective-c Objective C wrap theme={null}
//Get Unread Notifications count
[[MoEngageSDKInbox sharedInstance] getUnreadNotificationCountForAppID:@"YOUR Workspace ID" withCompletionBlock:^(NSInteger count, MoEngageAccountMeta * _Nullable accountMeta) {
NSLog(@"Fetched unread message Count");
}];
```
## Deleting Messages
Use [*removeInboxMessages(forAppID:completionHandler:)*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKInbox.html#/c:@M@MoEngageInbox@objc\(cs\)MoEngageSDKInbox\(im\)removeInboxMessagesForAppID:completionHandler:) method to remove all the messages currently stored in inbox.
```swift Swift wrap theme={null}
MoEngageSDKInbox.sharedInstance.removeInboxMessages { success in
print("Removed all inbox messages \(success)")
}
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKInbox sharedInstance] removeInboxMessagesForAppID:@"YOUR Workspace ID" completionHandler:^(BOOL) {
// Add your code
}];
```
Use [*removeInboxMessage(withCampaignID:forAppID:completionHandler:)*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKInbox.html#/c:@M@MoEngageInbox@objc\(cs\)MoEngageSDKInbox\(im\)removeInboxMessageWithCampaignID:forAppID:completionHandler:) method to remove the single message stored in inbox by passing the Campaign ID.
```swift Swift wrap theme={null}
MoEngageSDKInbox.sharedInstance.removeInboxMessage(withCampaignID: "YOUR CAMPAIGN ID")
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKInbox sharedInstance] removeInboxMessageWithCampaignID:@"CAMPAIGN ID" forAppID:@"YOUR Workspace ID"];
```
# Methods deprecated in SDK version 4.4.0
We have revamped the Inbox Module in the SDK version 4.4.0 and following this, we have deprecated `MOInboxPushDataModel` class and use `MOInboxModel` class instances as the model object for notifications. Along with this, we have also deprecated few of the existing methods of `MOInbox` as listed below:
```objective-c Objective C wrap theme={null}
+(NSArray *)getInboxMessages __deprecated_msg("This method is deprecated as the payload structure has changed, this method will be removed in SDK Version 5.0.0. Use getInboxMessagesWithCompletionBlock: instead");
+(void)trackInboxNotificationClickForCampaign:(MOInboxPushDataModel*)campaignObj andIsFirstClick:(BOOL)isFirstClick __deprecated_msg("This method is deprecated as MOInboxPushDataModel Class is depreacted, this method will be removed in SDK Version 5.0.0. Use trackInboxNotificationClickWithCampaignID: instead");
+(void)processInboxNotificationOnClickForCampaign:(MOInboxPushDataModel*)campaignObj __deprecated_msg("This method is deprecated as MOInboxPushDataModel Class is depreacted, this method will be removed in SDK Version 5.0.0. Use processInboxNotificationWithCampaignID: instead");
+(NSMutableDictionary*)markNotificationReadWithCampaignID:(NSString*)cid __deprecated_msg("This method is deprecated as MOInboxPushDataModel Class is depreacted, this method will be removed in SDK Version 5.0.0. Use markInboxNotificationClickedWithCampaignID: instead");
+(void)writeArrayToFile:(NSMutableArray *)anArray __deprecated_msg("Method Deprecated. From SDK Version 5.0.0 you will not be able to change the inbox file content.");
```
These methods will be removed from the SDK version 5.0.0; therefore, make sure you have updated all the Inbox features to use the newer APIs.
**Information**
The MoEngage SDK only synchronizes push data with the Notification Center when the app is launched for the first time or when it returns to the foreground from the background.
# Location triggered
Source: https://moengage.com/docs/developer-guide/ios-sdk/push/optional/location-triggered
Set up geofence-based location-triggered push notifications in your iOS app with the MoEngage SDK.
**Important**
* Starting from **iOS 14.0**, Apple has provided user control to choose the level of precision of location to be shared in App. Now because of this **region monitoring(Geofence feature) will not work in cases where the precise location is disabled by the user**. Refer [link](https://developer.apple.com/videos/play/wwdc2020/10660/) for more info.
* Region monitoring is only supported with **Always authorization**. When-in-use authorization doesn't support this feature. Refer [link](https://developer.apple.com/documentation/corelocation/choosing_the_authorization_level_for_location_services) for more info.
* **Dwell** trigger is **not supported in iOS**, hence the SDK supports only Enter and Exit triggers.
# How to enable Location Triggered?
## Required Permissions:
**Region Monitoring(Geofences) requires Always Authorization and Precise location accuracy to be enabled to work**. Therefore make sure that the app is configured to get these permissions and also it's a good practice to let the user know the context in which these permissions are needed, this will also encourage the user to provide these permissions.
# SDK Installation
## Install using Swift Package Manager
MoEngageGeofence is supported through SPM from SDK version 4.2.0. To integrate, use the GitHub url [https://github.com/moengage/apple-sdk.git](https://github.com/moengage/apple-sdk.git) for SDK versions equal and above 9.23.0, or [https://github.com/moengage/MoEngage-iOS-SDK.git](https://github.com/moengage/MoEngage-iOS-SDK.git) for other SDK versions link and set the branch as master or required version.
## Install using CocoaPod
**Information**
CocoaPods is being deprecated. MoEngage recommends using Swift Package Manager for all new integrations. For more info on CocoaPods, refer to [CocoaPods Integration Guide](/developer-guide/ios-sdk/sdk-integration/basic/integration-through-cocoa-pods).
Integrate the MoEngageGeofence framework by adding the dependency in the podfile as show below.
```ruby Ruby wrap theme={null}
pod 'MoEngage-iOS-SDK/GeoFence',
```
Now run `pod install `to install the framework
## Manual Integration
To integrate the `MoEngageGeofence` SDK manually to your project follow this [doc](/developer-guide/ios-sdk/manual-integration/manual-integration).
**Note**
MOGeofence has been renamed to MoEngageGeofence from version 4.2.0.Do update the podfile and import statement accordingly.
## Start Geofence Monitoring:
After integrating the MoEngageGeofence module call [*startGeofenceMonitoring()*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKGeofence.html#/c:@M@MoEngageGeofence@objc\(cs\)MoEngageSDKGeofence\(im\)startGeofenceMonitoring) method to initiate the geofence module. This will fetch the geofences around the current location of the user.
```swift Swift wrap theme={null}
MoEngageSDKGeofence.sharedInstance.startGeofenceMonitoring()
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKGeofence sharedInstance] startGeofenceMonitoring];
```
Geofence Handler also has callbacks for `didEnterRegion` and `didExitRegion`. You can get these by confirming to the as `MoEngageSDKGeofence.sharedInstance.setGeofenceDelegate(self)`
```swift Swift wrap theme={null}
extension GeofenceViewController: MoEngageGeofenceDelegate {
func geofenceEnterTriggered(withLocationManager locationManager: CLLocationManager?, andRegion region: CLRegion?, forAccountMeta accountMeta: MoEngageAccountMeta) {
print("Geofence Entered")
}
func geofenceExitTriggered(withLocationManager locationManager: CLLocationManager?, andRegion region: CLRegion?, forAccountMeta accountMeta: MoEngageAccountMeta) {
print("Geofence Exited"
}
}
```
```objective-c Objective C wrap theme={null}
@interface MyViewController ()
---
- (void)geofenceEnterTriggeredWithLocationManager:(CLLocationManager *)locationManager andRegion:(CLRegion *)region forAccountMeta:(MoEngageAccountMeta *)accountMeta {
NSLog(@"Geofence Entered");
}
- (void)geofenceExitTriggeredWithLocationManager:(CLLocationManager *)locationManager andRegion:(CLRegion *)region forAccountMeta:(MoEngageAccountMeta *)accountMeta {
NSLog(@"Geofence Exited");
}
```
# Stop Geofence Monitoring:
After version `9.3.0` we have provided support to stop the monitoring of geofences. To stop geofence monitoring call [*stopGeofenceMonitoring()*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKGeofence.html#/c:@M@MoEngageGeofence@objc\(cs\)MoEngageSDKGeofence\(im\)stopGeofenceMonitoring) method.
```swift Swift wrap theme={null}
MoEngageSDKGeofence.sharedInstance.stopGeofenceMonitoring()
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKGeofence sharedInstance] stopGeofenceMonitoring];
```
# Testing Geofencing
First, create a geofencing campaign on your MoEngage dashboard. You can test geofencing in the following ways:
1. On the simulator:
* You can simulate location as shown below.
* Simulate the location for which you have created the campaign on the dashboard. If you get the respective call back (the delegate methods in MoEngageGeofenceHandler), you are good to go. On simulator, you will not receive push notifications.
2. On the device:
* You can simulate location for real device from the bar above the console as shown below:
* You can add a gpx file with the locations configured. A sample gpx file looks like this:
```xml XML wrap theme={null}
CustomName
```
On the device, once you get the delegate callback for entering or exit in a region, a notification will be sent to the device. This happens instantly, but the notification might take up to 10 minutes.
# Geo Notifications
Once you have received the notification, to identify geo notifications, there is a custom param “cType” = “geo” in the param app\_extra, as shown below:
```json JSON wrap theme={null}
{
"app_extra" = {
cType = geo;
screenData = {
"" = "";
};
screenName = "";
};
aps = {
alert = "exit london- single fence";
badge = 1;
};
moengage = {
cid = "55a628bcf4c4073bb66a368b_GEO:55a628bcf4c4073bb66a368c_ABab1:2015-07-15_14:11:33.704706";
};
}
```
# Push Handled by Application
Source: https://moengage.com/docs/developer-guide/ios-sdk/push/optional/push-handled-by-application
Handle push notification display and tracking yourself using the MoEngage iOS SDK messaging APIs.
**SDK Version**
* **General Messaging:** Supported from version 9.13.0
* **Background Updates (Self handled):** Supported from version 10.10.0
## Track Notification Received
Call SDK's ***logNotificationReceived(withPayload: )*** function to track notification received impression as shown below.
```swift Swift wrap theme={null}
MoEngageSDKMessaging.sharedInstance.logNotificationReceived(withPayload:notification.request.content.userInfo) {
// updated content in contentHandler here
}
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKMessaging sharedInstance] logNotificationReceivedWithPayload:notification.request.content.userInfo completion: ^(void) {
// updated content in contentHandler here
}];
```
## Track Notification Click
To track the notification clicked event using the payload, call the SDK's ***logNotificationClicked*** function, as shown below.
```swift Swift wrap theme={null}
MoEngageSDKMessaging.sharedInstance.logNotificationClicked(withPayload: notification.request.content.userInfo)
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKMessaging sharedInstance] logNotificationClickedWithPayload:notification.request.content.userInfo];
```
To accurately track clicks or dismissals, use the ***logNotificationClicked(withResponse: )*** method.
```swift Swift wrap theme={null}
MoEngageSDKMessaging.sharedInstance.logNotificationClicked(withResponse: UNNotificationResponse)
```
**Note**
To use above functions, Appdelegate swizzling should be disabled. To see how to disable swizzling, please see the [link](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial#app-delegate-method-swizzling).
## Validate if the notification belongs to MoEngage
Call SDK's ***isPushFromMoEngage(withPayload:)*** function to validate if the notification belongs to MoEngage as shown below:
```swift Swift wrap theme={null}
let isPushFromMoEngage = MoEngageSDKMessaging.sharedInstance.isPushFromMoEngage(withPayload: notification.request.content.userInfo))
```
```objective-c Objective C wrap theme={null}
BOOL isPushFromMoEngage = [[MoEngageSDKMessaging sharedInstance] isPushFromMoEngageWithPayload:notification.request.content.userInfo];
```
## Handling Background Updates (Self-Handled)
**Prerequisites for iOS Background Updates**
* **Background Modes:** You must enable **Remote notifications** under the *Signing & Capabilities* tab in Xcode.
* **Payload Identifier:** The SDK identifies these payloads by checking for `nt: sh_b` inside the `moeFeatures` dictionary.
The **Background Update** template allows you to send silent data payloads to your application. Because these notifications do not display a UI, the MoEngage SDK provides a specific helper method to identify them so you can execute custom background logic.
For more information on the payload structure and available keys, refer to [Background Update Templates](https://help.moengage.com/hc/en-us/articles/4415622460948-Push-Templates).
**Implementation Note**
Background updates must be handled in the `didReceiveRemoteNotification` fetch completion handler. You must also call `logNotificationReceived` manually to ensure these silent events are recorded in your analytics.
```swift Swift wrap theme={null}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
// 1. Check if it's a MoEngage Background Update payload
if MoEngageSDKMessaging.sharedInstance.isSelfHandledBackgroundNotification(payload: userInfo) {
// 2. Log notification received impression manually
MoEngageSDKMessaging.sharedInstance.logNotificationReceived(withPayload: userInfo) {
// 3. Execute your custom background logic here (e.g., sync data, logout)
// self.handleCustomBackgroundLogic(userInfo)
// 4. Always call the completion handler
completionHandler(.newData)
}
} else {
// Handle standard MoEngage or other push notifications
MoEngageSDKMessaging.sharedInstance.didReceieveNotification(inApplication: application, withInfo: userInfo)
}
}
```
```objective-c Objective C wrap theme={null}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
// 1. Check if it's a MoEngage Background Update payload
if ([[MoEngageSDKMessaging sharedInstance] isSelfHandledBackgroundNotificationWithPayload:userInfo]) {
// 2. Log notification received impression manually
[[MoEngageSDKMessaging sharedInstance] logNotificationReceivedWithPayload:userInfo completion:^{
// 3. Execute your custom background logic here (e.g., sync data, logout)
// [self handleCustomBackgroundLogic:userInfo];
// 4. Always call the completion handler
completionHandler(UIBackgroundFetchResultNewData);
}];
} else {
// Handle standard MoEngage or other push notifications
[[MoEngageSDKMessaging sharedInstance] didReceieveNotificationInApplication:application withInfo:userInfo];
}
}
```
# Push templates
Source: https://moengage.com/docs/developer-guide/ios-sdk/push/optional/push-templates
Add custom push notification templates with Notification Content Extension in your iOS app.
Notification Content Extension allows you to customize the appearance of the notification in expanded mode. For info on how to create campaigns with templates in the dashboard refer to [this](https://help.moengage.com/hc/en-us/articles/4415622460948-Push-Templates) link.
**Prerequisites**
Make sure you have completed the [App Target](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial#step-1-implement-notification-service-extension-nse) and [Notification Service Extension](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial#Optional) Implementation for supporting Rich Push in your project before proceeding with the below steps.
# STEPS:
To support these custom push templates, your project needs to have a Notification Content Extension. Follow the below steps to create a Content Extension and to set it up to support MoEngage templates:
## 1. Create a Notification Content Extension
After the target is created, Activate the scheme for Extension when prompted for the same.
After this, your extension will be added to the project you will see a class with the extension name provided by you while creating and an .plist file associated with it.
## 2. Set deployment target
Set the deployment target same as the main app target.
## 3. Add required Capabilities
In the Capabilities Section add **App Groups** and select the same app group id that you have configured in your App target and Notification Service Extension target.
Refer to the **Set AppGroup ID** section of the [doc](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial#step-1-implement-notification-service-extension-nse) for more information on setting the app group ID on the main target
## 4. Info.plist changes
Make the changes in the `Info.plist` of your Notification Content Extension, as shown above, set NSExtensionAttributes as following:
| Attribute | Attribute Value |
| :--------------------------------------------- | :------------------ |
| UNNotificationExtensionCategory | MOE\_PUSH\_TEMPLATE |
| UNNotificationExtensionInitialContentSizeRatio | 1.2 |
| UNNotificationExtensionDefaultContentHidden | YES |
| UNNotificationExtensionUserInteractionEnabled | YES |
**Note**
Update the UNNotificationExtensionCategory with the necessary values according to the categories that you have declared.
## 5. Storyboard changes
Select ***MainInterface.storyboard*** in your Content extension and remove the default label which is placed there and set the background color of the view to clear color, as shown:
## 6. MoEngageRichNotification Integration
### Integration via Swift Package Manager (Recommended)
To integrate via SPM, use the GitHub url [https://github.com/moengage/apple-sdk.git](https://github.com/moengage/apple-sdk.git) for SDK versions equal and above 9.23.0, or [https://github.com/moengage/MoEngage-iOS-SDK.git](https://github.com/moengage/MoEngage-iOS-SDK.git) for other SDK versions link and set the branch as master or required version.
### Integration via CocoaPod
**Information**
CocoaPods is being deprecated. MoEngage recommends using Swift Package Manager for all new integrations. For more info on CocoaPods, refer to [CocoaPods Integration Guide](/developer-guide/ios-sdk/sdk-integration/basic/integration-through-cocoa-pods).
For integrating through CocoaPod, include **MoEngageRichNotification** pod for your Notification Content Extension as shown below, and run the pod update / install command:
```ruby Ruby wrap theme={null}
target "NotificationContent" do
pod 'MoEngage-iOS-SDK/RichNotification',
end
```
**Manual Integration**
* To integrate the MoEngageRichNotification SDK manually to your project follow this [doc](/developer-guide/ios-sdk/manual-integration/manual-integration).
* Add MoEngageRichNotification to embed binaries in the App target, and ensure it is linked to your Notification Content Extension target.
## 7. Code Changes in Content Extension:
```swift Swift wrap theme={null}
import UIKit
import UserNotifications
import UserNotificationsUI
import MoEngageRichNotification
class NotificationViewController: UIViewController, UNNotificationContentExtension {
override func viewDidLoad() {
super.viewDidLoad()
// Set App Group ID
MoEngageSDKRichNotification.setAppGroupID("Your App Group ID")
}
func didReceive(_ notification: UNNotification) {
// Method to add template to UI
MoEngageSDKRichNotification.addPushTemplate(toController: self, withNotification: notification)
}
}
```
```objective-c Objective C wrap theme={null}
#import "NotificationViewController.h"
#import
#import
@import MoEngageRichNotification;
@interface NotificationViewController ()
@end
@implementation NotificationViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Set App Group ID
[MoEngageSDKRichNotification setAppGroupID:@"Your App Group ID"];
}
- (void)didReceiveNotification:(UNNotification *)notification {
// Method to add template to UI
[MoEngageSDKRichNotification addPushTemplateToController:self withNotification:notification];
}
@end
```
As shown above, make these changes in your ***NotificationViewController*** class:
1. Set the same App Group ID in ***viewDidLoad()*** method which was enabled in Capabilities.
2. Call [*addPushTemplate(toController:withNotification:)* ](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKRichNotification.html#/c:@M@MoEngageRichNotification@objc\(cs\)MoEngageSDKRichNotification\(cm\)addPushTemplateToController:withNotification:)method to add template in ***didReceiveNotification()*** callback.
## 8. Notification Click callback in App:
In the case of Simple Image Carousel notification, to know which slide was clicked by the user, make use of `MOMessagingDelegate` to get `notificationClicked(withScreenName: andKVPairs:)` callback to get key-value pairs and screen name if set for the clicked slide. Refer to the example below, here we are registering for the callback in AppDelegate:
```swift Swift wrap theme={null}
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate, MOMessagingDelegate{
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Set the delegate
MOMessaging.sharedInstance.setMessagingDelegate(self)
//Rest of the implementation
}
// Notification Clicked Callback
func notificationClicked(withScreenName screenName: String?, andKVPairs kvPairs: [AnyHashable : Any]?) {
if let screenName = screenName {
print("Navigate to Screen:\(screenName)")
}
if let actionKVPairs = kvPairs {
print("Selected Action KVPair:\(actionKVPairs)")
}
}
// Notification Clicked Callback with Push Payload
func notificationClicked(withScreenName screenName: String?, kvPairs: [AnyHashable : Any]?, andPushPayload userInfo: [AnyHashable : Any]) {
print("Push Payload: \(userInfo)")
if let screenName = screenName {
print("Navigate to Screen:\(screenName)")
}
if let actionKVPairs = kvPairs {
print("Selected Action KVPair:\(actionKVPairs)")
}
}
}
```
```objective-c Objective C wrap theme={null}
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Set the delegate
[[MOMessaging sharedInstance] setMessagingDelegate:self forAppID:@"YOUR WORKSPACE ID"];
//Rest of the implementation
}
// Notification Clicked Callback
-(void)notificationClickedWithScreenName:(NSString *)screenName andKVPairs:(NSDictionary *)kvPairs{
if (screenName) {
NSLog(@"Screen Name : %@",screenName);
}
if (kvPairs) {
NSLog(@"KV Pairs : %@",kvPairs);
}
}
// Notification Clicked Callback with Push Payload
-(void)notificationClickedWithScreenName:(NSString *)screenName KVPairs:(NSDictionary *)kvPairs andPushPayload:(NSDictionary *)userInfo{
NSLog(@"Push Payload: %@",userInfo);
if (screenName) {
NSLog(@"Screen Name : %@",screenName);
}
if (kvPairs) {
NSLog(@"KV Pairs : %@",kvPairs);
}
}
@end
```
# Real-Time Triggers
Source: https://moengage.com/docs/developer-guide/ios-sdk/push/optional/real-time-triggers
Set up device-triggered push notifications that fire instantly when a user performs an event on iOS.
Real-time device triggers are push notifications that are triggered instantly in the device whenever a trigger event(configured while creating the campaign) is tracked with the SDK [trackEvent:](/developer-guide/ios-sdk/data-tracking/basic/tracking-events) method. In this case, the notifications are triggered in the device, which enables you to post notifications even in offline scenarios.
**Note**
Real-Time Triggers are available from SDK version [4.0.0](/developer-guide/release-notes/ios-sdk/2023-and-older)
# SDK Installation
## Install using Swift Package Manager (Recommended)
MoEngageRealTimeTrigger is supported through SPM from SDK version 1.2.0. To integrate, use the GitHub url [https://github.com/moengage/apple-sdk.git](https://github.com/moengage/apple-sdk.git) for SDK versions equal and above 9.23.0, or [https://github.com/moengage/MoEngage-iOS-SDK.git](https://github.com/moengage/MoEngage-iOS-SDK.git) for other SDK versions link and set the branch as master or required version.
## Install using CocoaPod
**Information**
CocoaPods is being deprecated. MoEngage recommends using Swift Package Manager for all new integrations. For more info on CocoaPods, refer to [CocoaPods Integration Guide](/developer-guide/ios-sdk/sdk-integration/basic/integration-through-cocoa-pods).
From MoEngage-iOS-SDK version 8.2.0, MoEngageRealTimeTrigger module is separated from the SDK to a separate module as MoEngageRealTimeTrigger and hence has to be added separately.
Integrate the RealTimeTrigger framework by adding the dependency in the podfile as shown below.
```ruby Ruby wrap theme={null}
pod 'MoEngage-iOS-SDK/RealTimeTrigger',
```
Now run `pod install` to install the framework
# Manual Syncing
MoEngage SDK syncs all the real-time trigger campaigns whenever the app is **launched OR comes to the foreground**. But in case its needed to manually sync the device triggers for any of the background tasks, use [*syncRealTimeTriggers(forAppID:andCompletionHandler:)*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKRealTimeTrigger.html#/c:@M@MoEngageRealTimeTrigger@objc\(cs\)MoEngageSDKRealTimeTrigger\(im\)syncRealTimeTriggersForAppID:andCompletionHandler:) as shown below:
```swift Swift wrap theme={null}
MoEngageSDKRealTimeTrigger.sharedInstance.syncRealTimeTriggers { (rtSyncCompleted) in
if(rtSyncCompleted){
print("Real-Time trigger sync successfull")
}
}
```
```objective-c Objective C wrap theme={null}
[[MoEngageSDKRealTimeTrigger sharedInstance] syncRealTimeTriggersForAppID:@"YOUR APP ID" andCompletionHandler:^(BOOL rtSyncCompleted) {
if (rtSyncCompleted) {
NSLog(@"Real-Time trigger sync successfull");
}
}];
```
# Additional Callbacks for version below iOS 10
**Note**
For iOS 10 and above, MoEngage SDK uses the UserNotification framework for triggering notifications and relies on the callbacks from **UNUserNotificationCenter** to obtain and process the notification payload. Therefore, make sure the SDK methods are called in UNUserNotificationCenter delegate callbacks as mentioned in this [doc](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial#step-1-implement-notification-service-extension-nse).
For iOS versions below iOS 10 call `didReceieveNotificationinApplication: withInfo:openDeeplinkUrlAutomatically:` method of MoEngage SDK as shown below.
```swift Swift wrap theme={null}
func application(_ application: UIApplication, didReceive notification: UILocalNotification) {
if let userInfo = notification.userInfo {
MoEngage.sharedInstance().didReceieveNotificationinApplication(application, withInfo: userInfo, openDeeplinkUrlAutomatically: true)
}
}
```
```objective-c Objective C wrap theme={null}
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification{
NSDictionary* userInfo = notification.userInfo;
[[MoEngage sharedInstance]didReceieveNotificationinApplication:application withInfo:userInfo openDeeplinkUrlAutomatically:YES];
}
```
# iOS Sample App
Source: https://moengage.com/docs/developer-guide/ios-sdk/sample-app/i-os-sample-app
Explore the MoEngage iOS sample application on GitHub as a reference for your SDK integration.
**Sample App**
The [MoEngage iOS Sample application](https://github.com/moengage/iOS-SampleApp) offers a useful reference point for integrating MoEngage into your iOS app.
## Next Steps
* [SDK Installation](/developer-guide/ios-sdk/sdk-integration/basic/sdk-integration)
* [Release Checklist](/developer-guide/ios-sdk/checklist/release-checklist)
# Custom Proxy Domain - iOS
Source: https://moengage.com/docs/developer-guide/ios-sdk/sdk-integration/advanced/Custom-Proxy-Domain-iOS
Route MoEngage SDK traffic through your own subdomain to bypass ad blockers on iOS.
In today's privacy-focused digital landscape, many users employ ad blockers or private DNS services. These tools often block network requests to known third-party domains, including analytics and engagement platforms. When these requests are blocked, you lose critical data visibility, and your users may not receive in-app messages or push notifications.
To ensure reliable campaign delivery and campaign performance, MoEngage offers the **Custom Proxy Domain** feature. This allows you to route MoEngage SDK traffic through a subdomain of your own primary domain (e.g., `data.yourcompany.com`). Because the traffic appears as first-party communication, it bypasses common ad-blocking lists.
## Onboarding Process
Setting up a Custom Proxy Domain requires a one-time DNS delegation process between your team and MoEngage.
**Prerequisite**
Before updating your SDK code, you must complete the DNS delegation setup. For a detailed guide on picking a domain and configuring NS records, refer to [DNS Delegation](https://help.moengage.com/hc/en-us/articles/45199793953300-DNS-Delegation-for-Custom-Subdomains).
### Step 1: Choose a Subdomain
Select a subdomain that is short and does not contain keywords typically flagged by filters (e.g., avoid "tracking", "ads", or "moengage").
### Step 2: Request DNS Delegation
Contact your MoEngage Customer Success Manager (CSM) or Support Team to initiate the request. Provide your chosen subdomain.
### Step 3: Configure NS Records
MoEngage will provide you with a list of Name Server (NS) records. You must add these records to your DNS provider's configuration for the chosen subdomain.
## Implementation
Once the DNS delegation is verified, update your SDK initialization logic. The SDK will dynamically rewrite all MoEngage endpoints (API calls and CDN assets) to use your custom proxy domain.
### Update MoEngage Configuration
```swift Swift wrap theme={null}
import MoEngageSDK
let sdkConfig = MoEngageSDKConfig(appId: "YOUR_Workspace_ID", dataCenter: DATA_CENTER)
sdkConfig.customBaseDomain = "CUSTOM_DOMAIN"
#if DEBUG
MoEngage.sharedInstance.initializeDefaultTestInstance(sdkConfig)
#else
MoEngage.sharedInstance.initializeDefaultLiveInstance(sdkConfig)
#endif
```
```objective-c Objective C wrap theme={null}
@import MoEngageSDK;
MoEngageSDKConfig* sdkConfig = [[MoEngageSDKConfig alloc] initWithAppId:@"YOUR_Workspace_ID" dataCenter: DATA_CENTER];
sdkConfig.customBaseDomain = @"CUSTOM_DOMAIN";
#ifdef DEBUG
[[MoEngage sharedInstance] initializeDefaultTestInstance:sdkConfig];
#else
[[MoEngage sharedInstance] initializeDefaultLiveInstance:sdkConfig];
#endif
```
## Best Practices and Validation
1. **Domain Selection:** Keep your subdomain string short (5-8 characters).
2. **Network Logs:** Verify that requests start with your custom subdomain (e.g., `sdk-01.data.example.com`).
3. **Asset Loading:** Ensure images in campaigns load correctly.
# Add-On Security
Source: https://moengage.com/docs/developer-guide/ios-sdk/sdk-integration/advanced/add-on-security
Encrypt data stored by the MoEngage iOS SDK on device using Keychain and encrypted storage.
# Encrypted Storage
By default, all the data stored by the SDK on the device is inside the application sandbox. This prevents other applications from accessing the data(both read and write). Due to compliance standards or any other use cases, you might want additionally encrypt the data stored on the SDK.
## Keychain Set Up
To ensure the encryption works as expected, follow the below steps to set up the Keychain Sharing.
1. Turn on Keychain sharing in Xcode with the below steps:
a. Select your app target and click the ***Signing & Capabilities*** tab.
b. Turn on the ***Keychain Sharing*** capability.
2. Specify the Keychain group name
3. App ID Prefix and Keychain group name: Xcode automatically prefixes keychain groups with your team ID. This ensures that your groups are specific to your development team. In order to see how it works, click on the *.entitlements* file and look at the value of the *Keychain Access Groups* array.
4. Get your AppID: The App ID Prefix (also called Team ID) is a unique text identifier associated with your Apple developer account that allows the sharing of keychain and pasteboard items between your apps.
Assume the AppID is ***AB123CDE45***, Keychain group name is ***AB123CDE45.com.example.sharedItems***. Make sure to pass the same keychain group name to MoEngage SDK via the [***keyChainConfig***](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKConfig.html#/c:@M@MoEngageCore@objc\(cs\)MoEngageSDKConfig\(py\)keyChainConfig) property on [***MoEngageSDKConfig***](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKConfig.html) object.
## Enabling Encryption
You can enable the storage encryption by setting the [***storageConfig***](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKConfig.html#/c:@M@MoEngageCore@objc\(cs\)MoEngageSDKConfig\(py\)storageConfig) property on the [***MoEngageSDKConfig***](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKConfig.html) while initializing the SDK.
```swift Swift wrap theme={null}
let sdkConfig = MoEngageSDKConfig(withAppID: "YOUR_APP_ID")
sdkConfig.storageConfig = MoEngageStorageConfig(encryptionConfig: MoEngageStorageEncryptionConfig(isEncryptionEnabled: true))
sdkConfig.keyChainConfig = MoEngageKeyChainConfig(groupName: "YOUR_KEYCHAIN_GROUP_NAME")
```
```objective-c Objective C wrap theme={null}
MoEngageSDKConfig* sdkConfig = [[MoEngageSDKConfig alloc] initWithAppID:@"YOUR Workspace ID"];
sdkConfig.storageConfig = [[MoEngageStorageConfig alloc] initWithEncryptionConfig: [[MoEngageStorageEncryptionConfig alloc] initWithIsEncryptionEnabled:true]];
sdkConfig.keyChainConfig = [[MoEngageKeyChainConfig alloc] initWithGroupName:@"YOUR_KEYCHAIN_GROUP_NAME"];
```
**Note**
Once storage encryption is enabled and a build is released to production(App Store), you should not disable encryption. Disabling the encryption after the build is released will result in a new user being created in the MoEngage system when the user updates the application.
# Encrypted Network Communication
By default, we use HTTPS protocol for all requests made from the SDK; HTTPS encrypts the requests by default. MoEngage SDK optionally adds another layer of encryption apart from the encryption done by HTTPS.
## Enabling Encryption
You can enable the storage encryption setting in the [***networkConfig***](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKConfig.html#/c:@M@MoEngageCore@objc\(cs\)MoEngageSDKConfig\(py\)networkConfig) property on the [***MoEngageSDKConfig***](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKConfig.html) while initializing the SDK.
```swift Swift wrap theme={null}
let sdkConfig = MoEngageSDKConfig(withAppID: appId)
sdkConfig.networkConfig = MoEngageNetworkRequestConfig(dataSecurityConfig: MoEngageNetworkDataSecurityConfig(isEncryptionEnabled: true, encryptionKeyDebug: "YOUR_TEST_ENVIRONMENT_ENCRYPTION_KEY", encryptionKeyRelease: "YOUR_LIVE_ENVIRONMENT_ENCRYPTION_KEY"))
```
```objective-c Objective C wrap theme={null}
MoEngageSDKConfig* sdkConfig = [[MoEngageSDKConfig alloc] initWithAppID:@"YOUR Workspace ID"];
sdkConfig.networkConfig = [[MoEngageNetworkRequestConfig alloc] initWithDataSecurityConfig:[[MoEngageNetworkDataSecurityConfig alloc] initWithIsEncryptionEnabled:true encryptionKeyDebug:@"YOUR_TEST_ENVIRONMENT_ENCRYPTION_KEY" encryptionKeyRelease:@"YOUR_LIVE_ENVIRONMENT_ENCRYPTION_KEY"]];;
```
**Note**
1. When using encrypted network communication, we strongly recommend you enable Storage encryption as well.
2. Adding the above dependency and enabling the flag isn't enough for this feature to work; there is some additional configuration required on our side to enable this feature completely. In case you want to use this feature, reach out to your account manager or the MoEngage Support team.
# JWT Authentication
Source: https://moengage.com/docs/developer-guide/ios-sdk/sdk-integration/advanced/jwt-authentication
Secure your MoEngage data collection by implementing JWT authentication in your iOS application.
## Overview
JWT (JSON Web Token) authentication is a standard method for securely verifying user identity. By implementing JWT authentication, you add a critical layer of security to your data collection process with MoEngage.
The feature ensures that the data sent on behalf of your identified users is authentic and has not been tampered with. This security is achieved by requiring a token that is cryptographically signed by your own server, which prevents unauthorized users from impersonating your legitimate users.
**Prerequisites**
Before you begin the implementation, please ensure you meet the following requirements:
* Your application must use the MoEngage iOS SDK version ***10.08.0*** or higher to access the JWT authentication feature.
* You must have access to your MoEngage dashboard to manage public keys and configure the feature's enforcement settings.
The following diagram illustrates the interaction between your application, your server, the MoEngage SDK, and the MoEngage server:
## Integration
Follow these steps to integrate JWT authentication into your iOS application.
### Step 1: Enable JWT Authentication
You can enable JWT authentication during [SDK initialization](/developer-guide/ios-sdk/sdk-integration/basic/sdk-initialization) by configuring the [***networkConfig***](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKConfig.html#/c:@M@MoEngageCore@objc\(cs\)MoEngageSDKConfig\(py\)networkConfig).[***authorizationConfig***](https://moengage.github.io/ios-api-reference/Classes/MoEngageNetworkRequestConfig.html#/c:@M@MoEngageCore@objc\(cs\)MoEngageNetworkRequestConfig\(py\)authorizationConfig) property on the [***MoEngageSDKConfig***](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKConfig.html) object.
```swift Swift wrap theme={null}
let sdkConfig = MoEngageSDKConfig(appId: "", dataCenter: .YOUR_DATA_CENTER)
sdkConfig.networkConfig = MoEngageNetworkRequestConfig(authorizationConfig: MoEngageNetworkAuthorizationConfig(isJwtEnabled: true))
#if DEBUG
MoEngage.sharedInstance.initializeDefaultTestInstance(sdkConfig)
#else
MoEngage.sharedInstance.initializeDefaultLiveInstance(sdkConfig)
#endif
```
```objective-c Objective C wrap theme={null}
MoEngageSDKConfig* sdkConfig = [[MoEngageSDKConfig alloc] initWithAppId:@"" dataCenter:YOUR_DATA_CENTER];
sdkConfig.networkConfig = [[MoEngageNetworkRequestConfig alloc] initWithAuthorizationConfig:[[MoEngageNetworkAuthorizationConfig alloc] initWithIsJwtEnabled:YES]];
#ifdef DEBUG
[[MoEngage sharedInstance] initializeDefaultTestInstance:sdkConfig];
#else
[[MoEngage sharedInstance] initializeDefaultLiveInstance:sdkConfig];
#endif
```
### Step 2: Pass the JWT to the SDK
Your application is responsible for managing the JWT lifecycle. The recommended flow is to fetch a token upon user login and pass the token to the SDK. You should also check if the token has expired on subsequent app launches and fetch a new one if necessary.
Use the [***MoEngageSDKCore.passAuthenticationDetails()***](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKCore.html#/c:@CM@MoEngageCore@objc\(cs\)MoEngageSDKCore\(im\)passAuthenticationDetails:workspaceId:) method to provide the token to the SDK.
```swift Swift wrap theme={null}
let jwtDetails = MoEngageJwtAuthenticationDetails(token: "your_jwt_token", identifier: "user_id")
MoEngageSDKCore.sharedInstance.passAuthenticationDetails(jwtDetails)
```
```objective-c Objective C wrap theme={null}
MoEngageJwtAuthenticationDetails* jwtDetails = [[MoEngageJwtAuthenticationDetails alloc] initWithToken:@"your_jwt_token" identifier:@"user_id"];
[[MoEngageSDKCore sharedInstance] passAuthenticationDetails:jwtDetails];
```
### Step 3: Handle Authentication Errors
To handle token validation errors that the MoEngage server returns, you must register an error listener using [***MoEngageSDKCore.registerAuthenticationListener()***](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKCore.html#/c:@CM@MoEngageCore@objc\(cs\)MoEngageSDKCore\(im\)registerAuthenticationListener:workspaceId:) method. The SDK invokes this listener when an authentication error occurs, which allows your application to fetch and provide a new token.
```swift Swift wrap theme={null}
class JwtAuthenticationListener: NSObject, MoEngageAuthenticationError.Listener {
func onError(_ error: MoEngageAuthenticationError) {
print("Authentication Error Received:")
if let jwtError = error as? MoEngageJwtAuthenticationError {
print("- Code: \(jwtError.details.code.rawValue) - \(jwtError.details.code.description)")
print("- Token: \(jwtError.details.token == nil ? "No token" : String(jwtError.details.token!.prefix(20)) + "...")")
print("- Identifier: \(jwtError.details.identifier == nil ? "No identifier" : jwtError.details.identifier!)")
print("- Message: \(jwtError.details.message ?? "No message")")
} else {
print("- Message: \(error.details.message ?? "No message")")
}
print("- Account: \(error.accountMeta.appID)")
}
}
// Register listner after SDK initialization
let listener = JwtAuthenticationListener()
MoEngageSDKCore.sharedInstance.registerAuthenticationListener(listener)
```
```objective-c Objective C wrap theme={null}
@interface JwtAuthenticationListener : NSObject
@end
@implementation JwtAuthenticationListener
- (void)onError:(MoEngageAuthenticationError *)error {
NSLog(@"Authentication Error Received:");
if ([error isKindOfClass:[MoEngageJwtAuthenticationError class]]) {
MoEngageJwtAuthenticationError *jwtError = (MoEngageJwtAuthenticationError *)error;
NSLog(@"- Code: %ld - %@", (long)jwtError.details.code.rawValue, jwtError.details.code.description);
NSString *tokenDisplay = jwtError.details.token ?
[[jwtError.details.token substringToIndex:MIN(20, jwtError.details.token.length)] stringByAppendingString:@"..."] :
@"No token";
NSLog(@"- Token: %@", tokenDisplay);
NSLog(@"- Identifier: %@", jwtError.details.identifier ?: @"No identifier");
NSLog(@"- Message: %@", jwtError.details.message ?: @"No message");
} else {
NSLog(@"- Message: %@", error.details.message ?: @"No message");
}
NSLog(@"- Account: %@", error.accountMeta.appID);
}
@end
//
JwtAuthenticationListener *listener = [[JwtAuthenticationListener alloc] init];
[[MoEngageSDKCore sharedInstance] registerAuthenticationListener:listener];
```
### Step 4: Register the listener after SDK initialization
Register the [***MoEngageAuthenticationError.Listener***](https://moengage.github.io/ios-api-reference/Classes/MoEngageAuthenticationError/Listener.html) in a global scope, such as the ***applicaton(\_:didFinishLaunchingWithOptions:)*** method of your AppDelegate class, to ensure your application always receives callbacks.
```swift Swift wrap theme={null}
let listener = JwtAuthenticationListener()
MoEngageSDKCore.sharedInstance.registerAuthenticationListener(listener)
```
```objective-c Objective C wrap theme={null}
JwtAuthenticationListener *listener = [[JwtAuthenticationListener alloc] init];
[[MoEngageSDKCore sharedInstance] registerAuthenticationListener:listener];
```
**Information**
* If an API request fails due to an authentication error, the SDK will not retry the request until your application provides a new token.
* After 10 consecutive authentication failures in a single session, the SDK will stop attempting to sync data until the next session begins. This counter resets after any successful sync.
* Upon user logout, if a data sync fails due to a JWT error, the pending data will be deleted, and no retry will be attempted.
# Configuring Project for Architecture Compatibility
Source: https://moengage.com/docs/developer-guide/ios-sdk/sdk-integration/basic/Configuring-Project-for-Architecture-Compatibility
Configure your Xcode project for arm64 architecture compatibility with MoEngage iOS SDK v10.x.x.
## Overview
**Note**
The changes mentioned in this article are also applied to the CI/CD environment.
Beginning with MoEngage iOS SDK v10.x.x, support for the `x86_64` and `x86` architectures are discontinued. The SDK only supports the `arm64` architecture.
Attempting to build a project for a simulator that runs on x86\_64 architecture used by the [Rosetta](https://developer.apple.com/documentation/apple-silicon/about-the-rosetta-translation-environment) simulator, or a simulator running on an Intel-based Mac (x86\_64), may result in linker errors. This article outlines the procedures for configuring an Xcode project to resolve these errors.
## Identify Host Machine Architecture
To determine the correct configuration procedure, identify the development machine's architecture by executing the following command in the terminal:
```shellscript Shell theme={null}
uname -m
```
The command returns one of the following outputs:
* **`arm64`**: An Apple silicon Mac.
* **`x86_64`**: An Intel-based Mac.
## Configuration Procedures
### For Apple silicon Macs (`arm64`)
On Apple silicon Macs, linker errors occur if the build targets a [Rosetta](https://developer.apple.com/documentation/apple-silicon/about-the-rosetta-translation-environment) simulator, which runs on the `x86_64` architecture. To prevent this, configure the build to run only on the native simulator (`arm64` architecture) as shown below:
1. In Xcode, select your project in the **Project Navigator**, and perform the steps below for all your targets (including Pods targets).
2. Navigate to the **Build Settings** tab.
3. Apply the following configurations for the `Debug` build:
* **`Excluded Architectures (EXCLUDED_ARCHS)`**
* Ensure this setting does not contain `arm64` for simulator builds.
* **`Build Active Architecture Only (ONLY_ACTIVE_ARCH)`**
* Set this value to **Yes**. This setting directs Xcode to build only for the architecture of the currently selected simulator.
* **Architectures** set to ARCHS\_STANDARD or include arm64.
### For Intel-based Macs (`x86_64`)
On Intel-based Macs, the iOS Simulator runs on the `x86_64` architecture. As MoEngage SDK v10.x.x and later do not support this architecture, projects cannot run on the simulator. To build and test the application, use a physical iOS device.
# Data Center
Source: https://moengage.com/docs/developer-guide/ios-sdk/sdk-integration/basic/data-center
Configure data center redirection in the MoEngage iOS SDK to route data to the correct cluster.
We support data redirection to our servers in different clusters. Use [*MoEngageSDKConfig*](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKConfig.html) initializer to set the data center according to your account's configuration.
```swift Swift wrap theme={null}
import MoEngageSDK
let sdkConfig = MoEngageSDKConfig(appId: "YOUR APPID", dataCenter: .data_center_01);
// Possible Values for Data Center
typedef enum {
data_center_01,
data_center_02,
data_center_03,
data_center_04,
data_center_05,
data_center_06 /// Data center 06 available SDK version 9.17.3
}MoEngageDataCenter;
```
```objective-c Objective C wrap theme={null}
@import MoEngageSDK;
MoEngageSDKConfig* config = [[MoEngageSDKConfig alloc] initWithAppId:@"YOUR APP ID" dataCenter:MoEngageDataCenterData_center_01];
// Possible Values for Data Center
typedef enum {
data_center_01,
data_center_02,
data_center_03,
data_center_04,
data_center_05,
data_center_06 /// Data center 06 available SDK version 9.17.3
}MoEngageDataCenter;
```
Following is the host for different data centers; please update the app's configuration according to the DataCenter in case would want to whitelist the SDK API domain:
| Data Center | SDK Host | Dashboard Host |
| :--------------- | :------------------ | :------------------------ |
| data\_center\_01 | sdk-01.moengage.com | dashboard-01.moengage.com |
| data\_center\_02 | sdk-02.moengage.com | dashboard-02.moengage.com |
| data\_center\_03 | sdk-03.moengage.com | dashboard-03.moengage.com |
| data\_center\_04 | sdk-04.moengage.com | dashboard-04.moengage.com |
| data\_center\_05 | sdk-05.moengage.com | dashboard-05.moengage.com |
| data\_center\_06 | sdk-06.moengage.com | dashboard-06.moengage.com |
**Important**
Refer to the dashboard host to know the Data Center of your account. Please make sure that you consult with the MoEngage team before using this method for changing the data center in the SDK.
For more information about MoEngage data centers, refer to [Data Centers in MoEngage](https://help.moengage.com/hc/en-us/articles/360057030512-Data-Centers-in-MoEngage).
# Integration through CocoaPods
Source: https://moengage.com/docs/developer-guide/ios-sdk/sdk-integration/basic/integration-through-cocoa-pods
Install the MoEngage iOS SDK using CocoaPods dependency manager for your Xcode project.
**Information**
CocoaPods is being deprecated. MoEngage recommends using Swift Package Manager for all new integrations. For more information, refer [here](/developer-guide/ios-sdk/sdk-integration/basic/sdk-integration).

Cocoapods is a dependency manager for Objective C & Swift projects and makes integration easier.
1. If you don't have CocoaPods installed, you can do it by executing the following line in your terminal.
```ruby Ruby theme={null}
sudo gem install cocoapods
```
2. If you don't have a Podfile, then create one by using `pod init` command. Post this add `MoEngage-iOS-SDK` pod to your pod file as shown below:
```ruby Ruby theme={null}
pod 'MoEngage-iOS-SDK',
```
**Information**
* To ensure automatic minor version updates for MoEngage-iOS-SDK, configure your Podfile with `pod 'MoEngage-iOS-SDK', '~> Major.Minor.Build'`. For example: `'MoEngage-iOS-SDK', '~>10.03.2`
* For automatic integration of the latest MoEngage-iOS-SDK version, including major changes, use `pod 'MoEngage-iOS-SDK'`.
3. Integrate MoEngage iOS SDK by executing the following in the terminal at your project's root directory:
```ruby Ruby theme={null}
pod repo update
pod install
```
4. Now, open your project workspace and check if MoEngage SDK is properly added.
# SDK Initialization
Source: https://moengage.com/docs/developer-guide/ios-sdk/sdk-integration/basic/sdk-initialization
Initialize the MoEngage iOS SDK in your AppDelegate using your Workspace ID and data center.
# Initializing MoEngage SDK
First, go to `Build Settings` of your `App Target` and ensure that **DEBUG** Preprocessor Macro is defined in `Debug` section as shown in the below image, if not present then add the same by entering `DEBUG=1` in `Debug` section:
**For Swift Project**, In `App Target` `Build Settings` make sure **-DDEBUG** is added to `Debug` section in the `Other Swift Flags` as described in the image:
* in to your MoEngage account, go to **Settings** in the left panel of the dashboard. Under General Settings, you will find your **Workspace ID**. Provide this Workspace ID along with the Datacenter while initializing the SDK with MoEngageSDKConfig instance . Use[***initializeDefaultTestInstance(\_:)***](https://moengage.github.io/ios-api-reference/Classes/MoEngage.html#/c:@M@MoEngageSDK@objc\(cs\)MoEngage\(im\)initializeDefaultTestInstance:) and [***initializeDefaultLiveInstance(\_:)***](https://moengage.github.io/ios-api-reference/Classes/MoEngage.html#/c:@M@MoEngageSDK@objc\(cs\)MoEngage\(im\)initializeDefaultLiveInstance:) methods as shown below.
```Swift Swift wrap theme={null}
import MoEngageSDK
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
//Add your MoEngage Workspace ID and Data center.
let sdkConfig = MoEngageSDKConfig(appId: "YOUR WorkspaceID", dataCenter: DATA_CENTER);
// MoEngage SDK Initialization
// Separate initialization methods for Dev and Prod initializations
#if DEBUG
MoEngage.sharedInstance.initializeDefaultTestInstance(sdkConfig)
#else
MoEngage.sharedInstance.initializeDefaultLiveInstance(sdkConfig)
#endif
//Rest of the implementation of method
//-------
return true
}
```
```objective-c Objective C wrap theme={null}
@import MoEngageSDK;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//TODO: Add your MoEngage Workspace ID and Data center.
MoEngageSDKConfig* sdkConfig = [[MoEngageSDKConfig alloc] initWithAppId:@"YOUR Workspace ID" dataCenter: DATA_CENTER];
// MoEngage SDK Initialization
// Separate initialization methods for Dev and Prod initializations
#ifdef DEBUG
[[MoEngage sharedInstance] initializeDefaultTestInstance:sdkConfig];
#else
[[MoEngage sharedInstance] initializeDefaultLiveInstance:sdkConfig];
#endif
//Rest of the implementation of method
//-------
}
```
* In your MoEngage account, if your [portfolio](https://help.moengage.com/hc/en-us/articles/40394603054100-Portfolio) is configured with multiple projects, Provide the respective Project ID along with the Datacenter while initializing the SDK with MoEngageSDKConfig instance . Use [initializeDefaultTestInstance(\_:)](https://moengage.github.io/ios-api-reference/Classes/MoEngage.html#/c:@M@MoEngageSDK@objc\(cs\)MoEngage\(im\)initializeDefaultTestInstance:) and[ initializeDefaultLiveInstance(\_:)](https://moengage.github.io/ios-api-reference/Classes/MoEngage.html#/c:@M@MoEngageSDK@objc\(cs\)MoEngage\(im\)initializeDefaultLiveInstance:) methods as shown below:
```swift Swift wrap theme={null}
let sdkConfig = MoEngageSDKConfig(appId: "YOUR WorkspaceID", dataCenter: DATA_CENTER)
sdkConfig.projectConfig = MoEngageProjectConfig(projectID: "YOUR ProjectID")
#if DEBUG
MoEngage.sharedInstance.initializeDefaultTestInstance(sdkConfig)
#else
MoEngage.sharedInstance.initializeDefaultLiveInstance(sdkConfig)
#endif
```
```objective-c Objective C wrap theme={null}
MoEngageSDKConfig* sdkConfig = [[MoEngageSDKConfig alloc] initWithAppId:@"YOUR Workspace ID" dataCenter: DATA_CENTER];
sdkConfig.projectConfig = [[MoEngageProjectConfig alloc] initWithProjectID:@"YOUR Project ID"];
#ifdef DEBUG
[[MoEngage sharedInstance] initializeDefaultTestInstance:sdkConfig];
#else
[[MoEngage sharedInstance] initializeDefaultLiveInstance:sdkConfig];
#endif
```
Following details of the different data centers you need to set based on the dashboard hosts
| Data Center | Dashboard host |
| :------------------------- | :------------------------ |
| DataCenter.DATA\_CENTER\_1 | dashboard-01.moengage.com |
| DataCenter.DATA\_CENTER\_2 | dashboard-02.moengage.com |
| DataCenter.DATA\_CENTER\_3 | dashboard-03.moengage.com |
| DataCenter.DATA\_CENTER\_4 | dashboard-04.moengage.com |
| DataCenter.DATA\_CENTER\_5 | dashboard-05.moengage.com |
| DataCenter.DATA\_CENTER\_6 | dashboard-06.moengage.com |
For more information about the detailed list of possible configurations, refer to the [API reference](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKConfig.html).
**Note**
***data\_center\_06*** is available from MoEngage-iOS-SDK version 9.17.3 onwards
**Important**
Make sure to call the initialization method in `applicationDidFinishLaunching(_:)` method. In case if you are initializing the SDK at a later stage and not at launch then you will have to call all the notification related methods instead of just relying on [AppDelegate Swizzling](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial#app-delegate-method-swizzling).
# Test/Live Environment
As mentioned above while initializing the build, MoEngage SDK makes use of the `DEBUG` preprocessor macro to decide whether the build is meant for TEST/LIVE Environment. Therefore, you will have to take care of the same while generating the build and make sure that the **Build Configuration** of the App's target is set as mentioned below:
* For **Development** Build: Build Configuration should be set to **Debug** (Data will be tracked in **TEST** Environment)
* For **AdHoc Build/App Store** Build: Build Configuration should be set to **Release** (Data will be tracked in **LIVE** Environment)
**What if Build Configuration is not set correctly?**
If the build configuration is not set correctly following might happen:
* You will see the data from the development build in LIVE environment
* **OR** data from AdHoc/Production Build in TEST environment
* You will get **Bad Device Token** error while trying to send a push notification to the device
# How to set Build Configuration?
## Build Configuration on Running the app from Xcode:
Whenever you run the app directly from Xcode without archiving, make sure the build configuration of **Run mode** of the App Target in Edit Scheme is set to **Debug**(set by default settings). Doing this will make sure data is tracked in TEST Environment.
## Build Configuration on Exporting the build:
While exporting the build make sure you set the correct `Build Configuration`. By default for Archive section in `Edit Scheme` the `Build Configuration` will be set to `Release`, but for a development build make sure its changed to `Debug` before exporting the build. To set the **Build Configuration** of the build in your Xcode project go to **App Target > Edit Scheme > Archive > Build Configuration** and set the configuration to **Debug/Release**(depending on the type of build). Refer to the image as described:
# Switching Environment in Dashboard
In the MoEngage dashboard you can switch between [test and live environment](https://help.moengage.com/hc/en-us/articles/210845683-LIVE-TEST-environments) for your app.
**TEST** Environment is used for all the development and testing-related uses and **LIVE** environment is used for running all the campaigns for AppStore Builds for your app's user base.
# SDK Integration
Source: https://moengage.com/docs/developer-guide/ios-sdk/sdk-integration/basic/sdk-integration
Install the MoEngage iOS SDK using Swift Package Manager or CocoaPods for your project.
**Note**
* The current SDK supports **iOS11 and above**.
* For complete API reference of the SDK, refer to the docs in this [link](https://moengage.github.io/ios-api-reference/).
# Integration through Swift Package Manager
Swift Package Manager (SPM) is a tool for managing the distribution of Swift code. It’s integrated with the Swift build system to automate the process of downloading, compiling, and linking dependencies.
To install the MoEngage-iOS-SDK through SPM, follow the below steps:
1. Navigate to File -> Add Package
2. Enter the URL [https://github.com/moengage/apple-sdk.git](https://github.com/moengage/apple-sdk.git) for SDK versions equal and above 9.23.0, or [https://github.com/moengage/MoEngage-iOS-SDK.git](https://github.com/moengage/MoEngage-iOS-SDK.git) for other SDK versions and select the branch as master or required version to install the package.
3. Click Add Package.
4. Now, MoEngage-iOS-SDK package is installed.
**Information**
CocoaPods is being deprecated. MoEngage recommends using Swift Package Manager for all new integrations. If your project requires CocoaPods, see the [CocoaPods Integration Guide](/developer-guide/ios-sdk/sdk-integration/basic/integration-through-cocoa-pods).
# Manual Integration
For more information about how to integrate the SDK manually into your project, refer to [Manual Integration](/developer-guide/ios-sdk/manual-integration/manual-integration).
# Troubleshooting and FAQs - iOS SDK
Source: https://moengage.com/docs/developer-guide/ios-sdk/troubleshooting-and-faqs/troubleshooting-and-faqs-ios
Enable SDK logs and find answers to common MoEngage iOS SDK integration and debugging questions.
# Enable SDK logs
By default, we have disabled logs from the SDK. For debugging if you want to see the SDK logs in your console, use the configuration below:
```swift Swift wrap theme={null}
sdkConfig.consoleLogConfig = MoEngageConsoleLogConfig(isLoggingEnabled: true, loglevel: .verbose)
```
```objective-c Objective C wrap theme={null}
MoEngageConsoleLogConfig *consoleLogConfig = [[MoEngageConsoleLogConfig alloc] initWithIsLoggingEnabled:TRUE loglevel:MoEngageLoggerTypeVerbose];
```
*All MoEngage logs are prefixed by the keyword "MoEngage".*
# FAQs
## Don't see events in the dashboard?
* Make sure that the [SDK initialization](/developer-guide/ios-sdk/sdk-integration/basic/sdk-initialization) is done properly. Check if the App ID provided in the initialization method is correct.
* Once the App ID is checked, make sure you are checking in the right MoEngage environment. While initializing the SDK, you must make use of the **DEBUG** macro in your project. By default behavior, if the build configuration is set to Debug then events will show up in **Test Environment**, or else if build configuration is set to Release then events will be tracked in **Live Environment**.
* In the SDK we reject events with invalid event attributes. Event attribute values can only have Strings, Numbers, and dictionaries, or else events might get rejected. For confirming enable the SDK logs and check if the events list sent while the app goes to the background has the event you are tracking, if not then events are getting rejected by the SDK.
* If neither of the above then sometimes it takes a little time to show up in the dashboard, so wait for about 10-15 mins for the events to show up. :)
## Seeing events of one user in another user's profile?
* Make sure you have implemented user unique ID tracking properly. Please set [**User Attribute Unique ID**](/developer-guide/ios-sdk/data-tracking/basic/tracking-user-attributes) **unique** to your users that are logged, don't hardcode this value.
* Make sure [resetUser](/developer-guide/ios-sdk/data-tracking/basic/tracking-user-attributes) method is called on the logout feature of the App so that SDK can differentiate between the users.
## IDFA not getting tracked?
* SDK tracks IDFA (Advertising Identifier) only when `AdSupport` framework is included in the project. This is to make sure to track IDFA only for apps that use `AdSupport` to show ads in the App. Also, there is an AppStore restriction on using IDFA without showing Ads in the app, which may result in rejection of the build.
* Also, we track IDFA only if the user has not limited the Ad Tracking in the device settings.
* If your app is not showing any ads then we advise you to remove `AdSupport` the framework to avoid rejection in the AppStore review process.
## Not getting push notifications on your devices?
* First, check if the [implementation](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial#step-1-implement-notification-service-extension-nse) is done correctly. Ensure you registered your app for push notifications correctly, check if you are getting the device token while trying to register for Remote Notification, and the same is sent to the SDK correctly.
* Refer this [link](/developer-guide/ios-sdk/push/basic/apns-certificate-pem-file-legacy) and verify uploaded APNS pem file is valid.
* The dashboard says notification sent, but the device didn’t receive it - Check if notification settings for the app were disabled.
## Getting BadDeviceToken Error while sending the push notifications?
* This error comes whenever you try to send push notifications from the TEST environment to AppStore/AdHoc Build **OR** from a LIVE environment to development build.
* Set Build Configuration correctly and test in the correct environment. Refer [link](/developer-guide/ios-sdk/sdk-integration/basic/sdk-initialization) for more info.
## Getting DeviceTokenNotForTopic Error while sending the push notifications?
* You will get this error when **Bundle-ID** of the build-in which you are expecting the push notifications and that of APNS certificate uploaded in the dashboard (`pem` file) are different.
## Push notification clicks not getting updated?
* Ensure that you are calling MoEngage SDK methods in callback methods which are called on receiving remote notifications.
## Rich landing not working for push notifications?
* **If HTTP link**: HTTP URLs aren't supported in iOS9 and above unless explicitly specified in the plist. Include **App Transport Security Settings** Dictionary in your **Info.plist** and inside this set **Allow Arbitrary Loads to YES**.
* Check if the Rich Landing URL is valid.
## Images/Video/Audio in Rich Notifications(iOS10 and above) not showing in push notifications?
* Make sure you have implemented the [Rich Notification](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial#tracking-and-analytics-verification) feature correctly.
* **If HTTP link**: HTTP URLs aren't supported in iOS9 and above unless explicitly specified in the plist. Include **App Transport Security Settings** Dictionary in your Notification Service Extensions **Info.plist** and inside this set **Allow Arbitrary Loads to YES**.
* Check if the Image/Audio/Video URL is valid.
## Not Getting notifications that are not clicked by users in the Notification Center(Inbox)?
* Make sure that the SDK Version is above 4.4.0, and confirm if you have implemented Notification Service Extension as mentioned [here](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial#step-1-implement-notification-service-extension-nse).
* Along with it make sure that the App Group IDs are set correctly for both the [App Target](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial#step-1-implement-notification-service-extension-nse) and the Service Extension target.
## Not getting Screen Names drop-down in the Navigation Action while creating the campaign?
* MoEngage iOS SDK doesn't track screen Names in your app. The possible values for screenName parameter are something that has to be defined by developers in the project. Therefore, there will be no dropdown in case of iOS and the Screen name value has to be entered by the marketer in the text field while creating the campaign. MoEngage will provide the entered value in the notification payload. The developers will have to implement the part to parse and get the `screenName` parameter's value and to navigate to the mentioned screen.
## InApp campaign doesn't show in the app?
* Make sure **handleInAppMessage** method is called wherever In-App is displayed - [link](/developer-guide/ios-sdk/in-app-messages/in-app-nativ)
* In-App only came once and can’t see/test it again. Then it might be a case where inApp to be shown may not pass a set of rules which we have kept in SDK to make sure the user experience isn't hindered. Refer the [link](/developer-guide/ios-sdk/in-app-messages/in-app-nativ) to know about these rules.
* In case image URLs are with HTTP scheme: HTTP URL aren't supported in iOS9 and above unless explicitly specified in the Apps `info.plist`. You will have to include **App Transport Security Settings** Dictionary in your Info.plist and inside this set **Allow Arbitrary Loads** to **YES**.
* [Enable SDK logs](/hc/en-us/articles/4404197969812-Troubleshooting-And-FAQs#enable-sdk-logs-0-0) to get more details on why inApp didn't show up and share it with MoEngage Team.
## Why are you getting Missing Purpose String in Info.plist File warning from App Store?
Very recently you would have started getting this warning mail from Apple on uploading the build to AppStore. This mail informs about a restriction that will be applied by Apple starting from Spring 2019. As a fix for this issue, we have separated SDK's Geofence module to [MOGeofence](http://cocoapods.org/pods/MOGeofence) from MoEngage-iOS-SDK [version 4.3.0](/developer-guide/release-notes/ios-sdk/2023-and-older), and going forward has to be integrated separately into a project. Also because of this, there are few changes in the implementation of geofence campaigns. Please follow the [docs](/developer-guide/ios-sdk/push/optional/location-triggered) here to know more.
# Getting FCM Server Key
Source: https://moengage.com/docs/developer-guide/partner-integrations/firebase/getting-fcm-server-key
Locate your Firebase Cloud Messaging server key in the Firebase console for MoEngage integration.
Firebase Cloud Messaging (FCM) server key is available on the Firebase console.
For more information, refer to [Firebase documentation](https://firebase.google.com/docs/projects/api-keys).
# Content Security Policy (CSP) and Impact on Personalize
Source: https://moengage.com/docs/developer-guide/personalize-sdk/sdk-integration/content-security-policy-csp-and-impact-on-personalize
Learn how to configure CSP to work seamlessly with MoEngage Personalize.
# What is Content Security Policy
**Content Security Policy** (CSP) for websites is a security mechanism that allows web administrators to define and enforce rules for how resources (such as scripts, stylesheets, images, and fonts) are loaded and executed on their websites. It helps protect against cross-site scripting (XSS) attacks and other types of code injection vulnerabilities.
CSP works by specifying an HTTP header or a meta tag in the website's HTML code, which contains a policy directive defining the allowed sources for various types of content. These sources can include hostnames, paths, or specific types of content (e.g., `'self'` for the same origin, `'none'` for disallowed, `'unsafe-inline'` for inline scripts/styles, and `'unsafe-eval'` for evaluating code dynamically).
```html HTML wrap theme={null}
```
In this example:
* `default-src 'self';` sets the default policy for all resource types to only allow resources from the same origin ('self').
* `script-src 'self' 'unsafe-inline' www.example.com;` allows scripts to be loaded from the same origin ('self'), allows inline scripts ('unsafe-inline'), and allows scripts from [www.example.com](http://www.example.com/).
* `style-src 'self' 'unsafe-inline' fonts.googleapis.com;` allows stylesheets to be loaded from the same origin ('self'), allows inline styles ('unsafe-inline'), and allows stylesheets from [fonts.googleapis.com](https://developers.google.com/fonts).
* `img-src 'self' data:;` allows images to be loaded from the same origin ('self') and allows data URLs.
* `font-src 'self' fonts.gstatic.com;` allows fonts to be loaded from the same origin ('self') and allows fonts from fonts.gstatic.com.
***
# Why is CSP important
When a user visits a website with CSP enabled, their browser will check if the requested resources comply with the defined policy. If any resources do not meet the policy's rules, the browser may block or modify their behavior, depending on the configuration.
CSP provides several benefits, including:
1. **Mitigation of XSS attacks**: By restricting the sources of executable code, CSP reduces the risk of malicious code injection by only allowing trusted sources.
2. **Protection against data exfiltration**: CSP can prevent unauthorized data transmissions by limiting the origins to which data can be sent.
3. **Protection against clickjacking**: CSP can prevent clickjacking attacks by restricting the frame or iframe sources.
4. **Enhanced security posture**: CSP helps in fortifying the overall security of web applications and websites by providing an additional layer of protection against various types of attacks.
***
# How does it impact Personalize
If you have implemented a Content Security Policy (CSP) for your website, which specifies the allowed sources for loading your website's content, browsers will reject content from sources that are not whitelisted. In this scenario, browsers will not permit MoEngage to load content on your website. As a result, the loading of variations that you have created in MoEngage may be affected.
***
# How to navigate CSP
To enable MoEngage to load variations on your website and generate previews for your variations, you need to whitelist MoEngage by updating the corresponding rules in your existing Content Security Policy (CSP).
| Policy Directive | What To Add To The Directive? |
| :------------------------------------ | :--------------------------------------------------------------------------------------------------- |
| **script-src-elem** or **script-src** | `*.moengage.com` |
| **style-src** | `'unsafe-hashes' *.moengage.com fonts.googleapis.com` |
| **img-src** | `*.moengage.com` [moe-email-campaigns.s3.amazonaws.com](http://moe-email-campaigns.s3.amazonaws.com) |
| **font-src** | `*.moengage.com fonts.googleapis.com fonts.gstatic.com;` |
| **connect-src** | `*.moengage.com` |
| **frame-src** | `*.moengage.com` |
| **media-src** | `*.moengage.com` |
# Custom Attributes
Source: https://moengage.com/docs/developer-guide/personalize-sdk/sdk-integration/custom-attributes
Learn how to define and use custom attributes to personalize user experiences on your website.
**Prerequisite**
MoEngage Personalize SDK must be integrated on your webpage to define custom attributes.
# What are custom attributes?
Custom attributes are used to define what pages on a website and what values on those pages can be used to personalize the experience for visitors. It helps you avoid configuring a combination of multiple URLs to deliver the experience on the right set of pages.
Below are the set of standard fields that can be used as a targeting criterion:
* `pageType`
* `category`
* `firstLevel`
* `secondLevel`
* `thirdLevel`
* `fourthLevel`
* `unitPrice`
* `salePrice`
* `currency`
Any values apart from the above can be defined in the **custom** block and then used for targeting.
```javascript JavaScript wrap theme={null}
window.moePageContext = {
pageType: "product page",
category: {
firstLevel: "Clothing & Accessories",
secondLevel: "T-shirts",
thirdLevel: "Polos"
},
unitPrice: "24",
salePrice: "18",
discount: "25",
currency: "USD",
custom: {
size: "Medium",
color: "Black",
gender: "Unisex"
}
};
```
**Below are some examples of using custom attributes**
## E-commerce
| Field name | Description | Example |
| :------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :--------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **pageType** | Define the type of page. Standard page type values are: *Homepage, category, cart, checkout, success* | `pageType: "Homepage"` **OR** `pageType: "category"` |
| **category** | Experiences can be targeted for any of the 4 levels of categories. | `category: { firstLevel: "Electronics", secondLevel: "Home Audio", thirdLevel: "Speaker", fourthLevel: "Bluetooth Speakers" }` |
| **unitPrice** | Target product pages based on the original price of the product. | `unitPrice: "24"` |
| **salePrice** | Target product pages based on the discounted price of the product. | `salePrice: "18"` |
| **discount** | Target product pages based on the discount amount on the product. | `discount: "25"` |
| **currency** | Target product pages based on the currency of the product. | `currency: "USD"` |
| **custom** | Any other trait that you want to target for personalization.
**Example:** Personalize all pages that display **White, Medium**-size Polo T-shirts for **Men** **OR** Personalize checkout page only when the cart value is \$500 or above and cart discount is 0 and cart contains at least 2 items. | **custom**: `{ color: "White", size: "M", gender: "Male" }` **OR** **custom**: `{ cartAmount: "750", cartDiscount: "0", cartQuantity: "4" }` |
## Finance
| Attribute | Description | Example |
| :----------- | :---------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------- |
| **pageType** | Define the type of page. Standard page type values are: *Homepage, blog, service/products, resources/downloads, offers* | `pageType: "Homepage"` **OR** `pageType: "products"` **OR** `pageType: "services"` |
| **category** | Experiences can be targeted for any of the 4 levels of categories. | `category: { firstLevel: "Insurance", secondLevel: "Health Insurance", thirdLevel: "Medical Insurance" }` |
For further assistance, please contact your MoEngage Customer Success Manager (CSM) or the Support team.
# Offerings events tracking
Source: https://moengage.com/docs/developer-guide/personalize-sdk/sdk-integration/offerings-events-tracking
Track impression and click events for MoEngage Offerings fetched via the Personalize SDK or API.
This document outlines the new methods available in the MoEngage Personalize SDK to report impressions and clicks for Offerings fetched using the [MoEngage Personalize SDK](/developer-guide/personalize-sdk/sdk-integration/self-handled-personalize-api-experiences) or directly via the [MoEngage Personalize API](https://www.moengage.com/docs/api/personalize-experience/personalize-overview).
# Pre-Requisites
## SDK Integration
Refer to [this article](/developer-guide/web-sdk/web-sdk-integration/basic-integration/web-sdk-integration) to integrate the Web SDK on your website.
Refer to [this article](/developer-guide/personalize-sdk/sdk-integration/web-personalization-v2) to integrate the Personalize SDK on your website.
## MoEngage Account Configuration
Ensure your MoEngage workspace is enabled to utilize Offerings. Refer to [this article](https://help.moengage.com/hc/en-us/articles/38661119123732-Offerings) for details on setting up Offerings.
# Reporting Offering Shown events
The SDK provides a method to track offering shown events.
Impressions should be reported when an Offering is visually presented to the user.
To report an impression offering, pass the **offeringContext** as a map.
```javascript Javascript wrap theme={null}
```
# Reporting Offering Clicked events
The SDK provides a method to track offering clicked events.
Clicked events should be reported when a user clicks on any offering contained in the response of the Personalize API. To report a click event for a single offering, pass the **offeringContext** of the offering.
When a user clicks on an Offering, we understand that they are also implicitly clicking on the parent Experience. You can now optionally pass the experienceContext to the **offeringClicked** function.
### **What this means**
* **If you pass both contexts,** MoEngage will **automatically** track clicks for **both** the Offering and the Experience. You no longer need to make a second, separate call to track the click event for the parent experience.
* **If you only pass the offeringContext,** the **experienceContext** is optional. If you don't pass it, we will only track the click for the Offering. You would then need to track the experience click separately, if required.
```javascript Javascript wrap theme={null}
```
# Personalize API Experience events tracking
Source: https://moengage.com/docs/developer-guide/personalize-sdk/sdk-integration/personalize-api-experience-events-tracking
Track impression and click events for API experiences created via the MoEngage Personalize API.
This document outlines the new methods available in the MoEngage Personalize SDK to report impressions and clicks for API experiences created via the [MoEngage Personalize API](https://www.moengage.com/docs/api/personalize-experience/personalize-overview).
# Pre-Requisites
## SDK Integration
1. Refer to [this article](/developer-guide/web-sdk/web-sdk-integration/basic-integration/web-sdk-integration) to integrate the Web SDK on your website.
2. Refer to [this article](/developer-guide/personalize-sdk/sdk-integration/web-personalization-v2) to integrate the Personalize SDK on your website.
## MoEngage Account Configuration
Ensure your MoEngage workspace is enabled to utilize Personalize. Refer to [this article](https://help.moengage.com/hc/en-us/articles/24644175705236-Create-Server-side-Personalization-Experience) for details on setting up a Personalize API experience.
# Reporting Experience Shown events
The SDK provides a method to track experience shown events. To report an impression for an experience, use the below SDK method.
```javascript Javascript wrap theme={null}
```
**experienceContext** is a JSON object that is returned in the Response to the Personalize API experience Fetch call. More details [here](https://www.moengage.com/docs/api/experiences/fetch-experience#response-experiences).
# Reporting Experience Clicked events
The SDK provides a method to track experience clicked events. To report an click for an experience, use the below SDK method.
```javascript Javascript wrap theme={null}
```
**extraAttributes** is a **optional** JSON object in which you can pass additional information about the link or the CTA which the user has interacted with.
```json JSON wrap theme={null}
{
"button_id": "",
"button_name": "",
"button_type": "",
}
```
The example JSON provided above illustrates sample values designed to give you a clear understanding of the types of data you can include when tracking additional information about clicks. Feel free to adapt these values to suit your specific implementation needs.
# Self Handled Personalize API experiences
Source: https://moengage.com/docs/developer-guide/personalize-sdk/sdk-integration/self-handled-personalize-api-experiences
Fetch Personalize API campaign data using the SDK and build custom UI for personalized experiences.
# Overview
MoEngage's Self-handled experience gives you the flexibility of creating Personalize API Campaigns on the MoEngage Platform and displaying the experience anywhere on the website. It allows you to fetch the experience's data using the SDK which you can use to personalize the user experience on the website.
# Implementing Self Handled Experiences
## Pre-requisites
### SDK installation
1. Refer to [this article](/developer-guide/web-sdk/web-sdk-integration/basic-integration/web-sdk-integration) to integrate the Web SDK on your website.
2. Refer to [this article](/developer-guide/personalize-sdk/sdk-integration/web-personalization-v2) to integrate the Personalize SDK on your website.
### Creating Personalize API experience
Refer to [this article](https://help.moengage.com/hc/en-us/articles/24644175705236-Create-Server-side-Personalization-Experience) to create a Personalize API experience.
## Fetching Personalize API experiences
Use the below SDK method to fetch the experiences and build your own UI using the result.
```javascript JavaScript wrap theme={null}
```
| Parameter | Description |
| ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `Moengage.personalize.fetchExperiences([], {custom attributes KV pair})` | `fetchExperiences` is the Web SDK method that will fetch all the Personalize API experiences as per the experience keys & custom attributes specified as input. |
| `[]` | This is an optional input. If no input is specified, then the method will return the response payload based on the following conditions: 1. **Logged in User** - If the user is logged in using the SDK, then response will contain the payload of all the experiences in which user is part of the target audience. 2. **Anonymous user** - If there is no user logged in using the SDK, then the response will contain the payload of all experiences that are targeted for **All Users**. Example: `["home-page-banner", "cart-checkout-offers"]`
In the above input, the method will return the payload for experiences configured with the keys "home-page-banner" and "cart-checkout-offers" respectively. |
| `{custom attributes KV pair}` | This is an optional input. Custom Attributes are the additional values used to define a target audience while creating a Personalized API experience. Refer to [this article](https://help.moengage.com/hc/en-us/articles/24644175705236-Create-Server-side-Personalization-Experience) for more details. Example: `{"locale": "en"}`
When you pass the above input, the response will contain all the experiences with audiences defined using the custom attribute **locale** and value equals **"en"** |
For further assistance, please contact your MoEngage Customer Success Manager (CSM) or the Support team.
# Web Personalization - V2
Source: https://moengage.com/docs/developer-guide/personalize-sdk/sdk-integration/web-personalization-v2
Integrate the MoEngage Personalize SDK to deliver personalized website experiences to your visitors.
MoEngage's Web Personalization allows you to personalize the website experience for every visitor with limited or no involvement from tech teams. Ensure that you have followed the SDK integration [doc](/developer-guide/web-sdk/web-sdk-integration/basic-integration/web-sdk-integration) and that the SDK is working properly.
# Prefetch the MoE domain
Add the following code snippet at the top of the `` to prefetch the moengage.com domain:
```javascript JavaScript wrap theme={null}
```
The 'X' in the API Endpoint URL refers to the MoEngage data center (DC). MoEngage hosts each customer in a different DC. You can find your DC number (value of X) and replace the value of 'X' in the URL by referring to the DC and API endpoint mapping [here](https://help.moengage.com/hc/en-us/articles/360057030512-Data-Centers-in-MoEngage).
# Method 1: Initiate Web P Module
The following table contains the details of the different data centers mapped to the dashboard hosts and is required for integration.
| Data Center | Dashboard host |
| :---------- | :------------------------ |
| dc\_1 | dashboard-01.moengage.com |
| dc\_2 | dashboard-02.moengage.com |
| dc\_3 | dashboard-03.moengage.com |
| dc\_4 | dashboard-04.moengage.com |
| dc\_6 | dashboard-06.moengage.com |
## Production or LIVE Environment
Add this script to initiate the web personalization module:
```javascript JavaScript wrap theme={null}
```
Change the following fields:
* Replace the 'workspace\_id' in the URL above with the Workspace ID in the MoEngage Dashboard settings. Navigate to Dashboard -> Settings -> App -> General and copy the Workspace ID.
* Replace 'DC' in the URL above with the data center your instance is hosted on. MoEngage hosts each customer in a different data center. Tracked data is stored in the default data center of MoEngage. To find your data center mapping, refer to Data Center Mapping. The possible value is dc\_X where 'X' is your data center number.
* Replace 'sdkVersion' in the URL above with the version of Web SDK that you are using. In case you are using NPM, use the version number of @moengage/web-sdk dependency that is in your package.json file.
For example, if the dashboard URL starts with [https://dashboard-01.moengage.com](https://dashboard-01.moengage.com), your current version of Web SDK is 2, and workspace\_id is XXXXXXXXXXXXXXXX, then the prefetch and initiation code would be:
```javascript JavaScript wrap theme={null}
```
**Warning**
Always update the version in the web personalisation cdn link whenever you change the version of Web SDK. Both this link and the Web SDK should have the exact same version every time for proper functioning of Web Personalisation.
## Test Environment
For data to be tracked in the test environment, include `debug_logs` in the src of the above script as follows:
```javascript JavaScript wrap theme={null}
```
For example, if the dashboard URL starts with [https://dashboard-01.moengage.com](https://dashboard-01.moengage.com), your current version of Web SDK is 2, and workspace\_id is XXXXXXXXXXXXXXXX, then the whole code will look like:
```javascript JavaScript wrap theme={null}
```
# Method 2: If you have passed the useLatest: true flag in NPM initialisation config
In this case, Add this script to initiate the web personalization module:
```javascript JavaScript wrap theme={null}
```
Change the following fields:
* Replace the 'workspace\_id' in the URL above with the Workspace ID in the MoEngage Dashboard settings. Navigate to Dashboard -> Settings -> App -> General and copy the Workspace ID.
* Replace 'DC' in the URL above with the data center your instance is hosted on. MoEngage hosts each customer in a different data center. Tracked data is stored in the default data center of MoEngage. To find your data center mapping, refer to Data Center Mapping. The possible value is dc\_X where 'X' is your data center number.
For example, if the dashboard URL starts with [https://dashboard-01.moengage.com](https://dashboard-01.moengage.com), and workspace\_id is XXXXXXXXXXXXXXXX, then the prefetch and initiation code would be:
```javascript JavaScript wrap theme={null}
```
# Cache Data Refresh
Web Personalization data will be fetched and stored in the browser cache. The data will be synced again on the Next Page Load only if it meets any of the below conditions:
* 15 minutes have passed since the last data fetch
* Login or Logout is executed
# Web Personalization Anti-Flicker Code
The Anti-Flicker snippet is a small piece of code that helps to maintain the user experience on your website when running a web personalisation experience. [Know more about Flicker](https://help.moengage.com/hc/en-us/articles/24406473752724-Flicker-Management)
Page flickering is a problem that only occurs with experiments on a web page in areas that are visible when the page initially loads. There are certain cases where page flickering may not be an issue, such as experiments occurring below the visible area or experiments that occur after a visitor performs a specific action, such as triggering a Recently Viewed or Added to Cart product grids. In such scenarios, generally, the anti-flicker code need not be added to the website.
## Steps To Install Anti-flicker Code
To prevent page-flickering, there are 2 options
1. Masking the content of the entire page until the personalization is complete **OR**
2. Masking individual elements that have been personalized using the WYSIWYG editor
**Note**
* Only one of approaches - [Option 1](/developer-guide/personalize-sdk/sdk-integration/web-personalization-v2#option-1-masking-content-of-the-entire-webpage) or [Option 2](/developer-guide/personalize-sdk/sdk-integration/web-personalization-v2#option-2-masking-individual-elements-on-the-webpage) - must be implemented on your website.
### Option 1: Masking content of the entire webpage
1. Add the below code as high on the page as possible, in the `` of your website code.
2. In the script below, **MAX\_RENDER\_TIME** refers to the wait time (in milliseconds) before the visitor is shown the original website in case the personalized experience fails to load. You can update this value based on your website performance needs.
```javascript JavaScript wrap theme={null}
```
### Option 2: Masking individual elements on the webpage
This method will only mask specific elements on the webpage that have been personalized. In the script below,
1. Add HTML selector of each personalized element on the webpage to the array **personalizedSelectors.** [How to find HTML selectors for personalized elements?](/developer-guide/personalize-sdk/sdk-integration/web-personalization-v2#option-1-use-the-element’s-html-id)
2. **maxRenderTime** refers to the wait time (in milliseconds) before the visitor is shown the original website in case the personalized experience fails to load. You can update this value based on your website performance needs.
3. Add the below code as high on the page as possible, in the `` section of your website code.
```javascript JavaScript wrap theme={null}
```
An example of multiple elements personalized on a webpage is shown below for reference.
```javascript JavaScript wrap theme={null}
const personalizedSelectors = ['#homepage-title', '#homepage-subtitle', '#homepage-cta', '#homepage-cta-link', '#homepage-banner'];
```
There are 2 ways to find the HTML selector that has been personalized.
#### Option 1: Use the element’s HTML ID
1. Right-click on the element.
2. Select **Inspect** or **Inspect Element** in the context menu.
3. In the highlighted HTML, find the HTML ID for that element. This is how the input would look like for the element highlighted in the image.
\
Below is the input to be given to the anti-flicker snippet for the HTML element in consideration.
```javascript JavaScript wrap theme={null}
const personalizedSelectors = ['#homepage-title'];
```
#### Option 2: Use the element’s HTML selector path
1. Right-click on the element.
2. Select **Inspect Element**in the context menu.
3. In the highlighted HTML, right click and choose **Copy Selector** in the context menu.
\
Below is the input to be given to the anti-flicker snippet for the HTML element in consideration
```javascript JavaScript wrap theme={null}
const personalizedSelectors = ['#side-container > a > img'];
```
# Cards Data Payload
Source: https://moengage.com/docs/developer-guide/react-native-sdk/cards/cards-data-payload
Review the data models and payload structure returned by the MoEngage React Native Cards SDK.
# SyncCompleteData
```typescript TypeScript theme={null}
/**
* Data on API sync complete.
*/
class SyncCompleteData {
/**
* Indicating if there were any updates in the cards post sync. true if there are any new
* updates present else false. This value is true even if card(s) are deleted.
*/
hasUpdates: boolean;
/**
* Condition under which sync was triggered. Refer to {@link SyncType}
*/
syncType: SyncType;
}
```
# CardInfo
```typescript TypeScript theme={null}
/**
* All data for cards.
*/
class CardInfo {
/**
* True if showing ALL tabs is enabled else false.
*/
shouldShowAllTab: boolean;
/**
* All configured categories for cards.
*/
categories: Array;
/**
* All cards which are eligible for display currently.
*/
cards: Array;
/**
* Accessibility data for static images used in cards.
*
* @since 6.0.0
*/
staticImageAccessibilityData: { [key in StaticImageType]: MoEAccessibilityData } | null;
}
```
# Card
```typescript TypeScript theme={null}
/**
* Card data
*/
class Card {
/**
* Internal SDK identifier.
*/
id: number;
/**
* Unique identifier for the campaign
*/
cardId: string;
/**
* Category to which the campaign belongs.
*/
category: string;
/**
* Template payload for the campaign.
*/
template: Template;
/**
* Meta data related to the campaign like status, delivery control etc.
*/
metaData: MetaData;
}
```
# Template
```typescript TypeScript theme={null}
/**
* Card Template data
*/
class Template {
/**
* Type of Template.
*/
templateType: TemplateType;
/**
* Containers in the template.
*/
containers: Array;
/**
* Additional data associated to the template
*/
kvPairs: { [k: string]: any };
}
```
# TemplateType
```typescript TypeScript theme={null}
/**
* Supported template types.
*/
enum TemplateType {
/**
* Basic Template
*/
BASIC,
/**
* Illustration Template
*/
ILLUSTRATION
}
```
# Container
```typescript TypeScript theme={null}
/**
* Container to hold UI widget
*/
class Container {
/**
* Unique identifier for a template
*/
id: number;
/**
* Type of container.
*/
templateType: TemplateType;
/**
* Style associated to the Container
*/
style: ContainerStyle | undefined;
/**
* Widget list associated to the Container
*/
widgets: Array;
/**
* Actions to be performed on widget click
*/
actionList: Array;
}
```
# Widget
```typescript TypeScript theme={null}
/**
* UI element in a card.
*/
class Widget {
/**
* Identifier for the widget.
*/
id: number;
/**
* Type of widget
*/
widgetType: WidgetType;
/**
* Content to be loaded in the widget.
*/
content: string;
/**
* Style associated with the widget
*/
style: WidgetStyle | undefined;
/**
* Actions to be performed on widget click
*/
actionList: Array;
/**
* Accessibility data for the widget
* @since 6.0.0
*/
accessibilityData: MoEAccessibilityData | null;
}
```
# WidgetType
```typescript TypeScript theme={null}
/**
* Types of UI widgets supported.
*/
enum WidgetType {
/**
* Widget that loads an image or gif
*/
IMAGE,
/**
* Widget that loads text content.
*/
TEXT,
/**
* Widget that loads button content.
*/
BUTTON
}
```
# MetaData
```typescript TypeScript theme={null}
/**
* Meta data related to a campaign.
*/
class MetaData {
/**
* True if the campaign should be pinned to the top else false.
*/
isPinned: boolean;
/**
* True if the campaign hasn't been delivered to the inbox, else false.
*/
isNewCard: boolean;
/**
* Current state of the campaign.
*/
campaignState: CampaignState;
/**
* Time at which the campaign would be deleted from local store
*/
deletionTime: number;
/**
* Delivery Controls defined during campaign creation.
*/
displayControl: DisplayControl;
/**
* Additional meta data regarding campaign used for tracking purposes.
*/
metaData: { [k: string]: any };
/**
* Creation time for the campaign.
* Notes: Available in iOS, default value is -1
*/
createdAt: number;
/**
* Last time the campaign was updated.
*/
updatedTime: number;
/**
* Complete Campaign payload.
*/
campaignPayload: { [k: string]: any };
}
```
# CardsData
```typescript TypeScript theme={null}
/**
* Data for cards
*/
class CardsData {
/**
* Category for the cards
*/
category: string;
/**
* [List] of [Card]
*/
cards: Array;
/**
* Accessibility data for static images used in cards.
*
* @since 6.0.0
*/
staticImageAccessibilityData: { [key in StaticImageType]: MoEAccessibilityData } | null;
}
```
# SyncType
```typescript TypeScript theme={null}
/**
* Condition/Situation when sync
*/
enum SyncType {
/**
* Sync when application comes to foreground
*/
APP_OPEN,
/**
* Sync when inbox screen opened.
*/
INBOX_OPEN,
/**
* Sync when SwipeToRefresh widget is pulled.
*/
PULL_TO_REFRESH
/**
* Sync when user logs in
* @since 5.0.0
*/
IMMEDIATE
}
```
# StaticImageType
```typescript TypeScript theme={null}
/**
* Enum representing different types of static images used in the cards.
*
* @since 6.0.0
*/
enum StaticImageType {
/**
* Image for No cards/Empty State
*/
EMPTY_STATE
/**
* Pin Card image
*/
PIN_CARD
/**
* Place Holder image for card loading
*/
LOADING_PLACE_HOLDER
}
```
# AccessibilityData
```typescript TypeScript theme={null}
/// @since 12.0.0 of react-native-moengage package
class MoEAccessibilityData {
/// The accessibility text
text: string | null;
/// The accessibility hint
hint: string | null;
}
```
# Framework Initialization
Source: https://moengage.com/docs/developer-guide/react-native-sdk/cards/initialization/framework-initialization
Initialize the MoEngage Cards plugin in your React Native app after the component mounts.
# Cards Plugin Initialization
Initialize the Cards plugin after the component is mounted.
```typescript TypeScript theme={null}
import ReactMoEngageCards from "react-native-moengage-cards";
ReactMoEngageCards.initialize(YOUR_Workspace_ID);
```
There is no platform-specific initialization required.
# Android
Source: https://moengage.com/docs/developer-guide/react-native-sdk/cards/installation/android
Configure Android dependencies for the MoEngage React Native Cards plugin in your project.
In the ***react-native-moengage-cards*** version 10.x.x, the native dependency is part of the Cards plugin itself, so there is no need to include any additional dependency for supporting Cards.
# Framework Dependency
Source: https://moengage.com/docs/developer-guide/react-native-sdk/cards/installation/framework-dependency
Install the MoEngage Cards plugin for React Native using the npm package manager.
Install MoEngage's Cards Plugin to your application, using the npm package manager.

```shell Shell theme={null}
$ npm install react-native-moengage-cards
```
After installing the plugin, use the following platform-specific configuration.
* [Android](/developer-guide/react-native-sdk/cards/installation/android)
* [iOS](/developer-guide/react-native-sdk/cards/installation/ios)
This plugin is dependent on `react-native-moengage` plugin. Make sure you have installed the `react-native-moengage` plugin as well. Refer to the [documentation](/developer-guide/react-native-sdk/sdk-integration/react-native/sdk-installation/framework-dependency) for the same.
# iOS
Source: https://moengage.com/docs/developer-guide/react-native-sdk/cards/installation/ios
Set up iOS dependencies for the MoEngage React Native Cards plugin with architecture support.
We now offer support for turbo architecture starting from version 3.0.0.
To run the application in the new react architecture, follow these steps:
1. Navigate to the iOS folder.
2. Run the command ***RCT\_NEW\_ARCH\_ENABLED=1 bundle exec pod install*** to install the necessary dependencies.
To run the application in the old react architecture, follow these steps:
1. Navigate to the iOS folder.
2. Run the command ***pod install*** to install the necessary dependencies.
# Self Handled Cards
Source: https://moengage.com/docs/developer-guide/react-native-sdk/cards/self-handled-cards
Build custom card views in your React Native app using the MoEngage self-handled cards SDK and APIs.
Self-handled cards give you the flexibility of creating Card Campaigns on the MoEngage Platform and displaying the cards anywhere inside the application. SDK provides APIs to fetch the campaign's data using which you can create your own view for cards.
# Get Cards Info
Fetch All the cards campaign data that are eligible to show for the particular user which returns data as ***CardsInfo***.
```typescript TypeScript theme={null}
import ReactMoEngageCards from "react-native-moengage-cards";
const cardsInfo = await ReactMoEngageCards.getCardsInfo();
```
Refer to the [Cards Data Payload](https://developers.moengage.com/hc/en-us/articles/18393678207380-Cards-Data-Payload) to get the details about the available data in ***CardsInfo***.
## Widget and Widget ID Mapping
### Basic Card/Illustration Card
| Widget Id | Widget Type | Widget Information |
| --------- | -------------------------- | --------------------------------- |
| 0 | Image (WidgetType.IMAGE) | Image widget in the card. |
| 1 | Text (WidgetType.TEXT) | Header text for the card. |
| 2 | Text (WidgetType.TEXT) | Message text for the card. |
| 3 | Button (WidgetType.Button) | Call to action(CTA) for the card. |
# Refresh Cards
Use the ***refreshCards***\*()\*\*\* API to refresh cards on the User Demand. This API can be used to mimic Pull to refresh behavior.
```typescript TypeScript theme={null}
import ReactMoEngageCards from "react-native-moengage-cards";
ReactMoEngageCards.refreshCards((data) => {});
```
Refer to the [Cards Data Payload](https://developers.moengage.com/hc/en-us/articles/18393678207380-Cards-Data-Payload)to get the detail about the available data in ***SyncCompleteData**.*
# Fetch Cards
Use the ***fetchCards***\*()\*\*\* API to fetch cards for the User. This API can be used to sync the latest cards data.
```typescript TypeScript theme={null}
import ReactMoEngageCards from "react-native-moengage-cards";
const cardsData = await ReactMoEngageCards.fetchCards();
```
Refer to the [Cards Data Payload](https://developers.moengage.com/hc/en-us/articles/18393678207380-Cards-Data-Payload)to get the details about the available data in ***CardsData**.*
# Inbox Loaded
You can show the cards on a separate screen or a section of the screen. When the cards screen/section is loaded call ***onCardSectionLoaded()***.
```typescript TypeScript theme={null}
import ReactMoEngageCards from "react-native-moengage-cards";
ReactMoEngageCards.onCardSectionLoaded((data) => {});
```
Refer to the [Cards Data Payload](https://developers.moengage.com/hc/en-us/articles/18393678207380-Cards-Data-Payload)to get the details about the available data in ***SyncCompleteData**.*
# Inbox UnLoaded
Call ***onCardSectionUnloaded()*** when the screen/section is no longer visible or going to the background.
```typescript TypeScript theme={null}
import ReactMoEngageCards from "react-native-moengage-cards";
ReactMoEngageCards.onCardSectionUnLoaded();
```
# Fetch Categories
To fetch all the categories for which cards are configured, use the***getCardsCategories()*** API. It will return an array of strings.
```typescript TypeScript theme={null}
import ReactMoEngageCards from "react-native-moengage-cards";
const cardsCategories = await ReactMoEngageCards.getCardsCategories();
```
# All Cards Categories Enabled
To fetch all the categories for which cards are configured, use the***isAllCategoryEnabled()*** API.
```typescript TypeScript theme={null}
import ReactMoEngageCards from "react-native-moengage-cards";
const isAllCategoryEnabled = await ReactMoEngageCards.isAllCategoryEnabled();
```
# Fetch Cards for Categories
To fetch cards eligible for display for a specific category use the ***getCardsForCategory()*** API.
```typescript TypeScript theme={null}
import ReactMoEngageCards from "react-native-moengage-cards";
const cardsData = await ReactMoEngageCards.getCardsForCategory(cardCategory);
```
Refer to the [Cards Data Payload](https://developers.moengage.com/hc/en-us/articles/18393678207380-Cards-Data-Payload)to get the details about the available data in ***CardsData**.*
# Get New Cards Count
To obtain the new cards count use \*\*\*getNewCardsCount()\*\*\*method as shown below:
```typescript TypeScript theme={null}
import ReactMoEngageCards from "react-native-moengage-cards";
const newCardsCount = await ReactMoEngageCards.getNewCardsCount();
```
# Card Shown
Call the ***cardShown()*** API to notify a card is shown to the user.
```typescript TypeScript theme={null}
import ReactMoEngageCards from "react-native-moengage-cards";
ReactMoEngageCards.cardShown(card);
```
# Card Clicked
Call the ***cardClicked()*** API to notify a card is shown to the user.
```typescript TypeScript theme={null}
import ReactMoEngageCards from "react-native-moengage-cards";
ReactMoEngageCards.cardClicked(card, widgetId);
```
# Delete Card
Call the ***deleteCard()*** API to delete a card.
```typescript TypeScript theme={null}
import ReactMoEngageCards from "react-native-moengage-cards";
// Delete a single card
ReactMoEngageCards.deleteCard(card);
// Delete a multiple card, pass the Array
ReactMoEngageCards.deleteCard(cards);
```
# Mark Card Delivered
To track delivery to the card section of the application call the ***cardDelivered()*** API when the cards section of the application is loaded.
```typescript TypeScript theme={null}
import ReactMoEngageCards from "react-native-moengage-cards";
ReactMoEngageCards.cardDelivered();
```
# Get Unclicked Cards Count
To obtain the unclicked cards count use \*\*\*getUnClickedCardsCount()\*\*\*method as shown below.
```typescript TypeScript theme={null}
import ReactMoEngageCards from "react-native-moengage-cards";
const unClickedCard = await ReactMoEngageCards.getUnClickedCardsCount();
```
# Card Sync Listener
## Version 4.0.0 and below.
Set this listener to get a callback for card sync on the App opened. This listener should be set before calling \*\*\*initialize()\*\*\*API. In most cases, this API is not required.
```typescript TypeScript theme={null}
import ReactMoEngageCards from "react-native-moengage-cards";
ReactMoEngageCards.setAppOpenSyncListener((data) => {});
```
## Version 5.0.0 and above.
Set this listener to receive a callback for card sync upon app launch or when user login.This listener should be set before calling \*\*\*initialize()\*\*\*API.
```typescript TypeScript theme={null}
import ReactMoEngageCards from "react-native-moengage-cards";
ReactMoEngageCards.setSyncCompleteListener((data) => {});
```
Refer to the [Cards Data Payload](https://developers.moengage.com/hc/en-us/articles/18393678207380-Cards-Data-Payload)to get the details about the available data in ***SyncCompleteData**.*
# Delete User From MoEngage Server
Source: https://moengage.com/docs/developer-guide/react-native-sdk/data-tracking/delete-user-from-moengage-server
Delete the current user from the MoEngage server using the React Native SDK on Android.
This API is supported from **react-native-moengage** version **8.6.0** and is only available for the Android platform and is a no-operation for other platforms.
To delete the current user from the MoEngage server use ***deleteUser()*** method as shown below, where you will get an instance of ***UserDeletionData***.
```javascript TypeScript theme={null}
import ReactMoE from 'react-native-moengage';
// Below method will return an instance of UserDeletionData
const userDeletionData = await ReactMoE.deleteUser();
```
## UserDeletionData
Below is the model returned on calling the API/method.
```typescript TypeScript theme={null}
/**
* Delete User State Data while deleting the user from MoEngage SDK
* @since 8.6.0
*/
class UserDeletionData {
/**
* Account Data, instance of { MoEAccountMeta }
* @since 8.6.0
*/
accountMeta: MoEAccountMeta;
/**
* User State, true if user delete succeeded else false
* @since 8.6.0
*/
isSuccess: boolean;
}
```
# Enable Advertising Identifier Tracking
Source: https://moengage.com/docs/developer-guide/react-native-sdk/data-tracking/enable-advertising-identifier-tracking
Enable advertising identifier tracking in your React Native app for accurate device analytics.
For accurate analytics around devices and tracking Re-installs, it is essential to track the Advertising Identifier.
## Add Ad Identifier Library
Add the below dependency in the application level ***build.gradle*** file.
```groovy Groovy theme={null}
implementation("com.google.android.gms:play-services-ads-identifier:18.0.1")
```
To enable Advertising Identifier tracking use the *enableAdIdTracking()* method as shown below.
```javascript Javascript theme={null}
import ReactMoE from 'react-native-moengage'
ReactMoE.enableAdIdTracking();
```
Before you enable Advertising Id tracking please ensure the application is complying with the [Google Play Policy](https://support.google.com/googleplay/android-developer/answer/10144311) regarding Advertising Id tracking. Refer to our [help document](https://help.moengage.com/hc/en-us/articles/7457641031828) for more information on the policy.
In case, you need to disable advertising-id after enabling tracking use the following method.
```javascript Javascript theme={null}
import ReactMoE from 'react-native-moengage'
ReactMoE.disableAdIdTracking();
```
The above APIs are available only starting plugin version 7.4.1. In the older versions, Advertising Identifier tracking is enabled by default.
# Install/Update
Source: https://moengage.com/docs/developer-guide/react-native-sdk/data-tracking/install-update
Differentiate between app installs and updates in your React Native app using MoEngage setAppStatus.
During integration if your app is already on the App Store, MoEngage would need to know whether your app update would be an actual UPDATE or an INSTALL.
Have logic in place to differentiate Install and Update and make use of the `setAppStatus()` method to track the same as described:
```javascript JavaScript theme={null}
import ReactMoE, {
MoEAppStatus,
} from "react-native-moengage";
//For Fresh Install of App
ReactMoE.setAppStatus(MoEAppStatus.Install);
// For Existing user who has updated the app
ReactMoE.setAppStatus(MoEAppStatus.Update);
```
# Setting Unique Id for SDK versions below 11.2.0
Source: https://moengage.com/docs/developer-guide/react-native-sdk/data-tracking/setting-unique-id-for-sdk-versions-below-1120
Set a unique user ID for login and logout in React Native SDK versions below 11.2.0.
# Implementing Login/Logout
* It's important to set the User Attribute Unique ID when a user logs into your app.
* This is to merge the new user with existing user, if any exists, and will help prevent creating of unnecessary/stale users.
* Setting the Unique ID is a critical piece to tie a user across devices and installs/uninstalls as well across all platforms (i.e. iOS, Android, Windows, The Web). Set the **USER\_ATTRIBUTE\_UNIQUE\_ID** attribute as soon as the user is **logged in**. Unique ID can be something like an email ID, a username (unique), or a database ID or any Backend generated ID.
* Do not set this for the user who not logged in.
## Login User
```javascript JavaScript theme={null}
import ReactMoE from 'react-native-moengage'
ReactMoE.setUserUniqueID("abc@xyz.com");
```
## Logout User
The application needs to notify the MoEngage SDK whenever the user is logged out of the application. To notify the SDK, call the API whenever the user is logged out of the application.
```javascript JavaScript theme={null}
import ReactMoE from 'react-native-moengage'
ReactMoE.logout();
```
## Updating User Attribute Unique Id
Use the method ***setAlias()*** to update the user attribute unique id instead of \*setUniqueId()\*with a different value. Using the method ***setUniqueId()*** with a new value creates unintended users in MoEngage.
```JavaScript JavaScript theme={null}
import ReactMoE from 'react-native-moengage'
ReactMoE.setAlias("asd@xyz.com");
```
# Tracking Events
Source: https://moengage.com/docs/developer-guide/react-native-sdk/data-tracking/tracking-events
Track user events and their properties using the MoEngage React Native SDK for campaigns.
SDK adheres to the MoEngage FUP policies. For more information, refer to the [Fair Usage Policy](https://help.moengage.com/hc/en-us/articles/24151864954644-Fair-Usage-Policy-FUP#h_01HQSMZVQWT2KYP0PY1P8GQMRM).
Tracking events is how you record any actions your users perform, along with any properties that describe the action. Every trackEvent call records a single user action. We recommend that you make your event names human-readable so that everyone on your team can know what they mean instantly.
Every ***trackEvent()*** API expects 2 parameters, event name, and event attributes i.e. instance of ***MoEProperties.***
Add all the additional information which you think would be useful for segmentation while creating campaigns.
For example, the following code tracks a Purchase event of a product. We are including attributes like price, quantity, purchase date, and store location which describe the event we are tracking.
```javascript JavaScript theme={null}
import ReactMoE, {
MoEGeoLocation,
MoEProperties,
} from "react-native-moengage";
let properties = new MoEProperties();
properties.addAttribute("quantity", 1);
properties.addAttribute("product", "iPhone");
properties.addAttribute("currency", "dollar");
properties.addAttribute("price", 699);
properties.addAttribute("new_item", true);
properties.addAttribute("models", ["iPhone15", "iPhone14"]);
properties.addDateAttribute("purchase_date", "2020-06-10T12:42:10Z");
properties.addLocationAttribute(
"store_location",
new MoEGeoLocation(90.00001, 180.00001)
);
ReactMoE.trackEvent("Purchase", properties);
```
* Event names should not contain any special characters other than "\_". It can contain just spaces and an underscore. Also, it should not contain “between”, “greater”, “less”, “in\_the\_last”, “in\_the\_next”, “equal”, “contains”, “starts”, or “is\_not".
* You can not use "moe\_" as a prefix while naming events, event attributes, or user attributes. It is a system prefix and using it might result in periodic blacklisting without prior communication.
* You can not use "user\_id" to name custom attributes. It is a reserved system field, and using it might result in an error.
# Analytics
MoEngage SDK tracks user sessions and application traffic sources. Refer to the [Sessions in MoEngage Analytics](https://help.moengage.com/hc/en-us/articles/35724347745812-Session-and-Source-Overview) and [Source Analysis in MoEngage Analytics](https://help.moengage.com/hc/en-us/articles/35724347745812-Session-and-Source-Overview)to learn more about how user session and application traffic source tracking works.
With user session tracking we have introduced the flexibility to selectively mark events as non-interactive.
## What is a non-interactive event?
Events that do not affect the session calculation in anyways are called non-interactive events. Non-interactive events have the below properties
* Do not start a new session.
* Do not extend the session.
* Do not have information related to a user session.
## How to mark an event as non-interactive?
To mark an event as a non-interactive call ***setNonInteractive()*** of the ***MoEProperties***instance as shown below:
```javascript JavaScript theme={null}
import ReactMoE, {
MoEGeoLocation,
MoEProperties,
} from "react-native-moengage";
let properties = new MoEProperties();
properties.addAttribute("quantity", 1);
properties.addAttribute("product", "iPhone");
properties.addAttribute("currency", "dollar");
properties.addAttribute("price", 699);
properties.addAttribute("new_item", true);
properties.addAttribute("models", ["iPhone15", "iPhone14"]);
properties.addDateAttribute("purchase_date", "2020-06-10T12:42:10Z");
properties.addLocationAttribute(
"store_location",
new MoEGeoLocation(90.00001, 180.00001)
);
//Marking it as Non Interactive
properties.setNonInteractiveEvent();
ReactMoE.trackEvent("Purchase", properties);
```
# Tracking User Attributes and User Identity
Source: https://moengage.com/docs/developer-guide/react-native-sdk/data-tracking/tracking-user-attributes-and-user-identity
Track user attributes and set identifiers for identity resolution in the React Native SDK.
User attributes are pieces of information you know about a user. They could be demographics such as age and gender, account-specific like plan, or whether a user has seen a particular A/B test variation. User attributes are customer properties you can reference throughout the customer's lifecycle.
## Difference Between User Attributes and User Identifiers
User attributes and user identifiers serve different purposes in MoEngage:
**User Identifiers:**
User identifiers are unique values that persist across multiple sessions and devices, allowing MoEngage to recognise a user as the same individual, even when they switch between different platforms or log in later. This process, known as identity resolution, is crucial for maintaining a unified user profile, providing a consistent user experience, and tracking user behaviour accurately.
Common examples of user identifiers include:
* Email address: A user's email address is a widely used identifier because it is unique to the individual and remains consistent across different platforms.
* Phone number: Similar to email addresses, phone numbers can serve as unique identifiers, especially in mobile applications.
* User ID: MoEngage assigns each user a unique ID upon registration. This ID is used as a reliable identifier within the MoEngage platform.
* Customer ID: In e-commerce and customer relationship management (CRM) systems, a customer ID is assigned to track individual customers across various interactions.
These identifiers are set using the ***identifyUser()*** method.
By default, parameter ***ID*** is the identifier used for your workspaces, unless [Identity resolution](https://help.moengage.com/hc/en-us/articles/24050999467284-User-Identity-Resolution#h_01HQK9NXP3J3SHZJTEH95J89AC) is enabled and identifiers are activated in your workspace.
**User Attributes**:
Descriptive information about a user that enhances their profile - Used for segmentation, personalisation, and analytics - Examples: name, age, gender, preferences, purchase history - Set using dedicated methods like ***setFirstName()*** or ***setUserAttribute()*** - Help create personalised user experiences
In simple terms, identifiers answer "Who is this user?" while attributes answer "What do we know about this user?"
## Powering MoEngage Features
User attributes and identifiers are crucial for leveraging MoEngage effectively:
* **Segmentation:**
* Use attributes to create targeted user groups based on demographics, behavior, etc.
* Example: Segment users by age, purchase history for specific campaigns.
* **Personalisation:**
* Identifiers ensure consistent user experience across devices.
* Attributes enable tailored content (messages, recommendations).
* Example: Personalise emails with names, recommend relevant products.
* **Analytics:**
* Attributes provide context to user actions and behavior data.
* Analyze conversion rates by segments, feature engagement by demographics.
* Gain deeper insights for data-driven decisions.
By using attributes and identifiers, you can build more relevant and engaging user experiences.
# Implementing Login/Logout
For SDK versions below 11.2.00 refer to this document.
## Login User
**Single Identifier**
If your application relies on a single unique user identifier, such as an email ID for login, use the API below to pass the identifier to the MoEngage SDK
```javascript JavaScript theme={null}
import ReactMoE from 'react-native-moengage';
ReactMoE.identifyUser("abc@xyz.com"); //Pass any unique value for your user
```
**Note**: If a key is not specified, the SDK defaults to `uid`, the unique user identifier in MoEngage.
**Multiple Identifiers**
If your application supports multiple login identifiers, such as an email ID, user ID, or mobile number, pass all relevant identifiers to the SDK using the following function:
```javascript JavaScript theme={null}
import ReactMoE from 'react-native-moengage'
ReactMoE.identifyUser({"uid": "react-native","u_em": "react-native@moengage.com"});
```
Updates are made to SDK functions to improve user identification and session management.
* **Forced Logout**: The MoEngage SDK no longer automatically logs out the previous user when a new user is detected on the device. Logout should now be explicitly called for workspaces enabled with Identity resolution to avoid data corruption.
* **SetUniqueID**: *IdentifyUser* function supports multiple identifiers, which replaces the need of using *SetUniqueID* function for user identification. Note that *SetUniqueID* is marked for removal in the future releases of SDK versions - it is important to use *identifyUser* instead especially if you are using Identity resolution in your workspace.
* **SetAlias**: For workspaces with the Identity resolution feature enabled, MoEngage SDK stores the previous identifier values. When *IdentifyUser* function is used to track the new identifier values, MoEngage SDK detects the change in identifier value and reports accordingly.
* If you call the *IdentifyUser* function without logging out, then the existing logged-in user's ID is updated.
**Note**: Before implementing ***identifyUser()*** with multiple identifiers, you must activate the defined identifiers on the MoEngage dashboard. For configuration steps, see [this documentation](https://help.moengage.com/hc/en-us/articles/24050999467284-User-Identity-Resolution#h_01JK58XBFD66QA3W4JJNYVBD01).
***Behaviour of Multiple identifyUser() calls***
* When calling ***identifyUser()*** multiple times, the new identifiers are appended to the existing list rather than replacing them. Here's an example of how this works:
```javascript JavaScript theme={null}
import ReactMoE from 'react-native-moengage';
//First call with email
ReactMoE.identifyUser({"u_em":"abc@xyz.com"});
//Later call identifyUser() with mobile Number
ReactMoE.identifyUser({"u_mb":"999999999"});
//Result now the user has both email and mobile identifiers;
```
* If you call ***identifyUser()*** with an identifier key that already exists, the new value will be update the existing one. Here's an example of how this works:
```javascript JavaScript theme={null}
import ReactMoE from 'react-native-moengage';
//First call with initial email
ReactMoE.identifyUser({"u_em":"abc@xyz.com"});
//Later call identifyUser() when User updates their email
ReactMoE.identifyUser({"u_em":"jfk@xyz.com"});
//Result now the user email is updated with the later one;
```
This behaviour allows you to:
* Add new identifiers as they become available
* Update specific identifiers without affecting others
* Build a complete user identity profile over time
Here, `u_em`, `u_mb` are standard user attributes. Please refer to [this section](/developer-guide/react-native-sdk/data-tracking/tracking-user-attributes-and-user-identity) to identify user with more standard user attributes
## Standard and Custom Attributes
**Standard attributes:** These are common user attributes that are pre-defined within the MoEngage dashboard, such as email address and mobile phone number. The table below lists these standard attributes and their corresponding key names
| User Attribute Name | Key name to be used in identifyUser method |
| ------------------------ | ------------------------------------------ |
| ID | uid |
| Email (Standard) | u\_em |
| Gender | u\_gd |
| Birthday | u\_bd |
| Name | u\_n |
| First Name | u\_fn |
| Last Name | u\_ln |
| Mobile Number (Standard) | u\_mb |
**Custom attributes:** These are attributes that you define yourself within the MoEngage dashboard in addition to the standard attributes. Here's an example of how you might work with custom attributes:
```javascript JavaScript theme={null}
import ReactMoE from 'react-native-moengage';
//replace custom_attribute_name with the actual name of your custom user attribute and attributeValue with the actual value you want to assign to the attribute
ReactMoE.identifyUser({ custom_attribute_name: 'attributeValue' });
//you can set two or more identities at the same time
ReactMoE.identifyUser({ cust_attr_1: 'value1', cust_attr_2: 'value2' });
//you can set custom user identity and standard user identity at the same time
ReactMoE.identifyUser({ cust_attr_1: 'value1', cust_attr_2: 'value2', u_em: 'emailValue@emailDomain.com' });
```
For detailed instructions on selecting both custom and standard attributes when configuring multiple identifiers, please refer to [this document](https://help.moengage.com/hc/en-us/articles/24050999467284-User-Identity-Resolution#h_01JMESGEFWSXRECFMTN7V31Q7C).
## Logout User
```javascript JavaScript theme={null}
import ReactMoE from 'react-native-moengage';
ReactMoE.logout();
```
**Critical - Very Important Integration Guideline**
Never use both the login methods - `identifyUser` and `setUserUniqueID()`(method to assign identifier present in versions below 11.2.0) in your project. Use only either one of the methods. Using both the methods can lead to inconsistent user profile creation and merging in your MoEngage account.
# Tracking User Attributes
Use the following helper methods to set User attributes like Name, Email, Mobile, Gender, etc.
```javascript JavaScript theme={null}
import ReactMoE, {
MoEGeoLocation,
} from "react-native-moengage";
ReactMoE.setUserName("abc");
ReactMoE.setUserFirstName("abc");
ReactMoE.setUserLastName("xyz");
ReactMoE.setUserEmailID("abc@xyz.com");
ReactMoE.setUserContactNumber(1234567890);
ReactMoE.setUserGender("Male"); // OR Female
// Format - ISO-8601 String
ReactMoE.setUserBirthday("1970-01-01T12:00:00Z");
// For Location use MoEGeoLocation instance
ReactMoE.setUserLocation(new MoEGeoLocation(77.3201, -77.3201));
// For array of integers
ReactMoE.setUserAttribute("arrayOfInt",[1,2,3]);
// For array of strings
ReactMoE.setUserAttribute("arrayOfString",['sample1','sample2','sample3']);
```
For setting other User Attributes you can use the generic method ***setUserAttribute(key,value)***
To set custom user attributes, you will have to provide the attribute name as shown below:
```javascript JavaScript theme={null}
import ReactMoE, {
MoEGeoLocation,
} from "react-native-moengage";
ReactMoE.setUserAttribute("attribute name", "attribute value");
// For Time attribute use ISO-8601 format
ReactMoE.setUserAttributeISODateString(
"time attribute name",
new Date().toISOString()
);
// For Location, use MoEGeoLocation instance
ReactMoE.setUserAttributeLocation(
"location attribute name",
new MoEGeoLocation(10.3223, -88.6026)
);
```
You can not use "moe\_" as a prefix while naming events, event attributes, or user attributes. It is a system prefix and using it might result in periodic blacklisting without prior communication.
## Custom Boolean User Attribute
### iOS (optional)
Starting from version 11.x.x of react-native-moengage, the default tracking for the custom boolean attribute will be changed to ***boolean(true/false)*** from ***double(0/1***). To configure this, use ***MoEAnalyticsConfig*** and pass true to track the boolean as double. By default, this is set as **false** to track the boolean as true/false.
Refer to the initialisation code snippet below.
```java JavaScript theme={null}
import ReactMoE from 'react-native-moengage';
import { MoEInitConfig, MoEPushConfig, MoEngageLogConfig, MoEngageLogLevel } from "react-native-moengage";
const moEInitConfig = new MoEInitConfig(
MoEPushConfig.defaultConfig(),
new MoEngageLogConfig(MoEngageLogLevel.DEBUG, isEnabledForReleaseBuild),
new MoEAnalyticsConfig(true)
);
ReactMoE.initialize(YOUR Workspace ID, moEInitConfig);
```
Refer to the example code below for tracking the boolean user attribute
```javascript JavaScript theme={null}
import ReactMoE, {
MoEGeoLocation,
} from “react-native-moengage”;
// If MoEAnalyticsConfig is passed as true then `boolean attribute True` will tracked with value 1 else true
ReactMoE.setUserAttribute("boolean attribute True", true);
// If MoEAnalyticsConfig is passed as true then `boolean attribute False` will tracked with value 0 else false
ReactMoE.setUserAttribute("boolean attribute False", false);
```
## Reserved keywords for User Attributes
Below is the list of keys that should not be used when tracking user attributes.
* USER\_ATTRIBUTE\_UNIQUE\_ID
* USER\_ATTRIBUTE\_USER\_EMAIL
* USER\_ATTRIBUTE\_USER\_MOBILE
* USER\_ATTRIBUTE\_USER\_NAME
* USER\_ATTRIBUTE\_USER\_GENDER
* USER\_ATTRIBUTE\_USER\_FIRST\_NAME
* USER\_ATTRIBUTE\_USER\_LAST\_NAME
* USER\_ATTRIBUTE\_USER\_BDAY
* USER\_ATTRIBUTE\_NOTIFICATION\_PREF
* USER\_ATTRIBUTE\_OLD\_ID
* MOE\_TIME\_FORMAT
* MOE\_TIME\_TIMEZONE
* USER\_ATTRIBUTE\_DND\_START\_TIME
* USER\_ATTRIBUTE\_DND\_END\_TIME
* MOE\_GAID
* MOE\_ISLAT
* INSTALL
* UPDATE
* status
* user\_id
You can not use "moe\_" as a prefix while naming events, event attributes, or user attributes. It is a system prefix and using it might result in periodic blacklisting without prior communication.
# InApp NATIV
Source: https://moengage.com/docs/developer-guide/react-native-sdk/in-app-messages/inapp-nativ
Configure and display in-app messages in your React Native app using the MoEngage SDK.
In-App Messaging is custom views that you can send to a segment of users to show custom messages or give new offers or take to some specific pages. They can be created from your MoEngage account.
## Installing Android Dependency
### Requirements for displaying images and GIFs in InApp
Starting InApp version **7.0.0,** SDK requires [Glide](https://bumptech.github.io/glide/) to show images and GIFs in the in-apps. You need to add the below dependency in ***android/app/build.gradle*** file.
```gradle Groovy theme={null}
dependencies {
...
implementation("com.github.bumptech.glide:glide:4.9.0")
}
```
# Display In-App
Call the `showInApp()` wherever InApp has to be shown in the app as shown below :
```javascript JavaScript theme={null}
import ReactMoE from 'react-native-moengage'
ReactMoE.showInApp()
```
# Display Nudges
Starting with ***react-native-moengage*** version **9**\*\*.0.0,\*\*MoEngage InApp SDK supports displaying Non-Intrusive nudges.
To show a Nudge InApp Campaign call `showNudge()`
```javascript JavaScript theme={null}
import { ReactMoE, MoEngageNudgePosition } from "react-native-moengage";
ReactMoE.showNudge() // Display Nudge on any available position
ReactMoE.showNudge(MoEngageNudgePosition._NUDGE_POSITION) // Display Nudge on the specific position
```
# InApp/Nudge Redirection default behavior
On clicking an Inapp or Nudge, MoEngage SDKs will handle **only rich landing navigation** redirection.
For the screen name and deep link redirection, your app code should redirect the user to the right screen or deep link. To handle the screen name and deep link redirection, you must implement inapp click callback methods. MoEngage SDK will just pass the inapp payload to this call back code. Implementation steps are mentioned in the InApp callback section of the Integration.
# Self-Handled InApps
Self-handled In Apps are messages that the SDK delivers, but displaying them has to be handled by the app.
## Single Self-Handled InApps
To get self-handled In-App call the below method.
```javascript JavaScript theme={null}
import ReactMoE from 'react-native-moengage'
ReactMoE.getSelfHandledInApp();
```
The payload for self-handled in-app is returned via a callback. Register a callback as shown below.
```javascript JavaScript theme={null}
import ReactMoE from 'react-native-moengage'/// selfHandledCampaignData is of type MoESelfHandledCampaignData
ReactMoE.setEventListener("inAppCampaignSelfHandled", (selfHandledPayload) => {
if (selfHandledCampaignData && Object.keys(selfHandledPayload).length != 0) {
console.log("inAppCampaignSelfHandled", selfHandledCampaignData);
}
});
```
## Multiple Self-Handled InApps
* This feature is supported from version ***11.1.0*** of the plugin.
Fetch Multiple Self Handled Campaigns using *getSelfHandledInApps()*.
```javascript JavaScript theme={null}
import ReactMoE from 'react-native-moengage'
/// selfHandledCampaignsData is of type MoESelfHandledCampaignsData, which contains
/// a list of MoESelfHandledCampaignData data objects
var selfHandledCampaignsData = await ReactMoE.getSelfHandledInApps();
```
### Tracking Statistics for Multiple Self-Handled In-Apps
The *getSelfHandledInApps()* method returns [*MoESelfHandledCampaignsData*](/developer-guide/react-native-sdk/in-app-messages/inapp-nativ)\*\*,\*\*which contains a list of [*MoESelfHandledCampaignData*](/developer-guide/react-native-sdk/in-app-messages/inapp-nativ) objects. The statistics for each [*MoESelfHandledCampaignData*](/developer-guide/react-native-sdk/in-app-messages/inapp-nativ) object must be tracked individually below APIs.
### Fetching Contextual Multiple Self-Handled InApps
To fetch contextual multiple self-handled inapps, set the inapp contexts using *setCurrentContext(*)before calling \*getSelfHandledInApps().\*This will return a list of contextual and non-contextual inapps(in the order of campaign priority set at the time of campaign creation).
# Tracking Statistics
Since display, click, and dismiss for Self-Handled InApp are controlled by the application we need you to notify the SDK whenever the In-App is *Shown*, *Clicked*, or *Dismissed*. Below are the methods you need to call to notify the SDK. The campaign object which is an instance of the *MoESelfHandledCampaignData* object provided to the application in the callback for self-handled in-app should be passed in as a parameter to the below APIs.
```javascript JavaScript theme={null}
import ReactMoE from 'react-native-moengage'
ReactMoE.selfHandledShown(selfHandledCampaignData);
ReactMoE.selfHandledClicked(selfHandledCampaignData);
ReactMoE.selfHandledDismissed(selfHandledCampaignData);
```
# InApp Callbacks
The callbacks must be registered before inapps are displayed either via show methods or triggered events. And make sure you are calling `initialize()` the method of the plugin after you set up these callbacks. Refer [doc](/developer-guide/react-native-sdk/sdk-integration/react-native/sdk-initialization/manual-initialization/framework-initialization) for more info.
We provide callbacks whenever an InApp campaign is shown, dismissed, or clicked you can register for the same as shown below.
```javascript JavaScript theme={null}
import ReactMoE from 'react-native-moengage'
///inAppInfo is of type MoEInAppData
ReactMoE.setEventListener("inAppCampaignShown", (inAppInfo) =>
console.log("inAppCampaignShown", inAppInfo)
);
///inAppInfo is of type MoEClickData
ReactMoE.setEventListener("inAppCampaignClicked", (inAppInfo) =>
console.log("inAppCampaignClicked", inAppInfo)
);
///inAppInfo is of type MoEInAppData
ReactMoE.setEventListener("inAppCampaignDismissed", (inAppInfo) =>
console.log("inAppCampaignDismissed", inAppInfo)
);
///inAppInfo is of type MoEClickData
ReactMoE.setEventListener("inAppCampaignCustomAction", (inAppInfo) =>
console.log("inAppCampaignCustomAction", inAppInfo)
);
```
| Event Type | Event Name |
| -------------------------------- | ------------------------- |
| InApp Shown | inAppCampaignShown |
| InApp Clicked | inAppCampaignClicked |
| InApp Dismissed | inAppCampaignDismissed |
| InApp Clicked with Custom Action | inAppCampaignCustomAction |
# Contextual InApp
You can restrict the in-apps based on the user's context in the application apart from restricting InApp campaigns on a specific screen/activity. To set the user's context in the application use *setCurrentContext()* API as shown below.
## Set Context
Call the below method to set the context, before calling *showInApp().*
```javascript JavaScript theme={null}
import ReactMoE from 'react-native-moengage'// replace array elements with actual values.
ReactMoE.setCurrentContext(['c1', 'c2', 'ce'])
```
## Reset Context
Once the user is moving out of the context use the *resetCurrentContext()* API to reset/clear the existing context.
```javascript JavaScript theme={null}
import ReactMoE from 'react-native-moengage'
ReactMoE.resetCurrentContext();
```
For more information on Contextual InApp, refer to the video tutorial available in [Troubleshooting and FAQs](/developer-guide/android-sdk/troubleshooting-and-faqs/troubleshooting-and-faqs#how-to-use-contextual-inapps-in-react-nativ).
# Payload Structure
```typescript TypeScript theme={null}
class MoEInAppData {
/// account information
accountMeta: MoEAccountMeta;
/// Platform on which callback is received
platform: MoEPlatform;
///InApp data
campaignData: MoECampaignData;
}
class MoECampaignData {
/// Unique Campaign Identifier
campaignId: string;
/// Campaign Name
campaignName: string;
/// additional information associated with Campaign
context: MoECampaignContext;
}
class MoESelfHandledCampaignData {
///InApp data
campaignData:MoECampaignData;
/// account information
accountMeta: MoEAccountMeta;
///Platform on which callback is received
platform: MoEPlatform;
///SelfHandled data
campaign: MoESelfHandledCampaign
}
class MoESelfHandledCampaign {
///Campaign Content provided while creating campaign
payload: string;
///auto dismiss interval in seconds
dismissInterval: Number;
/// DisplayRules for Campaign
displayRules: MoEInAppRules;
}
class MoEInAppRules {
/// Screenname for which InApp was configured to be shown.
/// @deprecated Use the 'screenNames' property instead.
screenName: string | null;
/// contexts for which InApp was configured to be shown.
contexts: Array;
/// Screennames for which InApp was configured to be shown.
/// @since 12.0.0
screenNames: Array;
}
class MoEClickData {
///account information
accountMeta: MoEAccountMeta;
///Platform on which callback is received
platform: MoEPlatform;
///InApp Data
campaignData: MoECampaignData;
///InApp Click action
action: MoEAction;
}
class MoEInAppCustomAction extends MoEAction{
/// Key-Value pairs configured with action
keyValuePair: Map;
///Click action type
actionType: MoEActionType;
}
class MoEInAppNavigation extends MoEAction {
///navigation action type screen/deeplink
navigationType: MoENavigationType;
// ScreenName OR deeplink URL based on navigation type
navigationUrl: String;
// Key-Value pairs configured with action
keyValuePair?: Map;
///Click action type
actionType :MoEActionType;
// Model for Multiple SelfHandled Data
class MoESelfHandledCampaignsData {
///account information
accountMeta: MoEAccountMeta;
///List of SelfHandled data
campaigns: Array
}
```
# Handling Orientation Change
This is only for the Android platform
Starting SDK version `7.3.0`, in-apps are supported in both portrait and landscape modes.\
SDK has to be notified when the device orientation changes for SDK to handle in-app display.
## Add the API call in the Android native part of your app
Notify the SDK when `onConfigurationChanged()` API callback is received in your App's Activity class.
```java Java theme={null}
import android.content.res.Configuration;
import androidx.annotation.NonNull;
import com.facebook.react.ReactActivity;
import com.moengage.react.MoEReactHelper;
public class MainActivity extends ReactActivity {
/**
* Returns the name of the main component registered from JavaScript. This is used to schedule
* rendering of the component.
*/
@Override
protected String getMainComponentName() {
return "SampleApp";
}
@Override public void onConfigurationChanged(@NonNull Configuration newConfig) {
super.onConfigurationChanged(newConfig);
MoEReactHelper.getInstance().onConfigurationChanged();
}
}
```
# Display status bar
To display the status bar, use the following code snippet during Android SDK initialization:
```java Java wrap theme={null}
.configureInApps(new InAppConfig(false))
```
# Getting Started with React Native SDK
Source: https://moengage.com/docs/developer-guide/react-native-sdk/overview/getting-started-with-react-native-sdk
Get started with the MoEngage React Native SDK for push notifications, in-app messages, and tracking.
# Overview
MoEngage’s React Native SDK helps you integrate MoEngage into iOS and Android applications built with React Native framework. It allows you to work with push notifications, in-app messages, cards, user attributes, events, and much more.
To see the sample code, take a look at the [GitHub repository](https://github.com/moengage/React-Native-Sample-App). This article describes the steps to implement MoEngage features on React Native.
You can now get notified whenever MoEngage releases a new version of the React Native SDK. For more information, refer to [Subscribe to MoEngage SDK Releases](/developer-guide/release-notes/subscribe-to-moengage-sdk-releases/subscribe-to-mo-engage-sdk-releases).
# SDK Installation and Initialization
There are two methods for managing the MoEngage SDK: using the MoEngage Expo Plugin or configuring the native layers directly.
The Expo Plugin allows you to configure many SDK features without writing native code. For more information, see the [MoEngage Expo Plugin documentation](/developer-guide/react-native-sdk/sdk-integration/expo/installation). \
To configure the SDK by managing the native layers, follow the steps below:
**Step 1: Installation**
To add MoEngage's React Native SDK to your application, refer to [Installation Methods](/developer-guide/react-native-sdk/sdk-integration/react-native/sdk-installation/framework-dependency).
**Step 2: Complete Native Android Setup**
* Android native setup guidelines to complete the installation are described in this [article](/developer-guide/react-native-sdk/sdk-integration/react-native/sdk-installation/android).
* There are no additional steps required for iOS. Move on to the initialization (Step 3).
**Step 3: Framework Initialization**\
Initialize an instance of the MoEngage plugin by calling the method described in this [article](/developer-guide/react-native-sdk/sdk-integration/react-native/sdk-initialization/manual-initialization/framework-initialization).
**Step 4: Platform Initialization**\
The platform-specific steps to initialize the SDK and set up the data center are described in the following articles:
* [Android](/developer-guide/react-native-sdk/sdk-integration/react-native/sdk-initialization/manual-initialization/android)
* [iOS](/developer-guide/react-native-sdk/sdk-integration/react-native/sdk-initialization/manual-initialization/ios)
# Data Tracking
Data tracking allows apps to monitor and analyze user behavior to optimize engagement strategies. It involves tracking various user actions such as login, logout, and event tracking in a way that avoids data corruption. Use the following methods to implement data tracking.
* **Install/Update Differentiation** - To track fresh installs and updates separately, refer to the methods in this [article](/developer-guide/react-native-sdk/data-tracking/install-update).
* **Tracking Login, Logout, and Setting Unique ID** - To avoid data corruption, it is crucial to follow the steps outlined in the following articles when handling user login and logout.
* [Tracking Login and set user ID](/developer-guide/react-native-sdk/data-tracking/setting-unique-id-for-sdk-versions-below-1120#login-user)
* [Tracking Logout](/developer-guide/react-native-sdk/data-tracking/setting-unique-id-for-sdk-versions-below-1120#logout-user)
* [Updating User Attribute Unique ID](/developer-guide/react-native-sdk/data-tracking/setting-unique-id-for-sdk-versions-below-1120)
It is essential to have a unique ID for each of your app's users, which can be passed onto MoEngage SDK using setUserUniqueID(). This unique ID helps to correctly identify a user across multiple installs and platforms to provide a unified view.
Once a user logs out of the app, it's critical to call logout() to initiate the creation of a new user. This step is necessary to ensure that any subsequent activities performed by the new user are not wrongly attributed to the previously logged-in user, which could distort user data.
* **Tracking user attributes** - To set custom attributes available in the user profile, refer to the methods in [this article](/developer-guide/react-native-sdk/data-tracking/setting-unique-id-for-sdk-versions-below-1120).
* **Tracking Events** - Tracking events is how you record user actions, along with any properties that describe the action. To track custom events, refer to the methods in [this article](/developer-guide/react-native-sdk/data-tracking/tracking-events).
* **Enable Advertising Identifier Tracking (Android only)** - MoEngage SDK uses a Device ID (persistent device identifier) to uniquely identify the user to deliver personalized content and associates this to AAID if allowed by the app. This allows accurate identification of reachable devices for sending push notifications and tracking re-installs for users over time. To enable tracking of the AAID after obtaining the user’s consent, refer to the methods in [this article](/developer-guide/react-native-sdk/data-tracking/enable-advertising-identifier-tracking).
# Push Notifications
Push campaigns target users through notifications for your app or website. Depending on the desired capability, follow the integration steps listed below to integrate push notifications.
## Basic Setup - Android
Follow the basic setup outlined in this section to enable push notifications on an Android device using MoEngage.
* **FCM Setup on MoEngage Dashboard -** FCM Authentication is the method to enable sending push notifications to your app installed on Android devices. Use the methods mentioned in [this article](/developer-guide/android-sdk/push/basic/fcm-authentication) to authenticate MoEngage to access Firebase services.
* **Adding metadata for push notification -** Set the small icon and large icon drawable and other options to handle push notifications using the methods available in [this article](/developer-guide/components-for-sdk/push-notification/android-push-configuration-for-hybrid-applications#adding-metadata-for-push-notification).
* **Android Notification Runtime Permissions** - When the application is running on Android 13 to show notifications to the user, applications would need to request the user for notification permission. Refer to the methods available in [this article](/developer-guide/react-native-sdk/push/basic/android-notification-runtime-permissions) to handle permission requests.
* **Push Registration and Receiving** - To use Push Notification in your React Native application, you must configure Firebase. Configuring Firebase steps will depend on how you want to integrate it. MoEngage recommends leaving the push handling to MoEngage SDK, as the best practices are properly integrated. You can also handle the push at your app level. In any case, look at the following section that applies to you and finish the integration steps.
**Add messaging service**\
You must add the messaging service to the Manifest file for MoEngage SDK to show the notifications. Refer to this document [here](/developer-guide/android-sdk/push/basic/push-token-registration-and-display#push-token-registration-and-display-by-moengage-sdk).
**Callback on token registration (optional)**\
To get a callback whenever a new token is registered or refreshed, refer to the method [here](/developer-guide/android-sdk/push/basic/push-token-registration-and-display#token-callback-access-to-push-token-optional).
**Notification Clicked Callback**
To receive a callback whenever a push is clicked and for custom handling redirection, use the method in [this article](/developer-guide/android-sdk/push/advanced/callbacks-and-customisation#notification-clicked-callback).
**How to opt out of MoEngage Registration?**\
The MoEngage SDK attempts to register for a push token; since your application handles push, you need to opt out of SDK's token registration using the method in [this article](/developer-guide/android-sdk/push/basic/push-token-registration-and-display#how-to-opt-out-of-moengage-push-token-registration).
**Pass the Push Token To MoEngage SDK** - After receiving the push token from FCM, use the method in [this article](/developer-guide/android-sdk/push/basic/push-token-registration-and-display) to pass the Push Token to the MoEngage SDK to set it in the MoEngage platform.
**Passing the Push payload to the MoEngage SDK** - After receiving the push payload on the app, use the method in [this article](/developer-guide/android-sdk/push/basic/push-token-registration-and-display#passing-the-push-payload-to-the-moengage-sdk) to send out push notifications to the device.
MoEngage recommends using the Android native APIs to pass the push payload to the MoEngage SDK instead of the React-Native/Javascript APIs. React-Native Engine might not get initialized if the application is killed or if the notification is not sent at a high priority.
* [Pass the Push Token To MoEngage SDK](/developer-guide/react-native-sdk/push/basic/android-push-configuration#passing-push-token)
* [Pass the Push payload to the MoEngage SDK](/developer-guide/react-native-sdk/push/basic/android-push-configuration#passing-push-payload)
* [Callbacks and customizations](/developer-guide/react-native-sdk/push/basic/android-push-configuration#customizing-push-notification)
**Notification Clicked Callback -** MoEngage's React Native plugin optionally provides a callback on push clicks with the method in [this article](/developer-guide/react-native-sdk/push/basic/push-callback).
## Basic Setup - iOS
Follow the basic setup outlined in this section to enable push notifications on an iOS device using MoEngage.
* **APNS Setup on MoEngage dashboard**\
APNS Authentication is the method to enable sending push notifications to your app installed on Android devices. You can use any of these options to set up APNS on the MoEngage dashboard.
* [APNS Authentication Key (recommended)](/developer-guide/ios-sdk/push/basic/apns-authentication-key)
* [APNS Certificate/PEM file](/developer-guide/ios-sdk/push/basic/apns-certificate-pem-file-legacy)
* **App target implementation** - Make changes to your app target to enable notifications by following the steps mentioned in [this article](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial).
* **Provide the App Group ID to SDK**- Pass the App Group ID to MoEngage SDK using the method in [this article](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial).
* **Push Registration and Receiving**
In MoEngage SDK, we have swizzled the AppDelegate Class to get all the callbacks related to Push Notifications, and we have also applied the method swizzling for UserNotificationCenter delegate methods. This is to ease the integration of the SDK.
**Registering for Push notification**\
Follow the steps in [this article](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial#choose-a-notification-registration-method) to initiate registration.
**Callback methods on receiving Push Notification**\
With Swizzling enabled, no additional configuration is required.
In case you do not prefer to use swizzling, you can disable the same by adding the flag MoEngageAppDelegateProxyEnabled in the app’s Info.plist file and setting it to Boolean value NO, and follow the steps below.
**Registering for Push notification -** Follow the steps in [this article](https://moengage-sdk-docs.mintlify.app/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial#choose-a-notification-registration-method) to initiate registration and the steps in [this section](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial#app-delegate-method-swizzling) to call the respective MoEngage SDK methods for registration callbacks.
**Callback methods on receiving Push Notification -** With Swizzling disabled, include calls to MoEngage SDK methods on receiving notification callbacks, as described in [this article](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial#app-delegate-method-swizzling).
* **Disable Badge Reset**\
By default, the SDK sets the notification badge count to 0 on every app launch, and this also clears the notifications in the device notification center. If you want to keep the notifications even after the App Launch, disable badge reset by calling the method in [this section](https://moengage-sdk-docs.mintlify.app/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial#configure-push-notification-badge-behavior).
* **Custom Sound for Notification**\
To optionally set a custom tone for notifications of your app, you can follow the method in [this section](/developer-guide/ios-sdk/push/advanced/custom-notification-handling#custom-sound-for-notification).
* **Notification Service Extension Target Implementation**\
The notification service extension allows MoEngage SDK to customize the content of a notification before the system delivers it to the user. This gives you the capability to add media in notifications, support inbox, update badge count on notifications delivered, and track notification impressions. Follow the steps in [this article](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial#step-1-implement-notification-service-extension-nse) to set up the notification service extension.
* **Notification Actions**\
Actionable notifications let you add custom action buttons to the standard iOS push notifications. Follow the steps mentioned in [this article](/developer-guide/ios-sdk/push/basic/actionable-notifications) to add custom actions to your notifications and track the actions performed on notifications
This completes your basic setup for push notifications in React Native.
## Push Templates
Push templates enable you to craft beautiful notifications within minutes without any coding. For information on how to create campaigns with templates in the dashboard, refer to [this article](https://help.moengage.com/hc/en-us/articles/4415622460948-Push-Templates).
To enable push templates, please follow the platform-specific documentation
* [Android](/developer-guide/android-sdk/push/optional/push-templates#sdk-installation)
* [iOS](/developer-guide/ios-sdk/push/optional/push-templates#1-create-a-notification-content-extension)
## Push Amp+ (Android only and Optional)
Around 25-30% of notifications are not delivered due to issues with original equipment manufacturer (OEM) devices. To combat this problem and improve retention rates, MoEngage developed Push Amplification+ to reach customers who may not have received notifications. MoEngage has also partnered with OEMs to address these issues and ensure that notifications are reliably delivered. To minimize any additional burden on your application, we have developed individual software development kits (SDKs) for each OEM. You can choose and integrate the relevant SDK based on your application's specific needs and device share. Refer to the documentation for each OEM-specific service and integrate the appropriate ones into your application for optimal push notification delivery.
### Supported Integrations
* [HMS Push Kit](/developer-guide/android-sdk/push/optional/push-amp-plus/configuring-hms-push-kit)
## Push Amplification (Android only and Optional)
Push Amplification works as a fallback mechanism when Firebase Cloud Messaging (FCM) fails to deliver Push Notifications. Follow the method here to set up [Push Amplification](/developer-guide/android-sdk/push/optional/push-amplification).
## Notification Center
The Notification Center shows your push notification history, allowing you to provide an option for the end-user to scroll back and see what they have missed. MoEngage provides out-of-box inbox support with a fully customizable default UI and also provides an option to build your own Notification Center. For more information, refer to [Notification Center](/developer-guide/react-native-sdk/push/optional/notification-triggered).
## Location Triggered Notifications (Optional)
Location-triggered notifications allow you to send messages to your audience that are triggered on the user’s entry, exit, and dwell in defined Geo Fences. Follow the method in [this article](/developer-guide/react-native-sdk/push/optional/location-triggered) to set up location triggers.
## Device triggered notifications (Optional)
Device-triggered notifications allow you to send messages to your audience that are triggered locally based on any activity on a device. Offline delivery of messages is supported as well.
To enable device-triggered notifications, use the following platform-specific articles:
* [Android](/developer-guide/android-sdk/push/optional/device-triggered)
* [iOS](/developer-guide/ios-sdk/push/optional/real-time-triggers)
## Advanced Use Cases in Android
For advanced use cases, the following options are available:
* **Non-MoEngage Payload** - To get an optional callback in case a push payload is received for any other server apart from the MoEngage Platform, refer to the method [here](/developer-guide/android-sdk/push/basic/push-token-registration-and-display#push-display-for-non-moengage-payloads-optional).
* **Callbacks and customizations** - The MoEngage SDK allows the client application to optionally customize the notification display and extend/customize the behavior of the notification. Refer to the methods mentioned [here](/developer-guide/android-sdk/push/advanced/callbacks-and-customisation) to access the features, such as:
* Control whether a notification is shown to the user or not
* Notification Received Callback
* Notification Clicked Callback
* Notification Cleared Callback
* Custom Action on Action Button Click
* **Push Display Handled by Application(Android)** - When the application needs to handle the push display on the client side, you can track notification impressions and cases using the methods described in [this article](/developer-guide/android-sdk/push/advanced/push-display-handled-by-application).
# In-App
MoEngage In-App Campaigns target users by showing a message while the user is using your app. They are effective in providing contextual information and help to cross-sell/up-sell on desired screens of your app or/and on desired actions performed by the user in your app.
Basic Setup - To install In-app notifications in React Native, use the following platform-specific methods:
* [Android](/developer-guide/react-native-sdk/in-app-messages/inapp-nativ#installing-android-dependency)
* iOS (installation is not required for iOS)
## Displaying In-App Messages
You can either show In-app messages using MoEngage’s out-of-the-box UI, or you can use Self-handled In-apps to build the UI of the application using the payload from MoEngage.
**Show In-app**\
Call the method [here](https://moengage-sdk-docs.mintlify.app/developer-guide/react-native-sdk/in-app-messages/inapp-nativ#installing-android-dependency) to show an inApp campaign on a screen. In-app pop-ups will only show up where showInApp() method is called.
**Handling Orientation Change**\
In-apps are supported in both portrait and landscape modes. SDK has to be notified when the device orientation changes for SDK to handle in-app display. To handle orientation change, refer to [this article](developer-guide/react-native-sdk/in-app-messages/inapp-nativ#handling-orientation-change).
**Self-handled In-apps**\
Self-handled In Apps are messages that are delivered by the SDK to the application, and the application builds the UI using the delivered payload by the SDK. To get the self-handled in-app, refer to [this article](https://moengage-sdk-docs.mintlify.app/developer-guide/react-native-sdk/in-app-messages/inapp-nativ#display-in-app).
* [Getting self-handled campaigns](/developer-guide/react-native-sdk/in-app-messages/inapp-nativ#self-handled-inapps)
* [Tracking Statistics for Self-Handled In-Apps](/developer-guide/react-native-sdk/in-app-messages/inapp-nativ#tracking-statistics)
## InApp Callbacks
Optionally, we provide callbacks for in-app shown, in-app clicked, in-app dismissed, and self-handled in-app available events. You can register for the callbacks using the methods in [this article.](/developer-guide/react-native-sdk/in-app-messages/inapp-nativ)
# Cards
MoEngage Cards campaigns help you interact with your users with persistent and non-intrusive messages in your customer's journey. Self-handled cards are message payloads that are delivered by the SDK to the application, and the application builds the UI using the delivered payload.
Refer to [this article](/developer-guide/react-native-sdk/cards/self-handled-cards) to implement self-handled cards on React Native.
# Android Notification Runtime Permissions
Source: https://moengage.com/docs/developer-guide/react-native-sdk/push/basic/android-notification-runtime-permissions
Handle Android 13 notification runtime permissions in your React Native app using the MoEngage SDK.
Android 13 (API level 33) and higher supports [runtime permission](https://developer.android.com/guide/topics/permissions/overview#runtime) for sending [non-exempt](https://developer.android.com/develop/ui/views/notifications/notification-permission#exemptions)(including Foreground Services (FGS)) notifications from an app [POST\_NOTIFICATIONS](https://developer.android.com/reference/android/Manifest.permission#POST_NOTIFICATIONS). This change helps users focus on the notifications that are most important to them.
Refer to the [official documentation](https://developer.android.com/develop/ui/views/notifications/notification-permission) for more details.
The below-mentioned APIs are supported starting MoEngage core Android SDK version **12.3.01**
When an application runs on Android 13 and wants to show notifications to the user, it must request the user's notification permission. You have two options: let MoEngage handle permissions for you or handle the notification permission with your code.
* MoEngage handles Notification permission.
* You just have to call a single line of code mentioned on this page.
* You maintain the notification permission logic.
* Notify MoEngage SDK if permission to push notifications is granted.
We recommend you let MoEngage handle push notification permissions.
## Let MoEngage SDK handle Notification permission
MoEngage SDK provides helper APIs to show the permission request to the end-user or navigate the user to the settings screen for enabling notifications.
Use the below API to show the permission request dialog to the user.
When using the below API SDK automatically tracks the response, sets up the required notification channel, etc, mentioned above.
```java JavaScript theme={null}
import ReactMoE from 'react-native-moengage'
ReactMoE.requestPushPermissionAndroid()
```
## Notify SDK of permission result
Once the application requests the user for notification permission notify the SDK of the user response using the below API. *If you are letting MoEngage SDK handle the notification permissions, you should ignore this step.*
```java JavaScript theme={null}
import ReactMoE from 'react-native-moengage'
ReactMoE.pushPermissionResponseAndroid(true);
```
## Update the Permission request count(optional)
Once the application requests the user for notification permission, update the SDK of the request attempts.
**Why does the SDK require permission attempt count?**
SDK requires the attempt count to accurately track the number of times the permission request was attempted. If the user denies the permission request twice the application/SDK cannot request permission further i.e. if we request permission it would be automatically denied without the user seeing the request dialog. As an SDK we cannot be sure of the number of times the user has denied the permission we try to optimize the calls to request permission based on the attempt count.
```java JavaScript theme={null}
import ReactMoE from 'react-native-moengage'
ReactMoE.updatePushPermissionRequestCountAndroid(requestCount);
```
## Navigate to Notification Settings (situational/optional)
Use the below API to show navigate the user to the Notification Settings for the application on the device.
*Note*: Below Android 8(API level 26) the user is directed to the Application Info screen of your application.
```java JavaScript theme={null}
import ReactMoE from 'react-native-moengage'
ReactMoE.navigateToSettingsAndroid()
```
# Android Push Configuration
Source: https://moengage.com/docs/developer-guide/react-native-sdk/push/basic/android-push-configuration
Set up and configure Android push notifications for your React Native app using MoEngage and Firebase.
# Basic Setup
Follow the basic setup outlined in this section to enable push notifications on an Android device using MoEngage.
* **FCM Setup on MoEngage Dashboard -** FCM Authentication is the method to enable sending push notifications to your app installed on Android devices. Use the methods mentioned in [this article](/developer-guide/android-sdk/push/basic/fcm-authentication) to authenticate MoEngage to access Firebase services.
* **Adding metadata for push notification -** Set the small icon and large icon drawable and other options to handle push notifications using the methods available in [this article](/developer-guide/components-for-sdk/push-notification/android-push-configuration-for-hybrid-applications).
* **Android Notification Runtime Permissions** - When the application is running on Android 13 to show notifications to the user, applications would need to request the user for notification permission. Refer to the methods available in [this article](/developer-guide/components-for-sdk/push-notification/android-push-configuration-for-hybrid-applications#adding-metadata-for-push-notification) to handle permission requests.
* **Push Registration and Receiving** - To use Push Notification in your React Native application, you must configure Firebase. Configuring Firebase steps will depend on how you want to integrate it. MoEngage recommends leaving the push handling to MoEngage SDK, as the best practices are properly integrated. You can also handle the push at your app level. In any case, look at the following section that applies to you and finish the integration steps.
**Add messaging service**\
You must add the messaging service to the Manifest file for MoEngage SDK to show the notifications. Refer to this document [here](/developer-guide/react-native-sdk/push/basic/android-push-configuration#passing-push-token).
**Callback on token registration (optional)**\
To get a callback whenever a new token is registered or refreshed, refer to the method [here](/developer-guide/react-native-sdk/push/basic/android-push-configuration#passing-push-payload).
**Notification Clicked Callback**
To receive a callback whenever a push is clicked and for custom handling redirection, use the method in [this article](/developer-guide/react-native-sdk/push/basic/android-push-configuration#customizing-push-notification).
**How to opt out of MoEngage Registration?**\
The MoEngage SDK attempts to register for a push token; since your application handles push, you need to opt out of SDK's token registration using the method in [this article](/developer-guide/android-sdk/push/basic/push-token-registration-and-display#how-to-opt-out-of-moengage-push-token-registration).
**Pass the Push Token To MoEngage SDK** - After receiving the push token from FCM, use the method in [this article](/developer-guide/android-sdk/push/basic/push-token-registration-and-display) to pass the Push Token to the MoEngage SDK to set it in the MoEngage platform.
**Passing the Push payload to the MoEngage SDK** - After receiving the push payload on the app, use the method in [this article](/developer-guide/android-sdk/push/basic/push-token-registration-and-display#passing-the-push-payload-to-the-moengage-sdk) to send out push notifications to the device.
MoEngage recommends using the Android native APIs to pass the push payload to the MoEngage SDK instead of the React-Native/Javascript APIs. React-Native Engine might not get initialized if the application is killed or if the notification is not sent at a high priority.
* [Pass the Push Token To MoEngage SDK](/developer-guide/react-native-sdk/push/basic/android-push-configuration)
* [Pass the Push payload to the MoEngage SDK](/developer-guide/react-native-sdk/push/basic/android-push-configuration)
* [Callbacks and customizations](/developer-guide/react-native-sdk/push/basic/android-push-configuration)
**Notification Clicked Callback -** MoEngage's React Native plugin optionally provides a callback on push clicks with the method in [this article](/developer-guide/react-native-sdk/push/basic/push-callback).
# React-Native methods for Push
*You can skip this section completely if you let MoEngage handle push token registration and display or use Android Native methods to pass tokens and payload to MoEngage SDKs.*
Read on if you want to use React Native methods of MoEngage SDK to pass tokens and payload to MoEngage SDKs.
MoEngage recommends using the Android native APIs to pass the push payload to the MoEngage SDK instead of the React-Native/Javascript APIs. React-Native Engine might not get initialized if the application is killed or if the notification is not sent at a high priority.
## Passing Push Token
```javascript JavaScript theme={null}
const ReactMoE = require('react-native-moengage')
// pass the push token as a string
ReactMoE.passFcmPushToken("")
```
## Passing Push Payload
```javascript JavaScript theme={null}
const ReactMoE = require('react-native-moengage')
// pass the push payload as a JSONObject from FCM. Note only the data payload needs to be passed to SDK.
ReactMoE.passFcmPushPayload({})
```
MoEngage recommends that you use the Android native APIs for passing the push payload to the MoEngage SDK instead of the React-Native/Javascript APIs. React-Native Engine might not get initialized if the application is killed or if the notification is not sent at a high priority.
## Customizing Push notification
If required the application can customize the behavior of notifications by using Native Android code (Java/Kotlin). To learn more about the customization refer to the [Advanced Push Configuration](/developer-guide/android-sdk/push/advanced/callbacks-and-customisation) documentation.Instead of extending ***PushMessageListener*** as mentioned in the above document extend ***PluginPushCallback.***
Refer to the below documentation for Push Amp+, Push Templates, and Geofence.
* [Push Amplification](/developer-guide/android-sdk/push/optional/push-amplification)
* [Push Amp Plus](/developer-guide/android-sdk/push/optional/push-amp-plus/push-amp-plus-integration)
* [Push Templates](/developer-guide/android-sdk/push/optional/push-templates)
* [GeoFence Push](/developer-guide/android-sdk/push/optional/location-triggered)
# iOS Push Configuration
Source: https://moengage.com/docs/developer-guide/react-native-sdk/push/basic/ios-push-configuration
Configure iOS push notifications with APNS certificates and entitlements for your React Native app.
## Push Configuration
Following are the two ways to configure Push Notification
### APNS Authentication Key:
To send push notifications to iOS users, it is required to generate the APNs Auth Key file for your application and upload it to the MoEngage dashboard. Refer the [link](https://developers.moengage.com/hc/en-us/articles/8484447635348-APNS-Authentication-Key) to generate Auth key.
### APNS Certificate:
First you will have to create an APNS certificate and upload in the dashboard to be able to send push notifications in iOS. Follow the steps below to do that :
* [Create an APNS certificate](https://developers.moengage.com/hc/en-us/articles/4564208314516)
* [Convert the resultant certificate to .pem format](https://developers.moengage.com/hc/en-us/articles/4564208314516)
* [Upload .pem file to MoEngage Dashboard](https://developers.moengage.com/hc/en-us/articles/4564208314516)
## Adding Push Entitlement to your Project:
Once the APNS Certificate is uploaded, enable Push Entitlement in the Xcode project. For that select your app target, then go to Capabilities. Here enable the Push Notifications capability for your app as shown below :
## Uninstall Tracking:
We make use of silent pushes to track uninstalls. For tracking uninstalls of all the users, enable Remote Notification background mode in-app capabilities for the same as shown below :
## Push Registration:
After this you will have to register for push notification by using **registerForPush** method of the plugin as shown below :
```javascript JavaScript theme={null}
//This is only for iOS
import ReactMoE from 'react-native-moengage'
ReactMoE.registerForPush();
```
Plugin gets all the remote notification-related callbacks, therefore you won't receive any of them in your AppDelegate. Therefore, you will have to add observers for the notifications provided by plugin instead.
## Provisional Push Registration:
* This feature is supported from version ***11.1.0*** of the plugin.
To register for provisional push notification, call ***registerForProvisionalPush*** Api of the plugin as shown below
```javascript JavaScript theme={null}
import ReactMoE from 'react-native-moengage'
// This API is only for iOS
ReactMoE.registerForProvisionalPush();
```
## Rich Push and Templates Support:
Please refer to the Native iOS SDK docs for supporting Rich Push(images/videos/audio in the notification) and Templates in the app:
* [Rich Push](https://developers.moengage.com/hc/en-us/articles/43960004257428-iOS-Push-Integration-Tutorial#h_01K4MBZ6WN3PTSSS6N6K2YQ8S2)
* [Push Templates](https://developers.moengage.com/hc/en-us/articles/4403956104084-Push-Templates-7-x-x)
# Push Callback
Source: https://moengage.com/docs/developer-guide/react-native-sdk/push/basic/push-callback
Set up push token and push click callback listeners in the MoEngage React Native SDK.
# Push Token Callback
MoEngage plugin triggers the`pushTokenGenerated` event whenever device token is generated. This event is a common trigger for both iOS and Android platforms and is available from plugin version `6.0.0`. Refer to the below code to set listener to the same:
```typescript TypeScript theme={null}
import ReactMoE from 'react-native-moengage'
ReactMoE.setEventListener("pushTokenGenerated", (payload) => {
console.log("pushTokenGenerated", payload);
});
```
Payload received in the callback is a `MoEPushToken` instance with the following definition:
```typescript TypeScript theme={null}
class MoEPushToken {
/// Native platform from which the callback was triggered.(ios/android)
platform: MoEPlatform;
/// push type associated with platform
pushService: MoEPushService;
/// push token value
token: String;
}
```
# Push Click Callback
MoEngage plugin triggers the`pushClicked` event whenever a notification is clicked. This event is a common trigger for both iOS and Android platforms and is available from plugin version `6.0.0`. Refer to the below code to set the listener to the same:
Make sure you are calling `initialize()` method of the MoEngage plugin after you set up these callbacks. Refer [Initialise React-Native Component](/developer-guide/react-native-sdk/sdk-integration/react-native/sdk-initialization/manual-initialization/framework-initialization) for more info.
```typescript TypeScript theme={null}
import ReactMoE from 'react-native-moengage'
ReactMoE.setEventListener("pushClicked", (notificationPayload) => {
console.log("pushClicked", notificationPayload);
});
```
Make sure this callback is set as soon as the application is initialized. Preferably in the constructor of your `App.js`.
NotificationPayload received in the callback is a `MoEPushPayload` instance with the following definition:
```typescript TypeScript theme={null}
class MoEPushPayload {
/// account payload for which callback is received
accountMeta: MoEAccountMeta;
/// Push click payload
data: MoEPushCampaign;
/// Native platform from which the callback was triggered.(ios/android)
platform: MoEPlatform;
}
class MoEPushCampaign {
/// notification payload
payload: Map
///boolean value indicating if the user clicked on the default content or not.
isDefaultAction: Boolean;
///Action to be performed on notification click.
clickAction: Map;
}
```
Payload Structure for `clickedAction` Map
```json JSON theme={null}
{
"clickedAction": {
"type": "navigation/customAction",
"payload": {
"type": "screenName/deepLink/richLanding",
"value": "",
"kvPair": {
"key1": "value1",
"key2": "value2",
...
}
}
}
}
```
* `platform` - Native platform from which callback is triggered. Possible values - `android`, `ios`
* `isDefaultAction` - This key is present only for the Android Platform. It's a boolean value indicating if the user clicked on the default content or not. true if the user clicks on the default content else false.
* `clickedAction` - Action to be performed on notification click.
* `clickedAction.type` - Type of click action. Possible values `navigation` and `customAction`. Currently, `customAction` is supported only on Android.
* `clickAction.payload` - Action payload for the clicked action.
* `clickedAction.payload.type` - Type of navigation action defined. Possible values `screenName`, `deepLink`, `richLanding`. Currently, in the case of iOS, richlanding and deep-link URL are processed internally by the SDK and not passed in this callback therefore possible value in case of iOS is only `screenName`.
* `clickAction.value` - value entered for navigation action or custom payload.
* `clickAction.kvPair` - Custom key-value pair entered on the MoEngage Platform.
* `payload` - Complete campaign payload.
## Android Payload
If the user clicks on the default content of the notification the key-value pair and campaign payload can be found inside the `payload` key. If the user clicks on the action button or a push template action the action payload would be found inside `clickedAction`.\
You can use the `isDefaultAction` key to check whether the user clicked on the default content or not and then parse the payload accordingly.
## iOS Payload
In the case of iOS, you would always receive the key-value pairs with respect to clicked action in `clickedAction` the property. Refer to this [Notification Payload](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial#step-1-implement-notification-service-extension-nse) to know the iOS notification payload structure.
# Self-Handled Push Click Android (Optional)
By default, when the user clicks on a notification the SDK redirects the user to the defined Activity and passes the callback to the Application to load the specific react-native component.
When the application is in the foreground it might seem like the application is reloading and not a very good user experience. You might just want to navigate the user to the specific react-native component. To do so follow the below steps.
While initializing the React-Native Plugin, enable foreground click callback in the ***MoEPushConfig*** object.
```typescript TypeScript theme={null}
import { MoEPushConfig, MoEInitConfig } from "react-native-moengage";
ReactMoE.initialize(
"YOUR_APP_ID",
new MoEInitConfig(new MoEPushConfig(true))
);
```
You must call the ***initialize()*** when the React Component is mounted and the application comes to the foreground.
Enable the Self-Handled callback in the SDK initialization in the Application class as shown below
```kotlin Kotlin theme={null}
val moEngage = MoEngage.Builder(this, "YOUR_APP_ID")
MoEInitializer.initializeDefaultInstance(applicationContext, moEngage, true)
```
```java Java theme={null}
MoEngage.Builder moEngage = new MoEngage.Builder(this, "YOUR_APP_ID");
MoEInitializer.INSTANCE.initializeDefaultInstance(getApplicationContext(), moEngage, true);
```
Add the below Activity to your AndroidManifest.xml
```xml XML theme={null}
```
Notification click callbacks that are triggered when the application is in the foreground(and the above flow is enabled) will have an additional key i.e. ***selfHandledPushRedirection*** with value as ***true***
# Location Triggered
Source: https://moengage.com/docs/developer-guide/react-native-sdk/push/optional/location-triggered
Install and configure the MoEngage Geofence SDK for location-triggered push in React Native.
# Installation
To add MoEngage Geofence SDK to your application run the below command from a terminal
```NPM npm theme={null}
npm install react-native-moengage-geofence
```
Note: This plugin is dependent on `react-native-moengage` plugin. Make sure you have installed the `react-native-moengage` plugin as well.
## Android Installation
For location triggered push to work, ensure your Application has:
* Location permission
* Play Services Location Library
* Device's location should be enabled
## iOS Installation
To run the application in the new react architecture, follow these steps:
1. Navigate to the iOS folder.
2. Run the command ***RCT\_NEW\_ARCH\_ENABLED=1 bundle exec pod install*** to install the necessary dependencies.
To run the application in the old react architecture, follow these steps
1. Navigate to the iOS folder.
2. Run the command ***pod install*** to install the necessary dependencies.
# Configure Geofence
By default, the geofence feature is not enabled. To enable the feature call the below API.
```TypeScript TypeScript theme={null}
import ReactMoEGeofence from 'react-native-moengage-geofence';
ReactMoEGeofence.startGeofenceMonitoring(YOUR Workspace ID);
```
At any time if you want to stop the geofence monitoring or feature use the below API. This API will remove the existing geofences.
```TypeScript TypeScript theme={null}
import ReactMoEGeofence from 'react-native-moengage-geofence';
ReactMoEGeofence.stopGeofenceMonitoring(YOUR Workspace ID);
```
# Notification Center
Source: https://moengage.com/docs/developer-guide/react-native-sdk/push/optional/notification-center
Install and set up the MoEngage Inbox plugin to build a notification center in React Native.
# Installation
Install MoEngage's Inbox Plugin to your application, using the npm package manager. And then link your native dependencies.
```shell Shell theme={null}
$ npm install react-native-moengage-inbox
# required only if you are using versions that do not support auto linking
# This command is removed in version 0.69 of react-native
$ react-native link react-native-moengage-inbox
```
Note: This plugin is dependent on `react-native-moengage` plugin. Make sure you have installed the `react-native-moengage` plugin as well. Refer to the [link](https://developers.moengage.com/hc/en-us/articles/4404205340564) for the same.
## iOS Installation
To run the application in the new react architecture, follow these steps:
1. Navigate to the iOS folder.
2. Run the command ***RCT\_NEW\_ARCH\_ENABLED=1 bundle exec pod install*** to install the necessary dependencies.
To run the application in the old react architecture, follow these steps:
1. Navigate to the iOS folder.
2. Run the command ***pod install*** to install the necessary dependencies.
Make sure to configure [AppGroup ID in App Target](https://developers.moengage.com/hc/en-us/articles/4403905438228) and Set up [Notification Service Extension](https://developers.moengage.com/hc/en-us/articles/43960004257428-iOS-Push-Integration-Tutorial#h_01K45FKD0XDH4X776R47JA04GJ) in your iOS Project, for the SDK to save the received notifications.
# Inbox Initialization
To initialise Inbox, pass Workspace ID as parameter to `initialize(Workspace ID)` method of `MoEReactInbox` as shown below
```typescript TypeScript theme={null}
import MoEReactInbox from "react-native-moengage-inbox";
MoEReactInbox.initialize(YOUR Workspace ID);
```
# Fetch Messages
To fetch all the inbox messages use `fetchAllMessages()` method as shown below, where you would get an instance of `MoEInboxData`
```typescript TypeScript theme={null}
import MoEReactInbox from "react-native-moengage-inbox";
var inboxData= await MoEReactInbox.fetchAllMessages()
```
## InboxData Payload
MoEInboxData will be received in the below format:
```typescript TypeScript theme={null}
class MoEInboxData {
/// Native platform from which the callback was triggered.(ios/android)
platform: String;
/// List of [MoEInboxMessage]
messages:Array = [];
}
class MoEInboxMessage {
/// internal identifier used by the SDK for storage.(Only Android)
id: number;
/// Unique identifier for a message.
campaignId: string;
/// Text content of the message. Instance of MoETextContent
text: MoETextContent;
/// true if the message has been clicked by the user else false
isClicked: boolean;
/// Media content associated with the message.
media: MoEMedia;
/// List of actions to be executed on click. Instances of [MoEAction]
action: Array = [];
/// Tag associated with the message.
tag: string;
/// The time in which the message was received on the device.
///
/// Format - ISO-8601 yyyy-MM-dd'T'HH:mm:ss'Z'
receivedTime: string;
/// The time at which the message expiry.
///
/// Format - ISO-8601 yyyy-MM-dd'T'HH:mm:ss'Z'
expiry: string;
/// Complete message payload. This will vary for platforms
payload: Map;
/// A key representing the group to which the inbox message belongs.
/// @since 6.0.0
groupKey: string | null;
/// Notification Replacement Id.
/// @since 6.0.0
notificationId: string | null;
/// The timestamp indicating when the message was sent.
/// Format - ISO-8601 yyyy-MM-dd'T'HH:mm:ss'Z'
/// @since 6.0.0
sentTime: string | null;
}
class MoEAction {
/// actionType- navigation
actionType: MoEActionType;
/// navigationType- deepLink, richLanding, screenName
navigationType: string;
/// Value associated with navigation action eg: url / screen name
value: string;
/// Custom Key-Value Pairs associated with action
kvPair?: Map;
}
class MoEMedia {
/// Content type of the Media. (image/video/audio)
mediaType: MoEMediaType;
/// Url for the media content. Generally a http(s) url.
url: string;
/// Accessibility information associated with media content.
/// @since 6.0.0
accessibilityData: MoEAccessibilityData | null;
}
class MoETextContent {
/// Tiitle content of the message
title: string;
/// Subtitle content of the message
subtitle?: string;
/// Message content of the message
message: string;
/// Summary content of the message
summary?: string;
}
/// @since 12.0.0 of react-native-moengage package
class MoEAccessibilityData {
/// The accessibility text
text: string | null;
/// The accessibility hint
hint: string | null;
}
```
# Get Unclicked Message Count
To obtain the unclicked messages count from the Inbox use `getUnClickedCount()` method as shown below:
```typescript TypeScript theme={null}
import MoEReactInbox from "react-native-moengage-inbox";
var count = await MoEReactInbox.getUnClickedCount()
```
# Track Message Clicks
To track clicks on the messages inside your Inbox use `trackMessageClicked()` method as shown below:
```typescript TypeScript theme={null}
import MoEReactInbox from "react-native-moengage-inbox";
MoEReactInbox.trackMessageClicked(message) //Pass the instance of MoEInboxMessage here
```
# Delete Message
To delete a particular message from the list of messages use `deleteMessage()` method as shown below:
```typescript TypeScript theme={null}
import MoEReactInbox from "react-native-moengage-inbox";
MoEReactInbox.deleteMessage(message) //Pass the instance of MoEInboxMessage here
```
# Notification Center
Source: https://moengage.com/docs/developer-guide/react-native-sdk/push/optional/notification-triggered
Install the MoEngage Inbox plugin for notification-triggered messaging in your React Native app.
# Installation
Install MoEngage's Inbox Plugin to your application, using the npm package manager. And then link your native dependencies.
```shell Shell theme={null}
$ npm install react-native-moengage-inbox
# required only if you are using versions that do not support auto linking
# This command is removed in version 0.69 of react-native
$ react-native link react-native-moengage-inbox
```
Note: This plugin is dependent on `react-native-moengage` plugin. Make sure you have installed the `react-native-moengage` plugin as well. Refer to the [link](/developer-guide/react-native-sdk/sdk-integration/react-native/sdk-installation/framework-dependency) for the same.
## Android Installation
### Configuration Required For Older React Version (Optional)
This step is required only if react-native auto-linking is not working.
In ***android/settings.gradle(.kts)*** add the following:
```shell Groovy theme={null}
include ':react-native-moengage-inbox'
project(':react-native-moengage-inbox').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-moengage-inbox/android')
```
In ***android/app/build.gradle(.kts)*** add the following
```shell Groovy theme={null}
dependencies {
...
implementation project(':react-native-moengage-inbox')
}
```
Add the MoEngage React Package in the Application class's `getPackages()`
Path - ***android/app/src/main/java/package-name/MainApplication.java***
Note: Your Application class name might vary, go to your application class.
```java Java theme={null}
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
protected boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List getPackages() {
List packages = new PackageList(this).getPackages();
packages.add(new MoengageInboxPackage());
return packages;
}
}
};
@Override public void onCreate() {
super.onCreate();
}
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
}
```
In case you are facing issues with the import add the below import statement in your java file.
```java Java theme={null}
import com.moengage.react.inbox.MoengageInboxPackage;
```
## iOS Installation
To run the application in the new react architecture, follow these steps:
1. Navigate to the iOS folder.
2. Run the command ***RCT\_NEW\_ARCH\_ENABLED=1 bundle exec pod install*** to install the necessary dependencies.
To run the application in the old react architecture, follow these steps:
1. Navigate to the iOS folder.
2. Run the command ***pod install*** to install the necessary dependencies.
Make sure to configure [AppGroup ID in App Target](/developer-guide/ios-sdk/sdk-integration/basic/sdk-initialization) and Set up [Notification Service Extension](/developer-guide/ios-sdk/push/basic/ios-push-integration-tutorial#step-1-implement-notification-service-extension-nse) in your iOS Project, for the SDK to save the received notifications.
# Inbox Initialization
To initialise Inbox, pass Workspace ID as parameter to `initialize(Workspace ID)` method of `MoEReactInbox` as shown below
```typescript TypeScript theme={null}
import MoEReactInbox from "react-native-moengage-inbox";
MoEReactInbox.initialize(YOUR Workspace ID);
```
# Fetch Messages
To fetch all the inbox messages use `fetchAllMessages()` method as shown below, where you would get an instance of `MoEInboxData`
```typescript TypeScript theme={null}
import MoEReactInbox from "react-native-moengage-inbox";
var inboxData= await MoEReactInbox.fetchAllMessages()
```
## InboxData Payload
MoEInboxData will be received in the below format:
```typescript TypeScript theme={null}
class MoEInboxData {
/// Native platform from which the callback was triggered.(ios/android)
platform: String;
/// List of [MoEInboxMessage]
messages:Array = [];
}
class MoEInboxMessage {
/// internal identifier used by the SDK for storage.(Only Android)
id: number;
/// Unique identifier for a message.
campaignId: string;
/// Text content of the message. Instance of MoETextContent
text: MoETextContent;
/// true if the message has been clicked by the user else false
isClicked: boolean;
/// Media content associated with the message.
media: MoEMedia;
/// List of actions to be executed on click. Instances of [MoEAction]
action: Array = [];
/// Tag associated with the message.
tag: string;
/// The time in which the message was received on the device.
///
/// Format - ISO-8601 yyyy-MM-dd'T'HH:mm:ss'Z'
receivedTime: string;
/// The time at which the message expiry.
///
/// Format - ISO-8601 yyyy-MM-dd'T'HH:mm:ss'Z'
expiry: string;
/// Complete message payload. This will vary for platforms
payload: Map;
/// A key representing the group to which the inbox message belongs.
/// @since 6.0.0
groupKey: string | null;
/// Notification Replacement Id.
/// @since 6.0.0
notificationId: string | null;
/// The timestamp indicating when the message was sent.
/// Format - ISO-8601 yyyy-MM-dd'T'HH:mm:ss'Z'
/// @since 6.0.0
sentTime: string | null;
}
class MoEAction {
/// actionType- navigation
actionType: MoEActionType;
/// navigationType- deepLink, richLanding, screenName
navigationType: string;
/// Value associated with navigation action eg: url / screen name
value: string;
/// Custom Key-Value Pairs associated with action
kvPair?: Map;
}
class MoEMedia {
/// Content type of the Media. (image/video/audio)
mediaType: MoEMediaType;
/// Url for the media content. Generally a http(s) url.
url: string;
/// Accessibility information associated with media content.
/// @since 6.0.0
accessibilityData: MoEAccessibilityData | null;
}
class MoETextContent {
/// Tiitle content of the message
title: string;
/// Subtitle content of the message
subtitle?: string;
/// Message content of the message
message: string;
/// Summary content of the message
summary?: string;
}
/// @since 12.0.0 of react-native-moengage package
class MoEAccessibilityData {
/// The accessibility text
text: string | null;
/// The accessibility hint
hint: string | null;
}
```
# Get Unclicked Message Count
To obtain the unclicked messages count from the Inbox use `getUnClickedCount()` method as shown below:
```typescript TypeScript theme={null}
import MoEReactInbox from "react-native-moengage-inbox";
var count = await MoEReactInbox.getUnClickedCount()
```
# Track Message Clicks
To track clicks on the messages inside your Inbox use `trackMessageClicked()` method as shown below:
```typescript TypeScript theme={null}
import MoEReactInbox from "react-native-moengage-inbox";
MoEReactInbox.trackMessageClicked(message) //Pass the instance of MoEInboxMessage here
```
# Delete Message
To delete a particular message from the list of messages use `deleteMessage()` method as shown below:
```typescript TypeScript theme={null}
import MoEReactInbox from "react-native-moengage-inbox";
MoEReactInbox.deleteMessage(message) //Pass the instance of MoEInboxMessage here
```
# React Native Sample App
Source: https://moengage.com/docs/developer-guide/react-native-sdk/sample-app/react-native-sample-app
Explore the MoEngage React Native sample application as a reference for integrating the SDK.
The [MoEngage React Native Sample application](https://github.com/moengage/React-Native/tree/master/SampleApp) offers a useful reference point for integrating MoEngage into your React Native app.
## Next Steps
* [SDK Installation](/developer-guide/react-native-sdk/sdk-integration/react-native/sdk-installation/framework-dependency)
* [Framework Initialization](/developer-guide/react-native-sdk/sdk-integration/react-native/sdk-initialization/manual-initialization/framework-initialization)
# Configure the MoEngage Expo SDK
Source: https://moengage.com/docs/developer-guide/react-native-sdk/sdk-integration/expo/configure-the-moengage-expo-sdk
Configure the MoEngage Expo SDK plugin parameters and platform-specific initialization files.
## Overview
This guide covers the parameters you can use to configure the MoEngage SDK. All plugin-level configuration is done within your app.json or app.config.js file. Core SDK credentials are placed in separate platform-specific files.
You must complete the [installation](/developer-guide/react-native-sdk/sdk-integration/expo/installation) guide before you configure the SDK.
## Plugin-Managed Native Configuration
To ensure a reliable and streamlined setup, the MoEngage Expo plugin manages native project configurations automatically. This approach reduces the potential for manual errors by handling platform-specific requirements during the prebuild process.
Key automations include:
* Applying Critical Settings: The plugin automatically adds required settings, such as the Android backup exclusion rules, to ensure data integrity.
* Eliminating Manual File Edits: Direct modification of native files like AndroidManifest.xml (for Android) or Info.plist (for iOS) is not necessary.
## SDK Initialization Configuration (XML and Plist files)
As specified in the configFilePath property, your core MoEngage credentials and SDK settings do not go in app.json. Instead, they are defined in separate files for each platform.
* For Android: [Generate](https://app-cdn.moengage.com/sdk/integration/config/index.html) an XML file (e.g., android\_initialisation\_config.xml).
* For iOS: [Generate](https://app-cdn.moengage.com/sdk/integration/config/index.html) a Plist file (e.g., MoEngage-Config.plist).
The following tables detail the available properties for these files.
**Android SDK Configuration**
| Section | Field Name | Description |
| :-------------------- | :------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Core** | Moengage Workspace ID | This field denotes the unique identifier that links your application to a specific workspace within your MoEngage dashboard. |
| Core | Moengage Project ID | This field denotes the unique identifier associated with a specific project if you have [*Portfolio*](https://help.moengage.com/hc/en-us/articles/40394603054100-Portfolio) feature enabled for your workspace. |
| Core | Moengage Data Center | This field denotes the data center based on the dashboard URL. [Refer here](/developer-guide/android-sdk/sdk-integration/basic-integration/data-center) for more details. |
| Core | MoengageEnvironment | This field denotes the environment for data reporting, such as LIVE for the live application or TEST for development, to prevent test data from affecting production analytics. |
| Core | Custom Proxy Domain | This field denotes the base custom proxy domain used to route SDK network traffic through your own subdomain. (Key: `com_moengage_core_custom_base_domain`) |
| Core | Enable Logging for Release build | This field denotes whether to activate SDK logging in the production version of your app. It is recommended to disable this in release builds to improve performance and prevent exposure of sensitive data. |
| Core | Log Level | This field denotes the verbosity of the logs generated by the SDK, typically ranging from detailed (VERBOSE = 0) to minimal (ERROR = 3), for debugging purposes. |
| Core | Integration Partner | This field denotes the name of any third-party integration partner you are using, which helps in attributing user acquisition or specific events to that partner. |
| Core | Cache Connection | This field denotes the configuration for how the SDK caches data locally before sending it to MoEngage servers, helping to manage network usage and offline tracking. |
| **Data Tracking** | Track Device Information | This field denotes whether the SDK should track standard device attributes such as the device model, OS version, GAID, and app version. |
| Data Tracking | Enable Carrier Tracking | This field denotes whether the SDK should collect and send the user's mobile carrier information (e.g., Verizon, T-Mobile) for segmentation. |
| Data Tracking | Enable Screen Filtering by Package | This field denotes whether to enable the package-based filtering specified in Screen Tracking Whitelisted Packages. |
| Data Tracking | Screens to Exclude from Tracking | This field denotes a comma-separated list of Android Activity names to be excluded from automatic screen tracking, preventing data collection from sensitive or irrelevant screens. |
| Data Tracking | Enable Background Data Sync | This field denotes whether the SDK is permitted to synchronize data with MoEngage servers while the application is running in the background. |
| Data Tracking | Enable Periodic Data Sync | This field denotes the time interval in milliseconds at which the SDK syncs batched data with MoEngage servers if periodic sync is enabled. |
| **Push Notification** | Push Token Retry Interval(s) | This field denotes the time interval in seconds that the SDK should wait before attempting to resend a push notification that failed to be delivered. |
| Push Notification | Push Notification Small Icon | This field denotes the resource name of the drawable to be used as the small icon for all push notifications from your app. |
| Push Notification | Push Notification Large Icon | This field denotes the resource name of the drawable to be used as the large icon for push notifications. |
| Push Notification | Push Notification Color | This field denotes the hexadecimal color code (e.g., #FFFFFF) used to accent push notifications, affecting elements like the app name and action buttons. |
| Push Notification | Group Multiple Notifications in Drawer | This field denotes the key used to group multiple notifications from your app into a single, stacked notification in the system tray. |
| Push Notification | Enable Push Notification Back Stack Building | This field denotes whether tapping a notification should rebuild the app's task stack, ensuring proper back-button navigation. |
| Push Notification | Enable Notification Large Icon Display | This field denotes whether to show the specified large icon in push notifications. |
| Push Notification | Enable Heads-Up Notification | This field denotes whether to allow high-priority notifications to appear as a floating "heads-up" banner at the top of the screen. |
| Push Notification | Configure FCM Registration | This field denotes the server key from your Firebase Cloud Messaging (FCM) project, which is required to send push notifications to Android devices. |
| Push Notification | Configure Huawei Push Kit Registration | This field denotes the app secret key from your Huawei Mobile Services (HMS) project, required for sending push notifications to Huawei devices. |
| Push Notification | Enable RTT Background Sync | This field denotes whether to enable Real-Time Triggers (RTT) background sync, allowing for more immediate campaign actions based on user behavior. |
| **In-apps** | Screens to Suppress In-Apps | This field denotes a comma-separated list of Android Activity names on which in-app messages should not be displayed. |
| In-apps | Show In-App in New Activity | This field denotes whether in-app messages should be displayed within a new, dedicated Android Activity instead of overlaying the current one. |
| **Cards** | Cards Placeholder Image | This field denotes a URL for a placeholder image that is displayed while the actual Card content is loading. |
| Cards | Cards Empty Inbox Image | This field denotes a URL for an image to be displayed when the user's Card inbox is empty. |
| Cards | Cards Date Format | This field denotes the desired date format (e.g., "dd-MMM-yyyy") for displaying timestamps on Card elements in the UI. |
| Cards | Enable Swipe to Refresh the Cards | This field denotes whether users can pull down on the Card inbox screen to refresh its content. |
| **Security** | Enable Storage Encryption | This field denotes whether to encrypt the MoEngage data that is stored locally on the user's device, enhancing data security. |
| Security | Enable Network Encryption | This field denotes whether to encrypt the data transmitted between the SDK and MoEngage's servers, securing data in transit. |
| Security | Enable JWT Authorisation | This field denotes whether to enable JSON Web Token (JWT) based authorization for authenticating requests from the SDK to the MoEngage backend. |
**iOS SDK Configuration**
| Section | Field Name | Description |
| :---------------- | :--------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Core** | MoEngage Workspace ID | This field denotes the unique identifier that links your application to a specific workspace within your MoEngage dashboard. |
| Core | Moengage Project ID | This field denotes the unique identifier associated with a specific project if you have [Portfolio](https://help.moengage.com/hc/en-us/articles/40394603054100-Portfolio) feature enabled for your workspace. |
| Core | Moengage Data Center | This field denotes the geographical location of the MoEngage server (e.g., 1 for US, 2 for EU) where your app's data will be stored and processed. |
| Core | MoengageEnvironment | This field denotes the environment for data reporting, such as PROD for the live application or DEV for development, to prevent test data from affecting production analytics. By default, the environment is picked from the build configuration. |
| Core | Custom Proxy Domain | This field denotes the base custom proxy domain used to route SDK network traffic through your own subdomain. (Key: `CustomBaseDomain`) |
| Core | Enable Logging for Release & Debug build | This field denotes whether to activate SDK logging in your app's production version. It is recommended that you disable this in release builds. |
| Core | Integration Partner | This field denotes the name of any third-party integration partner, which helps in attributing user acquisition or specific events to that partner. |
| Core | App Group Name | This field denotes the App Group ID, which allows the main app to share data with its associated extensions, such as Notification Service Extensions. |
| **Data Tracking** | Enable Periodic Data Sync | This field denotes whether to batch and send tracked data to MoEngage at a set interval rather than in real time. Enabling this by default can optimize battery and network usage. |
| **In-apps** | Padding for Inapp | This field denotes the amount of padding (in points) as a safe area to apply around the content of in-app messages to control their spacing and layout. |
| In-apps | Provide Deeplink Call back | This field denotes whether to provide a callback method to the host application for custom handling of deep links triggered from in-app messages. |
| **Security** | Enable Storage Encryption | This field denotes whether to encrypt the MoEngage data that is stored locally on the user's device, enhancing data security. Encryption is not enabled by default. |
| Security | Enable Network Encryption | This field denotes whether to encrypt the data transmitted between the SDK and MoEngage's servers, securing data in transit. Encryption is not enabled by default. |
| Security | JWT Authorization Enabled | This field denotes whether to enable JSON Web Token (JWT) based authorization for authenticating requests from the SDK to the MoEngage backend. |
## Configuration parameters
Add the properties listed below inside the react-native-expo-moengage plugin entry in your app.json or app.config.js file. These parameters control the plugin's build-time behavior, such as linking native modules and pointing to your configuration files.
1. Open your app.json or app.config.js file.
2. Add react-native-expo-moengage to the plugins array.
```json JSON theme={null}
[
"react-native-expo-moengage",
{
"android": {
"configFilePath": "assets/moengage/android_initilisation_config.xml",
"smallIconPath": "assets/moengage/small_icon.png",
"largeIconPath": "assets/moengage/large_icon.png",
"disableMoEngageDefaultBackupFile": false,
"includeFirebaseMessagingDependencies": true,
"isExpoNotificationIntegration": true,
"shouldIncludeMoEngageFirebaseMessagingService": true
}
}
]
```
| Key | Description |
| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| configFilePath | Specifies the path to the configuration file (.xml) containing your core MoEngage SDK settings. |
| smallIconPath | Specifies the path to the small icon to be used in push notification. |
| largeIconPath | Specifies the path to the large icon to be used in push notification. |
| disableMoEngageDefaultBackupFile | MoEngage necessitates the exclusion of specific files during backup. This flag is designed to configure this process. If enabled, the configuration will be automatically included; otherwise, you need to add it manually. For more info, refer [here](/developer-guide/android-sdk/sdk-integration/basic-integration/exclude-mo-engage-storage-file-from-auto-backup). |
| includeFirebaseMessagingDependencies | The plugin includes the Firebase Cloud Messaging (FCM) library required for push. |
| isExpoNotificationIntegration | Set to true to ensure compatibility and correctly route push payloads when using the expo-notifications library alongside the MoEngage notification service. |
| shouldIncludeMoEngageFirebaseMessagingService | If enabled, the notification service is included by MoEngage; otherwise, you must pass the payload to the MoEngage SDK. |
```json JSON theme={null}
[
"react-native-expo-moengage",
{
"apple": {
"configFilePath": "assets/moengage/MoEngage-Config.plist",
"pushNotificationImpressionTrackingEnabled": true,
"richPushNotificationEnabled": true,
"pushTemplatesEnabled": true,
"deviceTriggerEnabled": true,
"liveActivityTargetPath": "assets/moengage/LiveActivity"
}
}
],
```
| Key | Description |
| ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| configFilePath | Specifies the path to the MoEngage configuration plist file relative to the application project root path. The data in this plist file is added to the MoEngage key in the application's Info.plist. If no path is provided, assets/moengage/MoEngage-Config.plist is assumed to be the path. |
| pushNotificationImpressionTrackingEnabled | Specifies whether to enable push notification delivery impression tracking. The default value is true if not provided. |
| richPushNotificationEnabled | Specifies whether to enable rich media content in push notifications. false if not provided. |
| pushTemplatesEnabled | Whether to enable push notification templates. False if not enabled. For more info, refer [here](/developer-guide/android-sdk/push/optional/push-templates). |
| deviceTriggerEnabled | Whether to enable device-triggered notifications. False if not enabled. For more info, refer [here](/developer-guide/ios-sdk/push/optional/real-time-triggers). |
| liveActivityTargetPath | Specifies the path to the Live Activity widget target files. It should include the widget's UI and payload definitions and any additional resources required by the widget. For more info, refer [here](/developer-guide/ios-sdk/push/optional/broadcast-live-activity). |
## Configure iOS App Extensions with EAS Build
EAS Build automatically handles standard iOS app configurations. However, if your app uses features that require separate native targets, you must configure them in `eas.json`. This includes features like:
* Notification Service Extensions (NSE): used for rich push and impression tracking.
* Notification Content Extensions (NCE): used for Push templates or Live Activities.
To configure iOS app extensions, add the `appExtensions` key to the `expo.extra.eas.build.experimental.ios` object. This configuration ensures EAS Build can correctly compile and sign the additional native targets.
```json JSON theme={null}
{
"expo": {
"extra": {
"eas": {
"build": {
"experimental": {
"ios": {
"appExtensions": [
{
"targetName": "MoEngageExpoRichPush",
"bundleIdentifier": "${YOUR Bundle Identifier}.MoEngageExpoRichPush",
"entitlements": {
"com.apple.security.application-groups": ["${YOUR AppGroup provided in apple.configFilePath}"]
}
},
{
"targetName": "MoEngageExpoPushTemplates",
"bundleIdentifier": "${YOUR Bundle Identifier}.MoEngageExpoPushTemplates",
"entitlements": {
"com.apple.security.application-groups": ["${YOUR AppGroup provided in apple.configFilePath}"]
}
},
{
"targetName": "MoEngageExpoLiveActivity",
"bundleIdentifier": "${YOUR Bundle Identifier}",
"entitlements": {
"com.apple.security.application-groups": ["${YOUR AppGroup provided in apple.configFilePath}"]
}
}
]
}
}
}
}
}
}
}
```
## Generate the native project files
After installing the package and adding the plugin entry, you must run the prebuild command. This command uses your configuration to generate the native Android and iOS directories for your project.
Run the following command:
```shell Shell theme={null}
npx expo prebuild
```
## Next steps
After you've added your configuration, the final step is to [initialize](/developer-guide/react-native-sdk/sdk-integration/expo/configure-the-moengage-expo-sdk) the SDK in your app's code.
# Initialization
Source: https://moengage.com/docs/developer-guide/react-native-sdk/sdk-integration/expo/initialization
Initialize the MoEngage SDK in your React Native Expo app to activate tracking and messaging.
## Overview
This is the final step to activate the MoEngage SDK. Calling the initialize method activates your configurations and lets the SDK start tracking data and handling messages.
You must complete the [installation](/developer-guide/react-native-sdk/sdk-integration/expo/installation) and [configuration](/developer-guide/react-native-sdk/sdk-integration/expo/configure-the-moengage-expo-sdk)guides before you initialize the SDK.
## Initialize the SDK
We recommend you initialize the SDK in your app's root component, which is usually App.js or App.tsx. To initialize the SDK, write the following code:
```TypeScript TypeScript theme={null}
import ReactMoE from 'react-native-moengage';
useEffect(() = {
ReactMoE.initialize("YOUR_Workspace_ID");
},[]);
```
The MoEngage SDK is now fully operational in your app.
To see detailed SDK logs in your console for development, initialize with a log configuration. This step is optional.
```TypeScript TypeScript theme={null}
import { MoEInitConfig, MoEPushConfig, MoEngageLogConfig, MoEngageLogLevel } from "react-native-moengage";
const moEInitConfig = new MoEInitConfig(
MoEPushConfig.defaultConfig(),
new MoEngageLogConfig(MoEngageLogLevel.DEBUG, isEnabledForReleaseBuild)
);
ReactMoE.initialize(YOUR Workspace ID, moEInitConfig);
```
The minimum supported version for `expo-notification` is *0.31.0*.
## Next steps
With the SDK initialized, you can start using other MoEngage features:
* [Track user events and attributes](/developer-guide/react-native-sdk/data-tracking/tracking-user-attributes-and-user-identity)
* [Set up push notifications](/developer-guide/react-native-sdk/push/basic/android-push-configuration)
* [Implement in-app messages](/developer-guide/react-native-sdk/in-app-messages/inapp-nativ)
# Installation
Source: https://moengage.com/docs/developer-guide/react-native-sdk/sdk-integration/expo/installation
Add the MoEngage SDK to your React Native Expo project using the npx expo install command.
## Overview
This guide shows you how to add the MoEngage SDK to your React Native Expo project.
**Prerequisites**
Make sure you have the following:
* A MoEngage account.
* A React Native project set up with Expo.
## Install the SDK Package
You'll add the MoEngage SDK to your project as a package. We recommend using `npx expo install` because it automatically installs a version that's compatible with your project's Expo SDK.
Open your terminal and go to your project's root directory.
Run the following commands:
```shell Shell theme={null}
npx expo install react-native-expo-moengage
```
```shell Shell theme={null}
npm install react-native-moengage
```
## Add the plugin to your configuration
Next, you need to add the MoEngage plugin to your Expo configuration file (`app.json` or `app.config.js`).
This step is required before generating the native project files.
```json theme={null}
{
"expo": {
"plugins": [
"react-native-expo-moengage"
]
}
}
```
## Next steps
The SDK is now installed. The next step is to [configure](/developer-guide/react-native-sdk/sdk-integration/expo/configure-the-moengage-expo-sdk) it with your app-specific details.
# Limitations
Source: https://moengage.com/docs/developer-guide/react-native-sdk/sdk-integration/limitations
Review features not supported or requiring native implementation in the MoEngage React Native plugin.
Compared to the Native Android or iOS SDKs there are a certain set of features we either do not support or require native Android or iOS implementation when using our React-Native plugin.
# Features not supported
* Action Buttons in iOS Notifications
# File Based Initialization
Source: https://moengage.com/docs/developer-guide/react-native-sdk/sdk-integration/react-native/sdk-initialization/file-based-initialization/file-based-initialization
Use file-based initialization to configure MoEngage React Native SDK with native config files.
## Overview
Starting with v10.5.0, the React Native SDK supports file-based initialization.
To streamline the integration process and minimize initialization errors, MoEngage supports Script-Based Initialization. This approach allows you to manage App IDs and configuration settings directly within native configuration files, keeping them separate from your application logic.
This article outlines how you can use the form-based interface to generate a validated code snippet for initialization and access module-specific configurations.
Alternatively, the SDK can be initialized manually. If you require this approach, please refer to the guide on [Framework Initialization](/developer-guide/react-native-sdk/sdk-integration/react-native/sdk-initialization/manual-initialization/framework-initialization).
## Script-based Initialization
Follow these steps to generate your initialization script:
Navigate to the [Initialization Website.](https://app-cdn.moengage.com/sdk/integration/config/index.html)
Configure the values based on your application requirements. Refer to the Configuration Parameters tables below for:
* [Android](/developer-guide/react-native-sdk/sdk-integration/react-native/sdk-initialization/file-based-initialization/file-based-initialization#android-configuration-reference)
* [iOS](/developer-guide/react-native-sdk/sdk-integration/react-native/sdk-initialization/file-based-initialization/file-based-initialization#ios-configuration-reference)
Click **Generate Code** at the bottom of the form.
## Android Configuration (XML)
For Android, initialization is handled by placing an XML configuration file in the application's resource directory.
### Android Configuration Reference
Below is the comprehensive list of keys available for `moengage.xml`.
| Category | XML Key Name | Type | Description |
| :----------- | :---------------------------------------------------- | :------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Core** | `com_moengage_core_workspace_id` | String | Specifies your App ID. This field is mandatory. |
| | `com_moengage_core_file_based_initialisation_enabled` | Boolean | Set to `true` to enable this feature. |
| | `com_moengage_core_data_center` | Integer | Default: `1`. For more info, refer to [Data Center values](/developer-guide/react-native-sdk/sdk-integration/react-native/sdk-initialization/file-based-initialization/file-based-initialization#data-center-values). |
| | `com_moengage_core_environment` | String | Supported values: `default`, `live`, or `test`. |
| | `com_moengage_core_custom_base_domain` | String | Specifies the base custom proxy domain to route SDK network traffic through your own subdomain. |
| | `com_moengage_core_integration_partner` | String | Specifies the core integration partner (e.g., `segment` or `mparticle`). |
| **Push** | `com_moengage_push_notification_small_icon` | Drawable | Resource ID for small icon. |
| | `com_moengage_push_notification_large_icon` | Drawable | Resource ID for large icon. |
| | `com_moengage_push_notification_color` | Color | Notification accent color. |
| | `com_moengage_push_notification_token_retry_interval` | Integer | Retry interval (in seconds) for token registration. |
| | `com_moengage_push_kit_registration_enabled` | Boolean | If `true`, SDK registers for push token. |
| **Logs** | `com_moengage_core_log_level` | Integer | `0` (No Log) to `5` (Verbose). Default: `3`. |
| | `com_moengage_core_log_enabled_for_release_build` | Boolean | If `true`, prints logs in release builds. |
| **Security** | `com_moengage_core_storage_encryption_enabled` | Boolean | Enables local storage encryption. |
| | `com_moengage_core_network_encryption_enabled` | Boolean | Enables payload encryption over the network. |
| **Sync** | `com_moengage_core_periodic_data_sync_enabled` | Boolean | Enables periodic data sync in the foreground. |
| | `com_moengage_core_background_data_sync_enabled` | Boolean | Enables periodic data sync in the background. |
| **In-App** | `com_moengage_inapp_show_in_new_activity_enabled` | Boolean | Required for specific TV/Android setups. |
**Troubleshooting**
If the XML file is missing or the `com_moengage_core_workspace_id` is empty, the SDK will throw a `ConfigurationMismatchError`.
### Add Configuration File
Place the generated file in `android/app/src/main/res/values/`.
\[placedholder for initialization snippet]
## iOS Configuration (Info.plist)
For iOS, initialization is handled by adding a configuration dictionary to your `Info.plist`.
### iOS Configuration Reference
Below is the comprehensive list of keys available for the `MoEngage` dictionary.
| Category | Plist Key | Type | Description |
| :----------- | :----------------------------------- | :--------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Core** | `WorkspaceId` | String | Specifies your App ID. Mandatory. |
| | `IsSdkAutoInitialisationEnabled` | Boolean | Set to `true` to enable SDK auto-initialisation. |
| | `DataCenter` | Integer | Mandatory. Default: `1`. Refer to [Data Center values](/developer-guide/flutter-sdk/sdk-integration/sdk-initialization/file-based-initialization/file-based-initialization#data-center-values). |
| | `IsTestEnvironment` | String / Boolean | Default: `$(SWIFT_ACTIVE_COMPILATION_CONDITIONS)`. |
| | `CustomBaseDomain` | String | Specifies the custom proxy domain subdomain. |
| | `IntegrationPartner` | String | Integration partner (e.g., `segment` or `mparticle`). |
| | `AppGroupName` | String | App Group name for sharing SDK data. |
| **Logs** | `IsLoggingEnabled` | Boolean | Set to `true` to enable SDK logs. |
| | `Loglevel` | Integer | `0` to `5`. Default: `2`. |
| **Security** | `IsStorageEncryptionEnabled` | Boolean | Enables local storage encryption. |
| | `KeychainGroupName` | String | Mandatory if storage encryption is enabled. |
| | `IsNetworkEncryptionEnabled` | Boolean | Enables payload encryption. |
| | `EncryptionEncodedTestKey` | String | Dashboard auto-populated string for Test environment. |
| | `EncryptionEncodedLiveKey` | String | Dashboard auto-populated string for Live environment. |
| **Sync** | `AnalyticsEnablePeriodicFlush` | Boolean | Enables periodic data flush. Default: `true`. |
| | `AnalyticsPeriodicFlushDuration` | Integer | Flush interval in seconds. Default: `60`. |
| **In-App** | `InAppDisplaySafeAreaInset` | Real | Safe area padding padding value. |
| | `InAppShouldProvideDeeplinkCallback` | Boolean | Provides callback on deeplink if `true`. |
### Data Center Values
Configure the integer corresponding to your region. Incorrect values will result in data loss.
| Data Center | Dashboard host |
| :---------- | :------------------------ |
| 1 | dashboard-01.moengage.com |
| 2 | dashboard-02.moengage.com |
| 3 | dashboard-03.moengage.com |
| 4 | dashboard-04.moengage.com |
| 5 | dashboard-05.moengage.com |
| 6 | dashboard-06.moengage.com |
### Update Info.plist
Open your project's `Info.plist` (found in `ios/ProjectName/`).
Create a new Top-Level Key named `MoEngage` of type `Dictionary`.
Add the configuration file content generated in the [Initialization Website.](https://app-cdn.moengage.com/sdk/integration/config/index.html)
**Warning** The key `IsSdkAutoInitialisationEnabled` uses the British spelling ('s'). Ensure you use the exact key name, or initialization will fail.
**XML Snippet Representation:**
```xml theme={null}
MoEngageWorkspaceIdYOUR_WORKSPACE_IDIsTestEnvironment$(SWIFT_ACTIVE_COMPILATION_CONDITIONS)|$(GCC_PREPROCESSOR_DEFINITIONS)DataCenter1CustomBaseDomaindata.example.comIsLoggingEnabled
```
## Framework Level Initialization
After you configure the native files, the initialization code in your hybrid framework is simplified.
### Android Native Setup
Add the following code to `android/app/src/main/java/com/your_app/MainApplication.java` (or `.kt`) inside the `onCreate()` method.
```kotlin theme={null}
import com.moengage.react.MoEInitializer
override fun onCreate() {
super.onCreate()
MoEInitializer.initializeDefaultInstance(application)
}
```
```java theme={null}
import com.moengage.react.MoEInitializer;
@Override
public void onCreate() {
super.onCreate();
// ... existing code
MoEInitializer.INSTANCE.initializeDefaultInstance(this);
}
```
### iOS Native Setup
Add the following code to your `AppDelegate` class inside the `didFinishLaunchingWithOptions` method.
```swift theme={null}
import MoEngageSDK
override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
// ... existing code
MoEngage.sharedInstance.initializeDefaultInstance()
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
```
```objectivec theme={null}
#import
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// ... existing code
[[MoEngageInitializer sharedInstance] initializeDefaultInstanceWithAdditionalReactConfig:[[MoEngageReactSDKDefaultInitializationConfig alloc] init]];
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
```
### Initialize React-Native Component
Initialize the MoEngage Plugin in the ***App.js*** or ***App.ts*** of your application once the component is mounted.
```typescript theme={null}
import ReactMoE from 'react-native-moengage';
ReactMoE.initialize("YOUR_Workspace_ID");
```
If you have a class-based component, you can initialize in the `render()` or `componentDidMount()`.
## Migration and Precedence
To migrate from manual code-based initialization to file-based approach, refer [here](/developer-guide/react-native-sdk/sdk-integration/sdk-initialization/file-based-initialization/migration-and-precedence).
## Environments (Test vs. Live)
You can configure Test/Live environments within these files:
* **Android:** Use `test`.
* **iOS:** Use `IsTestEnvironment`.
# Migration and Precedence
Source: https://moengage.com/docs/developer-guide/react-native-sdk/sdk-integration/react-native/sdk-initialization/file-based-initialization/migration-and-precedence
Migrate your MoEngage React Native SDK from manual initialization to file-based configuration.
### Android Migration Steps
1. **Add Configuration File:** Place the `moengage.xml` file in `src/main/res/values/moengage.xml`.
2. **Update Application Class:** Remove manual `MoEngage.Builder` logic and replace it with `initializeDefaultInstance`.
```java theme={null}
import com.moengage.react.MoEInitializer;
MoEInitializer.INSTANCE.initializeDefaultInstance(this);
```
```kotlin theme={null}
import com.moengage.react.MoEInitializer
MoEInitializer.initializeDefaultInstance(application)
```
### iOS Migration Steps
1. **Update Info.plist**: Add WorkspaceId, DataCenter, etc., directly to your `Info.plist` file.
2. **Update AppDelegate**: Remove manual `MoEngageSDKConfig` logic and call `initializeDefaultInstance`.
```objectivec theme={null}
#import
[[MoEngageInitializer sharedInstance] initializeDefaultInstanceWithAdditionalReactConfig:[[MoEngageReactSDKDefaultInitializationConfig alloc] init]];
```
```swift theme={null}
import MoEngageSDK
MoEngage.sharedInstance.initializeDefaultInstance()
```
### Precedence Rules
The source of configuration is determined by the initialization function called in your native code:
* **Android**:
* **File-Based Init:** `initializeDefaultInstance(context)` reads `moengage.xml`.
* **Code-Based Init:** `initialize(context, moEngage.Builder)` uses the configuration object and ignores XML.
* **iOS:** Auto-initialization via `Info.plist` occurs first. Calling the manual `initialize` method with a configuration object later will update the current instance.
# Android
Source: https://moengage.com/docs/developer-guide/react-native-sdk/sdk-integration/react-native/sdk-initialization/manual-initialization/android
Initialize the MoEngage SDK in your Android Application class for React Native integration.
# SDK Initialization
Get the Workspace ID from the Settings Page \_Dashboard --> Settings --> App --> Genera\_l on the MoEngage dashboard and initialize the MoEngage SDK in the ***Application*** class's ***onCreate()***.
It is recommended that you initialize the SDK on the main thread inside ***onCreate()*** and not create a worker thread and initialize the SDK on the worker thread.
```kotlin Kotlin theme={null}
import com.moengage.core.DataCenter
import com.moengage.core.MoEngage
import com.moengage.react.MoEInitializer
val moEngage = MoEngage.Builder(this, "YOUR_Workspace_ID", DataCenter.DATA_CENTER_X)
//replace X with your data center number
MoEInitializer.initializeDefaultInstance(applicationContext, moEngage)
```
```java Java theme={null}
import com.moengage.core.DataCenter;
import com.moengage.core.MoEngage;
import com.moengage.react.MoEInitializer;
MoEngage.Builder moEngage = new MoEngage.Builder(this, "YOUR_Workspace_ID", [YOUR_DATA_CENTER]);
MoEInitializer.INSTANCE.initializeDefaultInstance(getApplicationContext(), moEngage);
```
Following details of the different data centers you need to set based on the dashboard hosts
| Data Center | Dashboard host |
| -------------------------- | ------------------------- |
| DataCenter.DATA\_CENTER\_1 | dashboard-01.moengage.com |
| DataCenter.DATA\_CENTER\_2 | dashboard-02.moengage.com |
| DataCenter.DATA\_CENTER\_3 | dashboard-03.moengage.com |
| DataCenter.DATA\_CENTER\_4 | dashboard-04.moengage.com |
| DataCenter.DATA\_CENTER\_5 | dashboard-05.moengage.com |
| DataCenter.DATA\_CENTER\_6 | dashboard-06.moengage.com |
Refer to the [API reference doc](https://moengage.github.io/android-api-reference/core/com.moengage.core/-mo-engage/-builder/index.html) for a detailed list of possible configurations.
# Exclude MoEngage Storage File from Auto-Backup
This is a mandatory integration step and is very essential to prevent your data from getting corrupted. Android's auto back-up service periodically backs up Shared Preference files, Database files, etc, more details [here](https://developer.android.com/guide/topics/data/autobackup). This backup results in MoEngage SDK's identifiers being backed up and restored after re-install.This restoration of the identifier results in your data being corrupted and users not being reachable via push notifications.
To ensure data is not corrupted after a backup is restored, opt out of MoEngage SDK's storage files. Refer to [Exclude MoEngage Storage File from the Auto-Backup](/developer-guide/android-sdk/sdk-integration/basic-integration/exclude-mo-engage-storage-file-from-auto-backup) section of the documentation to learn more about which files to exclude.
# Framework Initialization
Source: https://moengage.com/docs/developer-guide/react-native-sdk/sdk-integration/react-native/sdk-initialization/manual-initialization/framework-initialization
Initialize the MoEngage React Native plugin in your App.js or App.ts after the component mounts.
# Initialize React-Native Component
Initialize the MoEngage Plugin in the **App.js** or ***App***\*.\*\*\****ts*** of your application once the component is mounted.
```java TypeScript theme={null}
import ReactMoE from 'react-native-moengage';
ReactMoE.initialize("YOUR_Workspace_ID");
```
**Example**
```java TypeScript theme={null}
import ReactMoE from 'react-native-moengage';
useEffect(() => {
ReactMoE.initialize("YOUR_Workspace_ID");
}, []);
```
If you have a class-based component then you can initialize in the ***render()*** or ***componentDidMount()***
## Initialize with Configuration (optional)
```java TypeScript theme={null}
import ReactMoE from 'react-native-moengage';
import { MoEInitConfig, MoEPushConfig, MoEngageLogConfig, MoEngageLogLevel } from "react-native-moengage";
const moEInitConfig = new MoEInitConfig(
MoEPushConfig.defaultConfig(),
new MoEngageLogConfig(MoEngageLogLevel.DEBUG, isEnabledForReleaseBuild)
);
ReactMoE.initialize(YOUR Workspace ID, moEInitConfig);
```
Make sure you are setting the Push/InApp callback listeners before calling the ***initialize()***.
Refer to the following for platform-specific initialization:
* [Android](/developer-guide/react-native-sdk/sdk-integration/react-native/sdk-initialization/manual-initialization/android)
* [iOS](/developer-guide/react-native-sdk/sdk-integration/react-native/sdk-initialization/manual-initialization/ios)
For more information about samples, refer to [React-Native Sample App](https://github.com/moengage/React-Native-Sample-App/tree/master).
# iOS
Source: https://moengage.com/docs/developer-guide/react-native-sdk/sdk-integration/react-native/sdk-initialization/manual-initialization/ios
Initialize the MoEngage SDK in your iOS AppDelegate for React Native integration.
For initializing the project, you'll need to provide the Workspace ID of your MoEngage App.
Login to your MoEngage account, go to Settings in the left panel of the dashboard. Under App Settings, you will find your Workspace ID.
## Code Initialisation
To initialize MoEngageSDK from ***application:didfinishlaunchingwithoptions*** call any one of the below initialization methods by passing MoEngageSDKConfig as parameter. Refer [doc](/developer-guide/ios-sdk/sdk-integration/basic/sdk-initialization) for more info on all the properties that can be configured using ***MoEngageSDKConfig***
Objective-C
```objectivec Objective-C theme={null}
/// @param sdkConfig MoEngageSDKConfig instance for SDK configuration
/// @param launchOptions Launch Options dictionary
- (void)initializeDefaultSDKConfig:(MoEngageSDKConfig*)sdkConfig andLaunchOptions:(NSDictionary*)launchOptions;
/// @param sdkConfig MoEngageSDKConfig instance for SDK configuration
/// @param isSdkEnabled Bool indicating if SDK is Enabled/Disabled
/// @param launchOptions Launch Options dictionary
- (void)initializeDefaultSDKConfigWithState:(MoEngageSDKConfig*)sdkConfig withSDKState:(MoEngageSDKState)sdkState andLaunchOptions:(NSDictionary*)launchOptions;
```
Sample code to initialize from ***application:didFinishLaunchingWithOptions:*** method:
```swift Swift theme={null}
import MoEngageSDK
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
//Add your MoEngage Workspace ID and Data center.
let sdkConfig = MoEngageSDKConfig(appId: "YOUR WorkspaceID", dataCenter: MoEngageDataCenter.data_center_0x) sdkConfig.consoleLogConfig = MoEngageConsoleLogConfig(isLoggingEnabled: true, loglevel: .verbose)
MoEngageInitializer.sharedInstance().initializeDefaultSDKConfig(sdkConfig, andLaunchOptions: launchOptions)
//Rest of the implementation of method
//-------
return true
}
```
```objectivec Objective-C theme={null}
#import
#import @implementation AppDelegate
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
MoEngageSDKConfig* sdkConfig = [[MoEngageSDKConfig alloc] initWithAppId:@"YOUR Workspace ID" dataCenter: MoEngageDataCenterData_center_0x];
sdkConfig.consoleLogConfig = [[MoEngageConsoleLogConfig alloc] initWithIsLoggingEnabled:true loglevel:MoEngageLoggerTypeVerbose];
[[MoEngageInitializer sharedInstance] initializeDefaultSDKConfig:sdkConfig andLaunchOptions:launchOptions];
return YES;
}
```
# Data Center
In case your app wants to redirect data to a specific zone due to any data regulation policy please configure the zone in the MOSDKConfig object.
Refer to the Data Center documentation for more information.
* [Android](/developer-guide/android-sdk/sdk-integration/basic-integration/data-center)
* [iOS](/developer-guide/ios-sdk/sdk-integration/basic/data-center)
# Android
Source: https://moengage.com/docs/developer-guide/react-native-sdk/sdk-integration/react-native/sdk-installation/android
Configure Android build settings and add required dependencies for the MoEngage React Native SDK.
# Configuring Build Settings
## Add Androidx Libraries
The MoEngage SDK depends on the lifecycle-process library for a few key features to work, and the latest version of lifecycle-process depends on the androidx.startup:startup-runtime library. Hence, do not remove the InitializationProvider component from the manifest. When adding other Initializers using the startup-runtime, make sure the Initializer for the lifecycle-process library is also added. Refer to the [documentation](https://developer.android.com/jetpack/androidx/releases/lifecycle#2.4.0) to know how to add the Initializer
The SDK also depends on a few Androidx libraries for its functioning. Add the below Androidx libraries in your application's ***build.gradle*** file or enable the required flag in the Package JSON file.
### Configure in the Package JSON file
* Setting the includeAndroidXRequiredLibraries to `true` automatically adds the AndroidX libraries that are used by the SDK as a dependency.
* **Required AndroidX Libraries:** The MoEngage SDK requires the following core AndroidX dependencies:
* `androidx.core:core`
* `androidx.appcompat:appcompat`
* `androidx.lifecycle:lifecycle-process`
* Before enabling this flag, validate if your application's native Android project (`build.gradle`) already has compatible versions of these libraries installed. If your app already includes them, you may not need to pull them in again, which helps prevent version conflicts or duplicate dependency errors during the build process.
File - ***package.json***
```json JSON theme={null}
{
"moengage": {
"includeAndroidXRequiredLibraries": true
}
}
```
### Configure in the Gradle file
Skip this step if ***includeAndroidXRequiredLibraries***flag is enabled in previous step.
Path - ***android/app/build.gradle(.kts)***
```Groovy Groovy theme={null}
dependencies {
...
implementation("androidx.core:core:1.9.0")
implementation("androidx.appcompat:appcompat:1.4.2")
implementation("androidx.lifecycle:lifecycle-process:2.7.0")
}
```
## Feature Modules (optional)
To include optional modules from the MoEngage SDK based on your feature requirements, you can use the provided flags. By default, these modules are not included in your project.
You can configure this by adding a new "moengage" key to the root level of your project's package.json file.
Inside this object, you can pass specific feature flags:
* true: Instructs the build system to download and link the required native dependencies for that specific module.
* false (or omitting the key): Excludes the module from your project. By default, all optional modules are excluded to help keep your overall app size optimized.
File - ***package.json***
```json JSON theme={null}
{
"moengage": {
"richNotification": true,
//Required for Push Templates
"encryption": true,
//Required for Add-On-Security
"pushAmp": true,
//Required for Push Amplification
"hmsPushkit": true,
//Required for HMS PushKit
"deviceTrigger": true
//Required for Device Triggered
}
}
```
### Documentation For Optional Feature Flag
* [Push Templates](/developer-guide/android-sdk/push/optional/push-templates)
* [Add-On-Security](/developer-guide/android-sdk/sdk-integration/advanced-or-optional/add-on-security)
* [Push Amplification](/developer-guide/android-sdk/push/optional/push-amplification)
* [HMS PushKit](/developer-guide/android-sdk/push/optional/push-amp-plus/configuring-hms-push-kit)
* [Device Triggered](/developer-guide/android-sdk/push/optional/device-triggered)
# Framework Dependency
Source: https://moengage.com/docs/developer-guide/react-native-sdk/sdk-integration/react-native/sdk-installation/framework-dependency
Install the MoEngage React Native plugin using npm and link your native dependencies.
Install the MoEngage React Native plugin using the npm package manager.
Link your native dependencies using the following code:
```shell Shell theme={null}
$ npm install react-native-moengage
# required only if you are using versions that do not support auto linking
# This command is removed in version 0.69 of react-native
$ react-native link react-native-moengage
```
A working Sample App can be found [here](https://github.com/moengage/React-Native/tree/master/SampleApp).
After installing the plugin use the following platform-specific configuration.
* [Android](/developer-guide/react-native-sdk/sdk-integration/react-native/sdk-installation/android)
* [iOS](/developer-guide/react-native-sdk/sdk-integration/react-native/sdk-installation/ios)
# iOS
Source: https://moengage.com/docs/developer-guide/react-native-sdk/sdk-integration/react-native/sdk-installation/ios
Set up iOS dependencies for the MoEngage React Native SDK with Turbo architecture support.
We now offer support for turbo architecture starting from version 10.0.0.
To run the application in the new architecture, follow these steps:
1. Navigate to the iOS folder.
2. Run the command ***RCT\_NEW\_ARCH\_ENABLED=1 bundle exec pod install*** to install the necessary dependencies.
To run the application in the old react architecture, follow these steps:
1. Navigate to the iOS folder.
2. Run the command ***pod install*** to install the necessary dependencies
# Troubleshooting and FAQs - React Native
Source: https://moengage.com/docs/developer-guide/react-native-sdk/troubleshooting-and-faqs/troubleshooting-and-faqs-react
Find answers to common MoEngage React Native SDK issues with push, callbacks, and in-app messages.
# Android - Why are notifications not working in the background or killed state?
Ensure that the MoEngage SDK is initialised in the main thread in the Android Native application class.
Sample code for initialisation - [GitHub](https://github.com/moengage/React-Native-Sample-App/blob/master/SampleApplication/android/app/src/main/java/com/moengage/sampleapp/MainApplication.java)
# Android - Why are callbacks not working in the background or killed state?
MoEngage callbacks must be registered in your app.js or app.ts, and after setting them up, you must call the MoEngage Plugin's initialize () method. Read more about [it here](/developer-guide/react-native-sdk/push/basic/push-callback#push-click-callback)
Sample code for callbacks - [GitHub](https://github.com/moengage/React-Native-Sample-App/blob/master/SampleApplication/App.tsx)
# Android - Why are inapp/nudge deep links not working?
MoEngage SDK doesn't handle in-app redirections by default except for rich landing pages; please refer to the documentation here. You must implement in-app click callback methods in your app.ts or app.js and call the moengage plugin initialise() method after you register for callbacks. In these callbacks, you will have to write code to extract navigation information and handle the redirection according to your preference. Callback documentation is [given here](/developer-guide/react-native-sdk/in-app-messages/inapp-nativ#inapp-callbacks).
Sample code for inapp/nudge callbacks - [GitHub](https://github.com/moengage/React-Native-Sample-App/blob/master/SampleApplication/App.tsx)
# Android - Why are inapp/nudge callbacks not working?
Refer to [this documentation](/developer-guide/react-native-sdk/in-app-messages/inapp-nativ#inapp-callbacks) to set up inapp callbacks. Additionally, you must register the callbacks in your application's app.js or app.ts, and after setting them up, you must call the MoEngage Plugin's initialize () method.
Sample code for inapp/nudge callbacks - [GitHub](https://github.com/moengage/React-Native-Sample-App/blob/master/SampleApplication/App.tsx)
# TV Support
Source: https://moengage.com/docs/developer-guide/react-native-sdk/tv/tv-support
Learn about MoEngage SDK support for Android TV and Apple TV in your React Native applications.
MoEngage supports your apps available on Android TV and Apple TV
Ensure that the [integration](/developer-guide/react-native-sdk/sdk-integration/react-native/sdk-installation/framework-dependency) and [initialization](/developer-guide/react-native-sdk/sdk-integration/react-native/sdk-initialization/manual-initialization/framework-initialization) is completed.
# Supported Features
MoEngage supports the following:
* [Data Tracking](/developer-guide/react-native-sdk/data-tracking/enable-advertising-identifier-tracking)
* [Self-handled InApp](/developer-guide/react-native-sdk/in-app-messages/inapp-nativ)
# 2023 and Older
Source: https://moengage.com/docs/developer-guide/release-notes/android-sdk/2023-and-older-1
View the 2023 and older release notes and changelogs for the MoEngage Android Native SDK.
You can now get notified whenever MoEngage releases a new version of the Android Native SDK. For more information, refer to [Subscribe to MoEngage SDK Releases](/developer-guide/release-notes/subscribe-to-moengage-sdk-releases/subscribe-to-mo-engage-sdk-releases).
## 14-12-2023
Catalog version - [3.2.3](https://github.com/moengage/android-dependency-catalog/blob/master/CHANGELOG.md#14-12-2023)
### InApp 7.1.2
* Bugfix
* Native in-apps were incorrectly showed in landscape mode.
# 29-11-2023
Catalog version - [3.2.2](https://github.com/moengage/android-dependency-catalog/blob/master/CHANGELOG.md#29-11-2023)
### Core 12.10.02
* Internal improvements.
### Cards UI 1.6.1
* Internal improvements.
* Updated minimum compatibility **core** version of **12.10.02**
### InApp 7.1.1
* Bugfix
* The background image is displayed on top and bottom for the gif/video nudge
* The background image is not displayed when the border radius is set to 0px in the template settings
* Updated minimum compatibility **core** version of **12.10.02**
### Rich Notification 4.7.2
* Internal improvements.
* Updated minimum compatibility **core** version of **12.10.02**
## 15-11-2023
Catalog version - [3.2.1](https://github.com/moengage/android-dependency-catalog/blob/master/CHANGELOG.md#15-11-2023)
### Core 12.10.01
* Bugfix
* Cached images not deleted immediately
### InApp 7.1.0
* Support for OR filter in Custom Event Trigger Criteria
### Rich Notification 4.7.1
* A progress bar will not be shown in templates if the application does not have ***android.permission.SCHEDULE\_EXACT\_ALARM*** when running on Android 13 or above. Only a timer would be shown.
## 25-10-2023
### Core 12.10.00
* Update Kotlin Version to **1.7.10**
* Android 14 Job Scheduler policy update
* Google Policy - API to delete User details. Refer [here](https://moengage.github.io/android-api-reference/core/com.moengage.core/%5Bandroid-jvm%5D-mo-e-core-helper/delete-user.html?query=fun%20deleteUser\(context:%20Context,%20appId:%20String,%20listener:%20UserDeletionListener\)) for more information.
### Cards Core 1.6.0
* Update Kotlin Version to **1.7.10**
* Updated minimum compatibility **core** version of **12.10.00**
### Cards UI 1.6.0
* Update Kotlin Version to **1.7.10**
* Updated minimum compatibility **core** version of **12.10.00**
### Device Trigger 2.6.0
* Update Kotlin Version to **1.7.10**
* Android 14 Job Scheduler policy update
* Updated minimum compatibility **core** version of **12.10.00**
### Encrypted Storage 1.3.0
* Update Kotlin Version to **1.7.10**
* Updated minimum compatibility **core** version of **12.10.00**
### Geofence 3.4.0
* Update Kotlin Version to **1.7.10**
* Updated minimum compatibility **core** version of **12.10.00**
### HMS Push Kit 4.7.0
* Update Kotlin Version to **1.7.10**
* Updated minimum compatibility **core** version of **12.10.00**
### InApp 7.0.0
* Support for Non-Intrusive Nudges
* Removed Embedded Nudges support.
* Added mandatory ***Glide*** library dependency for rendering in-apps with images and GIFs.
* Update Kotlin Version to **1.7.10**
* Updated minimum compatibility **core** version of **12.10.00**
### Inbox Core 2.6.0
* Update Kotlin Version to **1.7.10**
* Updated minimum compatibility **core** version of **12.10.00**
### Inbox UI 2.6.0
* Update Kotlin Version to **1.7.10**
* Updated minimum compatibility **core** version of **12.10.00**
### Integration Verifier 4.4.0
* Update Kotlin Version to **1.7.10**
* Updated minimum compatibility **core** version of **12.10.00**
### Push Amplification 4.6.0
* Update Kotlin Version to **1.7.10**
* Android 14 Job Scheduler policy update
* Updated minimum compatibility **core** version of **12.10.00**
### Push Amp Plus 6.6.0
* Update Kotlin Version to **1.7.10**
* Updated minimum compatibility **core** version of **12.10.00**
### Rich Notification 4.7.0
* Update Kotlin Version to **1.7.10**
* Handled template height for newer ViVo devices which has lower built-in height for collapsed and expanded notification state.
* Updated minimum compatibility **core** version of **12.10.00**
### Security 2.6.0
* Update Kotlin Version to **1.7.10**
* Updated minimum compatibility **core** version of **12.10.00**
## 12-10-2023
### HMS Push Kit 4.6.1
* Bugfix
* Fixing the crash due to HMS SDK not being able to connect to HMS Core APK
## 11-10-2023
### InApp 6.9.0
* Support for Delay in In-Apps
## 07-09-2023
### Core 12.9.03
* Bugfix
* `JvmOverloads` issue fix
### Geofence 3.3.2
* Updated minimum compatibility **core** version of **12.9.03**
### Integration Verifier 4.3.1
* Updated minimum compatibility **core** version of **12.9.03**
### Push Amplification 4.5.2
* Updated minimum compatibility **core** version of **12.9.03**
### Realtime Trigger 2.5.2
* Updated minimum compatibility **core** version of **12.9.03**
## 31-08-2023
### Core 12.9.02
* Internal improvements.
### Cards Core 1.5.1
* Internal improvements.
### Cards UI 1.5.1
* Internal improvements.
### InApp 6.8.1
* Internal improvements.
## 09-08-2023
### Core 12.9.01
* Support for configuring network caching via **NetworkRequestConfig**
* Gzip Support in SDK API calls
* Public API to enable instance agnostic logs
### Geofence 3.3.1
* Support for configuring network caching via **NetworkRequestConfig**
### Push Amplification 4.5.1
* Support for configuring network caching via **NetworkRequestConfig**
### Push Amp Plus 6.5.1
* Additional logs for better debugging.
### Realtime Trigger 2.5.1
* Support for configuring network caching via **NetworkRequestConfig**
## 18-07-2023
### Core 12.9.00
* Screen Name tracking improvement
* Support for Android Gradle Plugin **8.0.2**
* Bugfix
* Logging a large message to logcat causes ANR
### Cards Core 1.5.0
* Support for Android Gradle Plugin **8.0.2**
### Cards UI 1.5.0
* Support for Android Gradle Plugin **8.0.2**
### Device Trigger 2.5.0
* Support for Android Gradle Plugin **8.0.2**
### Encrypted Storage 1.2.0
* Support for Android Gradle Plugin **8.0.2**
### Geofence 3.3.0
* Support for Android Gradle Plugin **8.0.2**
### HMS Push Kit 4.6.0
* Support for Android Gradle Plugin **8.0.2**
### InApp 6.8.0
* Support for Android Gradle Plugin **8.0.2**
### Inbox Core 2.5.0
* Support for Android Gradle Plugin **8.0.2**
### Inbox UI 2.5.0
* Support for Android Gradle Plugin **8.0.2**
### Integration Verifier 4.3.0
* Support for Android Gradle Plugin **8.0.2**
* Bugfix
* Integration Verification is not working in Test Environment
### Push Amplification 4.5.0
* Support for Android Gradle Plugin **8.0.2**
### Push Amp Plus 6.5.0
* Support for Android Gradle Plugin **8.0.2**
### Rich Notification 4.6.0
* Support for Android Gradle Plugin **8.0.2**
### Security 2.5.0
* Support for Android Gradle Plugin **8.0.2**
## 27-06-2023
### Core 12.8.02
* Support for Array datatype in User Attributes.
### InApp 6.7.2
* Bugfix
* Self Handled campaign is not served if ***getSelfHandled()*** is called before SDK has synced with MoEngage Server.
* Memory leaks fixed.
## 08-06-2023
### Core 12.8.01
* Optimise download of push notification large icon.
* Bugfix
* Timer Template Chronometer shows different timing in expanded and collapsed modes.
### Rich Notification 4.5.1
* Optimise download of push notification large icon.
* Bugfix
* Timer Template Chronometer shows different timing in expanded and collapsed modes.
### Cards Core 1.4.1
* Cards sync API for self-handled cards
## 16-05-2023
### Core 12.8.00
* External library version updates
* androidx.core:core 1.8.0 --> 1.9.0
* com.google.firebase:firebase-messaging 23.0.8 --> 23.1.2
* Target & Compile SDK Version Update to 33
* Improved the SDK Initialisation Time on the main thread
* Additional Constructor with Data Center Support
* Removed deprecated APIs related to Inbox
| Then | Now |
| :------------------------------------------- | :------------------------------------------------------- |
| MoEngage.Builder(Application, YOUR\_APP\_ID) | MoEngage.Builder(Application, YOUR\_APP\_ID, DataCenter) |
| MoEngage.Builder#setDataCenter() | MoEngage.Builder(Application, YOUR\_APP\_ID, DataCenter) |
### Cards Core 1.4.0
* Target & Compile SDK Version Update to 33
* Requires core version **12.8.00** and above
### Cards UI 1.4.0
* Target & Compile SDK Version Update to 33
* Requires core version **12.8.00** and above
### Encrypted Storage 1.1.0
* Target & Compile SDK Version Update to 33
* Requires core version **12.8.00** and above
### Geofence 3.2.0
* Target & Compile SDK Version Update to 33
* Requires core version **12.8.00** and above
### HMS Push Kit 4.5.0
* Target & Compile SDK Version Update to 33
* Requires core version **12.8.00** and above
* External library version updates
* com.huawei.hms:push 6.5.0.300 --> 6.10.0.300
* com.huawei.agconnect:agcp 1.6.5.300 --> 1.8.0.300
### InApp 6.7.0
* Target & Compile SDK Version Update to 33
* Requires core version **12.8.00** and above
### Inbox Core 2.4.0
* Target & Compile SDK Version Update to 33
* Requires core version **12.8.00** and above
### Inbox UI 2.4.0
* Target & Compile SDK Version Update to 33
* Requires core version **12.8.00** and above
### Integration Verifier 4.2.0
* Target & Compile SDK Version Update to 33
* Requires core version **12.8.00** and above
### Rich Notification 4.5.0
* Support for Encrypting data stored in local storage
### Push Amplification 4.3.0
* Target & Compile SDK Version Update to 33
* Requires core version **12.8.00** and above
### Push Amp Plus 6.4.0
* Target & Compile SDK Version Update to 33
* Requires core version **12.8.00** and above
### Device Trigger 2.4.0
* Target & Compile SDK Version Update to 33
* Requires core version **12.8.00** and above
### Security 2.4.0
* Target & Compile SDK Version Update to 33
* Requires core version **12.8.00** and above
## 20-04-2023
### Core 12.7.02
* Bugfix
* Android opt-in In-app is shown on devices(lower than version 33) even when the notification permission enabled.
### InApp 6.6.1
* Bugfix
* Android opt-in In-app is shown on devices(lower than version 33) even when the notification permission enabled.
### Rich Notification 4.4.1
* Bugfix
* The image height in the image banner is not scaling to the available height of the image banner view.
## 10-04-2023
### Core 12.7.01
* Bugfix
* API calls are not working when the encrypted storage module is missing.
## 04-04-2023
### Core 12.7.00
* Support for new data center, Data Center 5
* Support for Encrypting data stored in local storage
* Changed APIs
| Then | Now |
| :-------------------------- | :--------------------------------- |
| MoEngage#enableEncryption() | MoEngage#configureNetworkRequest() |
### Cards Core 1.3.0
* Support for Encrypting data stored in local storage
### Cards UI 1.3.0
* Support for Encrypting data stored in local storage
### InApp 6.6.0
* Support for Encrypting data stored in local storage
### Inbox Core 2.3.0
* Support for Encrypting data stored in local storage
### Inbox UI 2.3.0
* Support for Encrypting data stored in local storage
### Rich Notification 4.4.0
* Support for Encrypting data stored in local storage
### Push Amplification 4.3.0
* Support for Encrypting data stored in local storage
### Push Amp Plus 6.3.0
* Support for Encrypting data stored in local storage
### Device Trigger 2.3.0
* Support for Encrypting data stored in local storage
### Geofence 3.1.0
* Support for Encrypting data stored in local storage
### HMS Push Kit 4.4.0
* Support for Encrypting data stored in local storage
### Encrypted Storage 1.0.0
* Support for Encrypting data stored in local storage
### Security 2.3.0
* Support for Encrypting data stored in local storage
### Integration Verifier 4.1.0
* Support for Encrypting data stored in local storage
## 30-03-2023
### Core 12.6.03
* Internal changes, it does not affect the integrating application.
## 16-03-2023
### Core 12.6.02
* Added additional check for **MoEAnalyticsHelper.setUniqueId()** empty string value.
### Rich Notification 4.3.2
* Bugfix
* XML resource file shrink error in release build.
### Geofence 3.0.1
* Updated the **play-services-location** version to **21.1.01**
### Cards UI 1.2.2
* Bugfix
* CardFragment inflation exception, Cannot inflate fragment without category name
## 14-02-2023
### Core 12.6.01
* Internal improvements. Does not affect the integrating application.
## 07-02-2023
### Core 12.6.00
* Support for Android 13 push notification Opt-in with rationale via In-Apps.
* Bugfix
* Multiple reports add calls executed in parallel.
### InApp 6.5.0
* Support for Android 13 push notification Opt-in with rationale via In-Apps.
## 31-01-2023
### Core 12.5.06
* Support for applications that do not have a launcher activity or have widgets only.
### Push Amplification 4.2.1
* Support for applications that do not have a launcher activity or have widgets only.
### Device Trigger 2.2.1
* Support for applications that do not have a launcher activity or have widgets only.
### Rich Notification 4.3.1
* Bugfix
* Progress bar update not working for Timer with Progress template when the user selects Remind Later action in the action button.
## 19-01-2023
### Core 12.5.05
* SDK now tracks DRM ID as a device identifier.
* ***configureGeofence()*** is deprecated. Use ***startGeofenceMonitoring()*** and ***stopGeofenceMonitoring()*** in the Geofence module.
* Security Improvement
* Launch Mode updated for Activity used for Snooze and Remind Later actions in Push Notifications.
* Bugfix
* Fix strict mode violation for an open Cursor
### InApp 6.4.2
* Bugfix
* Test InApp not working if the application is in the foreground, with the launcher activity on top and the launch mode of the activity being single instance.
### Geofence 3.0.0
* ***startGeofenceMonitoring()*** and ***stopGeofenceMonitoring()*** APIs are introduced to control Geofence better. Refer to the [integration documentation](/developer-guide/android-sdk/push/optional/location-triggered) for more details.
* Requires Core version **12.5.05** or above.
### Rich Notifications 4.3.0
* Support for templates for Android 12 and above.
* Requires Core version **12.5.05** or above.
## 19-12-2022
### Core 12.5.04
* Bugfix
* Handle cases where WebView is disabled by the user.
### InApp 6.4.1
* Bugfix
* Handle cases where WebView is disabled by the user.
### Cards UI 1.2.1
* Bugfix
* Handle cases where WebView is disabled by the user.
## 07-12-2022
### Core 12.5.03
* Added API to consume notification click from the client application for Push-Amp-Plus.
### Push-Amp-Plus 6.2.1
* Added API to consume notification clicks from the client application.
* Requires core version **12.5.03** or above.
## 01-12-2022
### Core 12.5.02
* Support for new data center, Data Center 4
* Optimization for notification posting, only a single channel is used in all cases.
* ***onNotificationCleared()*** will now be called if a user dismisses a persistent notification.
## 14-11-2022
### Core 12.5.01
* Bugfix
* Push Templates rendered incorrectly on Android 12 and above. Only affects users on SDK version 12.5.00.
## 04-11-2022
### Core 12.5.00
* Support for Push pre-processing callback.
### HMS Push Kit 4.3.0
* Support for Push pre-processing callback.
### Push Amp Plus 6.2.0
* Support for Push pre-processing callback.
### Rich Notification 4.2.0
* Support for Push pre-processing callback.
## 26-10-2022
### Behavioral Changes
* Build Configuration updated to the following:
* compileSdk 31
* minSdk 21
* targetSdk 31
### External Library Version Updates
* androidx.core:core 1.6.0 --> 1.9.0
* androidx.appcompat:appcompat 1.3.1 --> 1.4.2
### Core 12.4.00
* Support for Android Gradle Plugin 7.3.1
* External Library Version updates:
* androidx.lifecycle:lifecycle-process 2.4.0 --> 2.5.1
* com.google.firebase:firebase-messaging 23.0.0 --> 23.0.8
### Cards Core 1.2.0
* Support for Android Gradle Plugin 7.3.1
### Cards UI 1.2.0
* Support for Android Gradle Plugin 7.3.1
* External Library Version Updates:
* com.google.android.material:material 1.4.0 --> 1.6.1
* androidx.constraintlayout:constraintlayout 2.1.2 --> 2.1.4
* androidx.lifecycle:lifecycle-livedata 2.3.1 --> 2.5.1
### Geofence 2.2.0
* Support for Android Gradle Plugin 7.3.1
* **geofence-android-12** will no longer be supported. Use version 2.2.0 or above
### HMS Push Kit 4.2.0
* Support for Android Gradle Plugin 7.3.1
* External Library Version Updates:
* com.huawei.hms:push 6.3.0.304 --> 6.5.0.300
### InApp 6.4.0
* Support for Android Gradle Plugin 7.3.1
### Inbox Core 2.2.0
* Support for Android Gradle Plugin 7.3.1
### Inbox UI 2.2.0
* Support for Android Gradle Plugin 7.3.1
* External Library Version Updates:
* com.google.android.material:material 1.4.0 --> 1.6.1
* androidx.constraintlayout:constraintlayout 2.1.2 --> 2.1.4
* androidx.lifecycle:lifecycle-livedata 2.3.1 --> 2.5.1
### Push Amplification 4.2.0
* Support for Android Gradle Plugin 7.3.1
### Push Amp Plus 6.1.0
* Support for Android Gradle Plugin 7.3.1
### Realtime Trigger 2.2.0
* Support for Android Gradle Plugin 7.3.1
### Rich Notification 4.1.0
* Support for Android Gradle Plugin 7.3.1
### Security 2.2.0
* Support for Android Gradle Plugin 7.3.1
## 20-09-2022
### Core 12.3.02
* Handled trailing `#` in the action to open the dialer.
### InApp 6.3.3
* Handled trailing `#` in the action to open the dialer.
### Cards UI 1.1.2
* Handled trailing `#` in the action to open the dialer.
### Inbox UI 2.1.2
* Handled trailing `#` in the action to open the dialer.
### Rich Notification 4.0.1
* Handled trailing `#` in the action to open the dialer.
* Bugfix
* Stylized Notification is not getting updated properly when multiple notifications are disabled.
## 12-09-2022
### Core 12.3.01
* Support for Notification Runtime Permission for Android 13.
### InApp 6.3.2
* Bugfix
* Concurrent Modification crash for some OEMs on Android 10.
## 02-09-2022
### Core 12.2.05
* Support for new push templates.
### Rich Notification 4.0.0
* New templates added Timer, Timer with Progress bar, and Image banner with text overlay.
### Push Amp Plus 6.0.0
* Mi SDK update to Version 5.x.x, refer to the Configuring Xiaomi Push and update the integration.
## 18-08-2022
### InApp 6.3.0
* Removed support for cancellable
* Removed support primary widget.
## 12-08-2022
### Core 12.2.04
* Improved internal exception handling.
## 05-07-2022
### Core 12.2.03
* API added to check if the application is in the foreground.
* Bugfix
* Basic notification incorrectly marked as persistent.
## 15-06-2022
### Push Amp Plus 5.1.2
* Minor internal changes. No public-facing change.
## 19-05-2022
### Core 12.2.02
* Added API to fetch the current state of the SDK
### InApp 6.2.0
* Support InApp handling in onPause/onResume of Activity Lifecycle.
* Bugfix
* Activity is not unregistering on `onStop()`.
## 11-05-2022
### Core 12.2.01
* Fixed multiple Android Gradle Plugin version error.
### Cards Core 1.1.1
* Fixed multiple Android Gradle Plugin version error.
### Cards UI 1.1.1
* Fixed multiple Android Gradle Plugin version error.
### Geofence 2.1.1
* Fixed multiple Android Gradle Plugin version error.
### HMS Push Kit 4.1.1
* Fixed multiple Android Gradle Plugin version error.
### InApp 6.1.1
* Fixed multiple Android Gradle Plugin version error.
### Inbox Core 2.1.1
* Fixed multiple Android Gradle Plugin version error.
### Inbox UI 2.1.1
* Fixed multiple Android Gradle Plugin version error.
### Push Amplification 4.1.1
* Fixed multiple Android Gradle Plugin version error.
### Push Amp Plus 5.1.1
* Fixed multiple Android Gradle Plugin version error.
## Realtime Trigger 2.1.1
* Fixed multiple Android Gradle Plugin version error.
### Rich Notification 3.1.1
* Fixed multiple Android Gradle Plugin version error.
### Security 2.1.1
* Fixed multiple Android Gradle Plugin version error.
## 12.2.00 (09-05-2022)
### Core 12.2.00
* Moved GAID fetch to ads library
* Work-around for the crash **java.lang.AbstractMethodError** caused in the DefaultLifecycleObserver due to Android gradle plugin [issue](https://issuetracker.google.com/issues/194289155).
## 12.1.00 (29-04-2022)
### Core 12.1.00
* Support for Android Gradle Plugin 7.1.x
* Update Advertising Id tracking according to Google Play Policy. Advertising Id will not be tracked by the SDK by default, you can enable tracking based on user consent/preference.
### Cards Core 1.1.0
* Support for Android Gradle Plugin 7.1.x
### Cards UI 1.1.0
* Support for Android Gradle Plugin 7.1.x
### Geofence 2.1.0
* Support for Android Gradle Plugin 7.1.x
### HMS Push Kit 4.1.0
* Updated HMS Push SDK to 6.3.0.304
* Support for Android Gradle Plugin 7.1.x
### InApp 6.1.0
* Support for Android Gradle Plugin 7.1.x
* Support for application version filter for in-app campaigns triggered on custom events.
### Inbox Core 2.1.0
* Support for Android Gradle Plugin 7.1.x
### Inbox UI 2.1.0
* Support for Android Gradle Plugin 7.1.x
### Push Amplification 4.1.0
* Support for Android Gradle Plugin 7.1.x
### Xiaomi Push 5.1.0
* Support for Android Gradle Plugin 7.1.x
### Device Trigger 2.1.0
* Support for Android Gradle Plugin 7.1.x
### Rich Notification 3.1.0
* Support for Android Gradle Plugin 7.1.x
* Improved Image handling for tablets.
### Security 2.1.0
* Support for Android Gradle Plugin 7.1.x
## InApp 6.0.2 (12-04-2022)
* Bugfix
* Self-handled in-app shown and dismissed events are not tracked.
* Show in-app is not working in single activity with multiple fragments.
## 12.0.00 (16-03-2022)
### Behavioral Changes
* Build Configuration updated to the following:
* compileSdk 30
* minSdk 21
* targetSdk 30
* Starting from SDK version 12.0.00 following features are not integrated by default when adding moe-android-sdk as a dependency. If you are using these features refer to their respective integration document and update the dependencies.
* [InApp](/developer-guide/android-sdk/in-app-messages/in-app-nativ)
* [Push Amplification](/developer-guide/android-sdk/push/optional/push-amplification)
* [Device Trigger](/developer-guide/android-sdk/push/optional/device-triggered)
* APIs to initialize the SDK now throws *IllegalStateException* in case App-id is null or empty.
### External Library Version updates
* androidx.core:core 1.3.1 --> 1.6.0
* androidx.appcompat:appcompat 1.2.0 --> 1.3.1
* androidx.lifecycle:lifecycle-process 2.2.0 --> 2.4.0
* com.google.firebase:firebase-messaging 22.0.0 --> 23.0.0
* Kotlin Standard Library 1.4.20 --> 1.6.0
### Core 12.0.00
* *MoEHelper* deprecated and replaced with *MoEAnalyticsHelper*
* APIs to initialize the SDK now throws [*IllegalStateException*](https://developer.android.com/reference/java/lang/IllegalStateException) in case App-id is null or empty.
* Removed deprecated *AppUpdateReceiver.*
* Added configuration to disable Javascript across modules.
* *MoECallbacks* removed, all methods moved to [MoECoreHelper](https://moengage.github.io/android-api-reference/core/com.moengage.core/-mo-e-core-helper/index.html).
* Support for Notification tone dropped.
* Deprecated methods removed from *MoEngage.*
* FirebaseEventListener removed and replaced with [NonMoEngagePushListener](https://moengage.github.io/android-api-reference/moe-push-firebase/com.moengage.firebase.listener/-non-mo-engage-push-listener/index.html) and [TokenAvailableListener](https://moengage.github.io/android-api-reference/pushbase/com.moengage.pushbase.listener/-token-available-listener/index.html).
* Use [TokenAvailableListener](https://moengage.github.io/android-api-reference/pushbase/com.moengage.pushbase.listener/-token-available-listener/index.html) for token callback.
* Use [NonMoEngagePushListener](https://moengage.github.io/android-api-reference/moe-push-firebase/com.moengage.firebase.listener/-non-mo-engage-push-listener/index.html) for push notifications not sent from MoEngage Platform.
* Refer to the [Migration Guide](/developer-guide/android-sdk/migration/updating-to-12xxx-from-11xx) for more details.
### InApp 6.0.0
* InApp feature is no longer part of the Core SDK. InApp SDK needs to be added separately, refer to the [InApp](/developer-guide/android-sdk/in-app-messages/in-app-nativ) documentation for more details.
* InAppMessageListener removed and callbacks are broken down into multiple listeners: [OnClickActionListener](https://moengage.github.io/android-api-reference/inapp/com.moengage.inapp.listeners/-on-click-action-listener/index.html), [SelfHandledAvailableListener](https://moengage.github.io/android-api-reference/inapp/com.moengage.inapp.listeners/-self-handled-available-listener/index.html), [InAppLifeCycleListener](https://moengage.github.io/android-api-reference/inapp/com.moengage.inapp.listeners/-in-app-life-cycle-listener/index.html).
* InApp Display enhanced by moving the in-app below the status bar.
* Bugfix
* Fixed case where in-app does not cover the entire screen.
* Refer to the [Migration Guide](/hc/en-us/articles/4419611204116) for more details.
### Xiaomi Push 5.0.0
* Mi SDK updated to **4.8.6**
* MiPushEventListener removed and replaced with [NonMoEngagePushListener](https://moengage.github.io/android-api-reference/push-amp-plus/com.moengage.mi.listener/-non-mo-engage-push-listener/index.html) and [TokenAvailableListener](https://moengage.github.io/android-api-reference/pushbase/com.moengage.pushbase.listener/-token-available-listener/index.html).
* Use [TokenAvailableListener](https://moengage.github.io/android-api-reference/pushbase/com.moengage.pushbase.listener/-token-available-listener/index.html) for token callback.
* Use [NonMoEngagePushListener](https://moengage.github.io/android-api-reference/push-amp-plus/com.moengage.mi.listener/-non-mo-engage-push-listener/index.html) for push notifications not sent from MoEngage Platform.
* Refer to the [Migration Guide](/developer-guide/android-sdk/migration/updating-to-12xxx-from-11xx) for more details.
### Geofence 2.0.0
* Background sync for Geofence campaigns removed.
* Support for Geofence on Android 12.
### HMS Push Kit 4.0.0
* PushKitEventListener removed and replaced with [NonMoEngagePushListener](https://moengage.github.io/android-api-reference/hms-pushkit/com.moengage.hms.pushkit.listener/-non-mo-engage-push-listener/index.html) and [TokenAvailableListener](https://moengage.github.io/android-api-reference/pushbase/com.moengage.pushbase.listener/-token-available-listener/index.html).
* Use [TokenAvailableListener](https://moengage.github.io/android-api-reference/pushbase/com.moengage.pushbase.listener/-token-available-listener/index.html) for the token callback.
* Use [NonMoEngagePushListener](https://moengage.github.io/android-api-reference/hms-pushkit/com.moengage.hms.pushkit.listener/-non-mo-engage-push-listener/index.html) for push notifications not sent from MoEngage Platform.
* Refer to the [Migration Guide](/developer-guide/android-sdk/migration/updating-to-12xxx-from-11xx) for more details.
### Push Amplification 4.0.0
* The Push Amplification feature is no longer part of the Core SDK. Push Amplification SDK needs to be added separately, refer to the [Push Amplification](/developer-guide/android-sdk/push/optional/push-amplification) documentation for more details.
### Device Trigger 2.0.0
* The Device Trigger feature is no longer part of the Core SDK. Device Trigger SDK needs to be added separately, refer to the [Device Trigger](/developer-guide/android-sdk/push/optional/device-triggered) documentation for more details.
### Cards
* The current artifact i.e. **com.moengage:cards** is deprecated instead use **com.moengage:cards-ui**. Refer to the integration document for [Cards](/developer-guide/android-sdk/cards/cards) for more details.
### Rich Notification 3.0.0
* Compatibility update with core **12.0.00**
### Inbox Core 2.0.0
* Compatibility update with core **12.0.00**
### Inbox UI 2.0.0
* Compatibility update with core **12.0.00**
### Security 2.0.0
* Compatibility update with core **12.0.00**
## 11.6.02
* Update Advertising Identifier tracking in accordance with Google Play Policy. Android-id will no longer be tracked by the SDK by default. The setting for tracking Android-id in [TrackingOptoutConfig](https://moengage.github.io/android-api-reference/core/com.moengage.core.config/-tracking-opt-out-config/index.html) is ignored. Refer to [Device Identifier Tracking](/developer-guide/android-sdk/data-tracking/advanced-or-optional/device-identifier-tracking) to know more.
## 11.6.00 (14-03-2022)
* Push Templates disabled for Android 12.
## 11.5.00 (08-03-2022)
* Update Android-id tracking in accordance with Google Play Policy. Android-id will no longer be tracked by the SDK by default. The setting for tracking Android-id in [TrackingOptoutConfig](https://moengage.github.io/android-api-reference/core/com.moengage.core.config/-tracking-opt-out-config/index.html) is ignored. Refer to [Device Identifier Tracking](/developer-guide/android-sdk/data-tracking/advanced-or-optional/device-identifier-tracking) to know more.
## 11.4.04 (22-02-2022)
* Support for transparent background for HTML-based In-Apps.
* Improved exception handling.
## 11.4.03 (27-01-2022)
* Bugfix
* Campaign name not present in the self-handled in-app callback.
### Geofence 1.2.2 (27-01-2022)
* Bugfix
* Geofence campaigns are not triggered as `play-services-location` return an empty intent.
## Xiaomi Push 4.0.1 (10-12-2021)
* Internal Improvements
## Xiaomi Push 4.0.0 (01-12-2021)
* Xiaomi SDK version updated to `4.8.3`
## 11.4.02 (09-11-2021)
* Push Templates rendering improvement
### Geofence 1.2.1 (09-11-2021)
* Graceful handling of an already caught exception
### Rich Notification 2.4.0 (09-11-2021)
* Template rendering improvement
* Support to customize application name color
* Requires `moe-android-sdk` version `11.4.02` or above
### HMS PushKit 3.0.0 (09-11-2021)
* HMS SDK Update for Android 12 Guidelines
## 11.4.01 (29-09-2021)
* Nudge View will no longer be dismissed on back press
* Bugfixes
* InApp is not dismissed on back press in a few cases when Nudge is also visible.
## 11.4.00 (31-08-2021)
* Complying with Android 12 guidelines
* Support for custom HTML templates with in-apps
* Bugfixes
* Trigger-based in-app campaigns not sorted according to time and priority
### Geofence 1.2.00 (31-08-2021)
* Complying with Android 12 guidelines
* Requires `moe-android-sdk` version `11.4.00` or above
### HMS PushKit 2.4.00 (31-08-2021)
* Complying with Android 12 guidelines
* Requires `moe-android-sdk` version `11.4.00` or above
### Rich Notification 2.3.00 (31-08-2021)
* Complying with Android 12 guidelines
* Requires `moe-android-sdk` version `11.4.00` or above
## 11.3.01 (19-07-2021)
* Bugfix
* Application crashes if `glide` dependency is not added and a GIF is added as a background for in-app.
### Rich Notification 2.2.01 (19-07-2021)
* Bugfix
* Slide-specific re-direction not working for 3rd slide when the carousel has 3 cards.
### HMS PushKit 2.3.00 (19-07-2021)
* Push Kit SDK version updated to `5.3.0.304`
## 11.3.00 (02-07-2021)
* Improved handling of Gif files in in-app.
* Support for FCM 22.0.0 and above.
* Bugfix
* `MoERttHelper` not accessible.
### Inbox UI 1.0.01
* Bugfix
* APIs in `inbox-core` not accessible when `inbox-ui` is only added as a dependency.
## 11.2.01 (13-05-2021)
* Bugfix
* Tracking opt-out configuration not honoured in a few cases.
## 11.2.00 (10-05-2021)
* Internal storage re-write for performance and scale improvement.
* Removed deprecated APIs related to Inbox
| Then | Now |
| :----------------------------------------- | :-------------------------------------------------------- |
| MoEHelper#getUnreadMessagesCount() | MoEInboxHelper#getUnClickedMessagesCount(Context) |
| MoEHelper#getAllMessages() | MoEInboxHelper#fetchAllMessages(Context) |
| MoEHelper#setMessageClicked() | MoEInboxHelper#trackMessageClicked(Context, InboxMessage) |
| MoEHelper#trackNotificationClickedByTime() | NA |
* Bugfix
* Self-handled Smart Trigger in-app not delivered when the application is in landscape orientation.
### Cards 2.1.00 (10-05-2021)
* Compatible with Core version `11.2.00` and above
### Geofence 1.1.00 (10-05-2021)
* Compatible with Core version `11.2.00` and above
### HMS PushKit 2.2.00 (10-05-2021)
* Compatible with Core version `11.2.00` and above
### Xiaomi Push 3.2.00 (10-05-2021)
* Compatible with Core version `11.2.00` and above
### Rich Notification 2.2.00 (10-05-2021)
* Compatible with Core version `11.2.00` and above
### Inbox 1.0.00 (10-05-2021)
* `addon-inbox` module deprecated and broken down moved to separate artifacts `inbox-core` and `inbox-ui`.
* Compatible with Core version `11.2.00` and above
* Deprecated APIs
| Then | Now |
| :------------------------------------------------------------- | :----------------------------------------------------------- |
| com.moengage.addon.inbox.MoEInboxHelper | com.moengage.inbox.core.MoEInboxHelper |
| com.moengage.addon.inbox.listener. OnMessagesAvailableListener | com.moengage.inbox.core.listener.OnMessagesAvailableListener |
| com.moengage.addon.inbox.InboxMessageClickCallback | com.moengage.inbox.ui.listener.OnMessageClickListener |
| com.moengage.addon.inbox.MoEInboxActivity | com.moengage.inbox.ui.view\.InboxActivity |
| com.moengage.addon.inbox.InboxFragment | com.moengage.inbox.ui.view\.InboxFragment |
| com.moengage.addon.inbox.DefaultInboxAdapter | com.moengage.inbox.ui.adapter.sdkdefault.DefaultInboxAdapter |
| com.moengage.addon.inbox.InboxManager.ViewHolder | com.moengage.inbox.ui.adapter.ViewHolder |
| com.moengage.addon.inbox.InboxManager.InboxAdapter | com.moengage.inbox.ui.adapter.InboxAdapter |
## 11.1.00 (14-04-2021)
* Internal changes for fixing OEM-specific navigation issues in Push Templates.
### Rich Notification 2.1.00 (14-04-2021)
* Expand indicator/arrow removed from UI.
* Bugfix
* Fixing navigation not working on few OEMs
* Navigation not working after notification is Snoozed or Reminder is set
* Compatible with Core version `11.1.00` and above
### HMS Push Kit 2.1.00 (14-04-2021)
* Compatibility update for OEM-specific navigation issues.
* Compatible with Core version `11.1.00` and above
### Xiaomi Push 3.1.00 (14-04-2021)
* Compatibility update for OEM-specific navigation issues.
* Compatible with Core version `11.1.00` and above
## 11.0.05 (08-04-2021)
* Support for `lifecycle-process:2.3.0` and above
## 11.0.04 (24-02-2021)
* Publishing moved to Maven Central. All future updates would be published on Maven Central only.
### Cards 2.0.02 (24-02-2021)
* Ability to customize string for delete Card action
* Configuration to disable swipe to refresh.
* Publishing moved to Maven Central.
### Rich Notification 2.0.03 (24-02-2021)
* Publishing moved to Maven Central.
### Xiaomi Push 3.0.02 (24-02-2021)
* Publishing moved to Maven Central.
### HMS Push Kit 2.0.02 (24-02-2021)
* Publishing moved to Maven Central.
### Inbox 6.0.2 (24-02-2021)
* Publishing moved to Maven Central.
### Geofence 1.0.02 (24-02-2021)
* Publishing moved to Maven Central.
## 11.0.03 (28-01-2021)
* Internal bugfixes.
* `OnAppBackgroundListener` is removed.
### Rich Notification 2.0.02 (28-01-2021)
* Support for notification small icon color.
### Xiaomi Push 3.0.01 (28-01-2021)
* Compatible with Core version `11.0.03`
### HMS Push Kit 2.0.01 (28-01-2021)
* Compatible with Core version `11.0.03`
## 11.0.02 (11-01-2021)
* Target SDK version bumped to API level 29
* Starting SDK version `11.0.00` Geofence is not included when `moe-android-sdk` is added in the application. Refer to the [GeoFence Push](/developer-guide/android-sdk/push/optional/location-triggered) documentation.
* SDK has been re-packaged to have clear separation for internal files and exposed classes. Any class with the package name `com.moengage.*.internal.*` should not be used.
* InApp is no longer shown via Activity lifecycle callbacks. To show in-app `showInApp()` should be called in the Activity or Fragment. Refer to the [In-App NATIV](/developer-guide/android-sdk/in-app-messages/in-app-nativ) documentation.
* Source and Target Compatibility Updated to Java 8.
* Updated hosts used by the SDK. Refer to the [Network Security Configuration](/developer-guide/android-sdk/sdk-integration/advanced-or-optional/network-security-configuration) documentation.
* `OnNonMoEngagePushReceivedListener` removed, use `FirebaseEventListener`
* Support for Self-Handled In-Apps in Smart Trigger.
* SDK no longer tracks location by default.
* Refer to the [Updating to 11.x.xx](/developer-guide/android-sdk/migration/updating-to-11xxx-from-10xxx) for more details.
### Cards 2.0.00 (11-01-2021)
* Compatible with Core version `11.0.02`
* Bugfix
* `MoECardHelper#getUnClickedCardCount()` returns in-correct counter
### Push Templates 2.0.01 (11-01-2021)
* Compatible with Core version `11.0.02`
* Internal fixes
### Inbox 6.0.0 (11-01.2021)
* Compatible with Core version `11.0.02`
### HMS PushKit 2.0.00 (11-01.2021)
* Compatible with Core version `11.0.02`
### Xiaomi Push 3.0.00 (11-01-2021)
* Compatible with Core version `11.0.02`
## 10.6.00 (18-12-2020)
* API to enable/disable the SDK
* Support for multiple Firebase Event Listeners
* Deprecated methods
| Then | Now |
| :----------------------------------------------------------------------- | :----------------------------------------------------------------------- |
| MoEFireBaseHelper.getInstance().setEventListener(FirebaseEventListener)) | MoEFireBaseHelper.getInstance().addEventListener(FirebaseEventListener)) |
### Xiaomi Push 2.2.00 (18-12-2020)
* Support for multiple Event Listeners
* Compatible with Core version `10.6.00`
* Deprecated APIs
| Then | Now |
| :------------------------------------------------------------------- | :------------------------------------------------------------------- |
| MoEMiPushHelper.getInstance().setEventListener(MiPushEventListener)) | MoEMiPushHelper.getInstance().addEventListener(MiPushEventListener)) |
### HMS Push Kit 1.2.00 (18-12-2020)
* Multiple Event Listener
* Compatible with Core version `10.6.00`
* Deprecated APIs
| Then | Now |
| :--------------------------------------------------------------------- | :--------------------------------------------------------------------- |
| MoEPushKitHelper.getInstance().setEventListener(PushKitEventListener)) | MoEPushKitHelper.getInstance().addEventListener(PushKitEventListener)) |
### Cards 1.2.00 (18-12-2020)
* Compatible with Core version `10.6.00`
# 10.5.00 (10-11-2020)
* Merged Card, FCM, and Optout configurations into single APIs.
* Deprecated APIs
| Then | Now |
| :------------------------------------------------- | :------------------------------------------------------------- |
| MoEngage.Builder#setDateFormatForCard(String) | MoEngage.Builder#configureCards(CardConfig) |
| MoEngage.Builder#setEmptyInboxImageForCard(int) | MoEngage.Builder#configureCards(CardConfig) |
| MoEngage.Builder#setPlaceHolderImageForCard(int) | MoEngage.Builder#configureCards(CardConfig) |
| MoEngage.Builder#optOutTokenRegistration() | MoEngage.Builder#configureFcm(FcmConfig) |
| MoEngage.Builder#setSenderId(String) | MoEngage.Builder#configureFcm(FcmConfig) |
| MoEngage.Builder.optOutGAIDCollection() | MoEngage.Builder.configureTrackingOptOut(TrackingOptOutConfig) |
| MoEngage.Builder.optOutAndroidIdCollection() | MoEngage.Builder.configureTrackingOptOut(TrackingOptOutConfig) |
| MoEngage.Builder.optOutCarrierNameCollection() | MoEngage.Builder.configureTrackingOptOut(TrackingOptOutConfig) |
| MoEngage.Builder.optOutDeviceAttributeCollection() | MoEngage.Builder.configureTrackingOptOut(TrackingOptOutConfig) |
## 10.4.04 (05-11-2020)
* Making `MoEFireBaseHelper` API Java friendly.
* Bugfix
* Push notification is not being displayed after the snooze time delay
* Coupon Code dialog not shown when used with deep-link.
* Deprecated APIs
| Then | Now |
| :-------------------------------------------------- | :----------------------------------------- |
| MoEngage.Builder#setLogLevel(int) | MoEngage.Builder#enableLogs(@LogLevel int) |
| MoEngage.Builder#redirectDataToRegion(DATA\_REGION) | MoEngage.Builder#setDataCenter(DataCenter) |
### Inbox 5.3.0 (05-11-2021)
* Add helper APIs in Inbox Module.
### Cards 1.1.01 (05-11-2021)
* Making `MoECardHelper` API Java friendly.
### Push Amp Plus 2.1.01 (05-11-2021)
* Making `MoEMiPushHelper` API Java friendly.
## v10.4.03 (16th October 2020)
* Bugfix
* Abnormally high Session duration in some cases.
* Notification color not set properly.
## v10.4.02 (8th October 2020)
* Bugfix
* Token Callback was not being triggered for `FirebaseEventListener`
## v10.4.01 (25th September 2020)
* Bugfix
* InApp not being dismissed on the close button click in a few cases.
* Token registration not working on certain versions of FCM library when sender-id is passed.
### Rich Notification (25th September 2020)
* Image Banner Templates added.
# v10.4.00 (16th September 2020)
* SDK compiled with `androidx`. Migrated from support libraries.
* SDK requires `lifecycle-process` library.
* Bugfix
* Copy action button not working (affected 10.3.00).
### HMS Push Kit 1.1.00 (16th September 2020)
* Compatibility with Core SDK `10.4.00` (androidx).
### Xiaomi Push 2.1.00 (16th September 2020)
* Compatibility with Core SDK `10.4.00` (androidx).
### Rich Notifications 1.1.00 (16th September 2020)
* Compatibility with Core SDK `10.4.00` (androidx).
### Cards 1.1.00 (16th September 2020)
* Compatibility with Core SDK `10.4.00` (androidx).
### Inbox 5.2.0 (16th September 2020)
* Compatibility with Core SDK `10.4.00` (androidx).
## v10.3.02 (14th September 2020)
* Internal Changes only.
## v10.3.00 (28th August 2020)
* Support for Push Templates and Huawei Push Kit.
* Xiaomi Push is now configurable.
* Deprecated APIs
| Then | Now |
| :--------------------------------------------------------------------- | :--------------------------------------------------------------- |
| PushManager.getInstance().refreshToken() | MoEFireBaseHelper.getInstance().passPushToken() |
| PushManager.getInstance().setTokenObserver() | MoEFireBaseHelper.getInstance().setEventListener() |
| MoEFireBaseHelper.getInstance().setOnNonMoEngagePushReceivedListener() | MoEFireBaseHelper.getInstance().setEventListener() |
| MoEPushHelper.getInstance().handlePushPayload(Context, Bundle) | MoEFireBaseHelper.getInstance().passPushPayload(Context, Bundle) |
| MoEPushHelper.getInstance().handlePushPayload(Context, Map) | MoEFireBaseHelper.getInstance().passPushPayload(Context, Map) |
### Rich Notification 1.0.00 (28th August 2020)
* Stylized Basic Template & Simple Image Carousel Template.
* Requires Core version `10.3.00` or above.
### Xiaomi Push 2.0.00 (28th August 2020)
* Breaking change in integration. Refer to [Migrating to Push Amp+ 2.0.00](/developer-guide/android-sdk/migration/migrating-to-push-amp-plus-2000).
* Requires Core version `10.3.00` or above.
### HMS Push Kit 1.0.00 (28th August 2020)
* Requires Core version `10.3.00` or above.
### Inbox 5.1.0 (28th August 2020)
* Compatibility with Core and Push Notification.
* Requires Core version `10.3.00` or above.
## v10.2.02 (5th August 2020)
* Internal Bugfix
## v10.2.01 (1st August 2020)
* Additional Security on APIs on top of HTTPS.
* UI Elements are non-interactive when In-App pop-up is visible.
* Min compatible: push-amp-plus `1.2.00`, cards `1.0.01`.
### Push Amp Plus 1.2.00 (1st August 2020)
* GET\_TASKS Permission is no longer required.
### Cards 1.0.01 (1st August 2020)
* Compatibility with Core.
## v10.1.01 (7th July 2020)
* Support for Card Campaigns.
* API to customize token retry interval.
* Deprecated APIs
| Then | Now |
| :-------------------------------------------------------- | :------------------------------------------------------- |
| MoEHelper.getInstance().registerAppBackgroundListener() | MoECallbacks.getInstance().addAppBackgroundListener() |
| MoEHelper.getInstance().setOnLogoutCompleteListener() | MoECallbacks.getInstance().addLogoutCompleteListener() |
| MoEHelper.getInstance().removeLogoutCompleteListener() | MoECallbacks.getInstance().removeAppBackgroundListener() |
| MoEHelper.getInstance().unregisterAppBackgroundListener() | MoECallbacks.getInstance().removeLogoutListener() |
## v10.0.02 (18th March 2020)
* Support for India cluster.
## v10.0.00 (21st February 2020)
* Removed support for manifest-based integration, GCM library, and Fresco.
* Use Glide for GIFs in In-Apps.
* InApp Callbacks listener is now a concrete class.
* Refer to [Migration to 10.x.xx](/developer-guide/android-sdk/migration/migration-to-10xxx).
## v9.8.03 (4th February 2020)
* Fixing Strict Mode violations and improved Geofence triggering.
## v9.8.02 (10th January 2020)
* Support for tracking Notification Received/Clicked for custom push handlers.
* Deprecated APIs
| Then | Now |
| :---------------------------------------------------------------------------- | :------------------------------------------------------------------ |
| PushManager.getInstance().getPushHandler().handlePushPayload(Context, Map) | MoEPushHelper.getInstance().handlePushPayload(Context, Map) |
| PushManager.getInstance().getPushHandler().handlePushPayload(Context, Bundle) | MoEPushHelper.getInstance().handlePushPayload(Context, Bundle) |
| PushManager.getInstance().setMessageListener(Object) | MoEPushHelper.getInstance().setMessageListener(PushMessageListener) |
| MoEngageNotificationUtils.isFromMoEngagePlatform(Map) | MoEPushHelper.getInstance().isFromMoEngagePlatform(Map) |
| MoEngageNotificationUtils.isFromMoEngagePlatform(Bundle) | MoEPushHelper.getInstance().isFromMoEngagePlatform(Bundle) |
## v9.8.00 (23rd November 2019)
* Internal Update for Xamarin Support.
* Removed methods using `HashMap`; use `Map` instead.
## v9.7.04 (20th November 2019)
* Fix for deep-linking not working for action button on some devices.
## v9.7.03 (13th November 2019)
* Push Amp+ support for Partner Integrations.
## v9.7.02 (31st October 2019)
* Minor Bugfixes.
## v9.7.00 (10th September 2019)
* Performance improvement.
## v9.6.01 (26th August 2019)
* Internal optimizations.
## v9.6.00 (23rd August 2019)
* Support for user session and traffic source tracking.
* Deprecated `setExistingUser()` (use `setAppStatus()`) and `trackEvent(String, JSONObject)` (use `PayloadBuilder`).
## v9.4.04 (11th July 2019)
* Bugfix - Geofence callback listener.
* Deprecated several push listeners; use `PushMessageListener` class instead.
## v9.4.01 (16th April 2019)
* Support for Gradle 5+.
* Granular control for in-app messages.
## v9.3.02 (1st February 2019)
* Support for push registration for Instant Apps.
## v9.3.00 (4th January 2019)
* Internal optimisations.
## v9.2.03 (13th November)
* Support for ISO date format string in `Payload Builder`.
## v9.2.02 (18th October)
* Listener for App background and Notification Responsiveness support.
## v9.2.00 (5th October)
* Support for FCM Version 17.3.2 and above.
## v9.1.06 (19th September)
* API to enable Segment Bundle Integration.
## v9.1.05 (31st July)
* APIs to opt-out for background sync.
## v9.1.04 (3rd July 2018)
* Internal optimisations.
## v9.1.02 (14th June 2018)
* Exit Intent Notifications and fix for Alarm Manager play console warning.
## v9.1.01 (25th May 2018)
* GDPR Compliance. Refer to [GDPR Compliance documentation](/developer-guide/android-sdk/compliance/compliance).
## v9.0.02 (27th April)
* Integration moved from AndroidManifest to Code via `MoEngage.Builder`.
* Location tracking and IMEI collection disabled by default (opt-in available).
* Removed support for GCM library 7.3 and below.
## v8.5.00 (12th April)
* Minor Bug fixes.
## v8.4.03 (21st February)
* Push-Amp included as part of the SDK. Remove `addon-messaging` dependency.
## v8.4.02 (7th February)
* Tracking events for geo-fence hits and smart navigation for rating in-app.
## v8.3.02 (17th January)
* Min API level 14. Compiles with 26.1.0 support libraries.
* Ships with FCM by default. GCM must be included explicitly.
## v7.7.16 (29th September)
* Support for json array and object in `PayloadBuilder`.
## v7.7.15 (25th September)
* Locale Tracking optional and Event batching.
## v7.7.13 (6th September)
* Inbox expiry and deprecation of `gcm_msgttl`.
## v7.7.11 (1st August)
* Payload optimisations.
## v7.7.10 (20th July)
* Support for Android Studio 3.0.
## v7.7.06 (5th July)
* Opt-out from MoEngage extras from deep-link.
## v7.7.05 (21st June)
* Callbacks for Geofence transition.
## v7.7.04 (19th June)
* InApp minimum delay bug fix.
## v7.7.03 (13th June)
* App Links auto-verification fix.
## v7.7.02 (18th May)
* Improved notification rendering on OPPO and tracking Device locale.
## v7.7.01 (3rd May)
* Push to inbox bug fix.
## v7.7.00 (20th April)
* Integration Verification and Push Cleared Callback.
## v7.6.04 (10th March)
* Tracking additional info in notification impressions.
## v7.6.03 (27th February)
* Callback to handle notification click and Carousel customisation.
## v7.6.02 (13th February)
* Added Support for Baidu.
## v7.5.00 (19th January)
* Notification display Changes for Android N.
## v7.4.01 (16th November)
* Improved refresh token handling.
## v7.3.00 (15th November)
* Added support for native firebase listeners.
## v7.2.04 (9th November)
* Bugfixes.
## v7.2.01 (2nd November)
* Bugfixes.
## v7.1.03 (27th September)
* InApp Testing.
## v7.0.06 (18th August 2016)
* Push Callbacks for Received and Clicked.
## v7.0.03 (10th August 2016)
* Critical fix regarding tracking events.
## v7.0.02 (5th August 2016)
* InApp Api response changes.
## v7.0.00 (2nd August 2016)
* Modular SDK. features are pluggable. Refer to [migration documentation](/developer-guide/android-sdk/migration/Migrating-to-7-x-xx).
Please refer to the [migration documentation](/developer-guide/android-sdk/migration/Migrating-to-7-x-xx) while upgrading the SDK.
## v6.0.29 (14th July 2016)
* InApp Navigation Drawer Fix.
## v6.0.28 (29th June 2016)
* DB Upgrade Fix.
## v6.0.27 (27th June 2016)
* InApp and Carousel Action Bug Fix.
## v6.0.26 (21st June 2016)
* InApp Bug Fix and GCM Failure Event Tracking.
## v6.0.25 (10th June 2016)
* Snooze and Remind Later Bug Fixes.
## v6.0.23 (30th May 2016)
* Bugfixes.
## v6.0.21 (13th May 2016)
* Additional Fallbacks for push registration.
## v6.0.20 (11th May 2016)
* Listener for token receive/change and InApp rating bar bug fix.
## v6.0.18 (5th May 2016)
* InApp Bug Fix.
## v6.0.17 (29th April 2016)
* Location Bugfixes.
## v6.0.14 (21st April 2016)
* API Update.
## v6.0.13 (14th April 2016)
* Location Library Support for older play services.
## v6.0.02 (15th March 2016)
* Added Snooze/Remind Later Action Button.
## v6.0.01 (12th March 2016)
* Added Support for in-app Nativ. `NudgeView` initialisation changes.
## v5.3.29 (28th Jan 2016)
* Feature to skip Notification from being stored in Notification Center.
## v5.3.28 (27th Jan 2016)
* Bug Fixes.
## v5.3.24 (12th Jan 2016)
* Initialize SDK with Sender ID and App ID from Segment.
## v5.3.23 (7th Jan 2016)
* APIs to Optionally Opt Out from location tracking and GeoFencing.
## v5.3.22 (5th Jan 2016)
* Fixed issue with logout introduced in 5.3.20.
## v5.3.20 (23rd December 2015)
* Removed support for play services \< 8.1.
## v5.3.18 (18th December 2015)
* Location library support for all versions.
## v5.3.17 (14th December 2015)
* API for unregistering GCM token.
## v5.3.15 (7th December 2015)
* Push Messages Tagging and Notification with multiple action buttons.
## v5.3.09 (15th October 2015)
* Google Play Services 8.1.0 support.
## v5.3.00 (13th August 2015)
* Google Play Services 7.5 support. Control push using `PushMessageListener`.
## v5.2.2 (27th July 2015)
* Notification Color support for Android Lollipop.
## v5.1.9 (14th July 2015)
* Pre-caching images for in-app messages.
## v5.1.0 (9th July 2015)
* Geofencing requires no additional coding other than providing permission.
## v5.0.5 (9th July 2015)
* Pre-caching images for in-app messages and Google Ads SDK optional.
# 2024
Source: https://moengage.com/docs/developer-guide/release-notes/android-sdk/2024-1
View the 2024 release notes and changelogs for the MoEngage Android Native SDK.
You can now get notified whenever MoEngage releases a new version of the Android Native SDK. For more information, refer to [Subscribe to MoEngage SDK Releases](/developer-guide/release-notes/subscribe-to-moengage-sdk-releases/subscribe-to-mo-engage-sdk-releases).
Module Status Legend
■ Updated: Module version has been updated in this release.
■ Unchanged: Module remains on the previous version.
■ Deprecated: Module is deprecated and will be removed in a future release.
### Core SDK 13.05.01
Improvements:
* Migration from **JobScheduler** to **WorkManager**.
* SDK now includes **2.9.1** version of **androidx.work:work-runtime**.
### Cards Core 2.3.1
Improvements: Internal improvements for compatibility with **core:13.05.01**.
### Cards UI 2.4.1
Improvements: Internal improvements for compatibility with **core:13.05.01** and **cards-core:2.3.1**.
### InApp 8.7.0
Improvements: Improvement in **Video Nudge** button behavior.
### Inbox Core 3.2.1
Improvements: Internal improvements for compatibility with **core:13.05.01**.
### Inbox UI 3.2.1
Improvements: Internal improvements for compatibility with **core:13.05.01** and **inbox-core:2.4.1**.
### Integration Verifier 5.3.1
Improvements: Internal improvements for compatibility with **core:13.05.01**.
### Geofence 4.2.1
Improvements: Internal improvements for compatibility with **core:13.05.01**.
### Pushkit 5.1.1
Improvements: Internal improvements for compatibility with **core:13.05.01**.
### Push Amp 5.2.1
Improvements:
* Migration from **JobScheduler** to **WorkManager**.
* SDK now includes **2.9.1** version of **androidx.work:work-runtime**.
* Internal improvements for compatibility with **core:13.05.01**.
### Realtime Trigger 3.4.1
Improvements:
* Migration from **JobScheduler** to **WorkManager**.
* SDK now includes **2.9.1** version of **androidx.work:work-runtime**.
* Internal improvements for compatibility with **core:13.05.01**.
### Rich Notification 5.1.1
Improvements: Internal improvements for compatibility with **core:13.05.01**.
***
## 10th September 2024
### Core SDK 13.05.00
Fixes: A new user is created on the user's device identifier read fail from the database.
### Cards Core 2.3.0
What's New: Cards fetch on new user attribute unique ID set.
### Cards UI 2.4.0
What's New: Cards fetch on new user attribute unique ID set.
### InApp 8.6.0
What's New: Support for multiple Self-Handled InApps fetch [refer here](/developer-guide/android-sdk/in-app-messages/in-app-nativ).
Improvements: **SelfHandledAvailableListener** callback improvements:
* Callback on network failure.
### Inbox Core 3.2.0
What's New: API support to delete all messages, [**deleteAllMessages()**](/developer-guide/android-sdk/push/optional/notification-center#delete-all-inbox-message).
### Inbox UI 3.2.0
What's New: Inbox Core version updated to 3.2.0.
### Realtime Trigger 3.4.0
Improvements: Internal improvements, requires Core version **13.05.00**.
***
## 31st July 2024
### Core 13.03.00
What's New:
* AGP Version update from **8.2.2** to **8.4.0**
* Kotlin Version update from **1.7.10** to **1.9.23**
* Compile SDK version updated to 34
Fixes: Memory leak issue fix in Activity lifecycle handler.
### Cards Core 2.1.0
What's New:
* AGP Version update from **8.2.2** to **8.4.0**
* Kotlin Version update from **1.7.10** to **1.9.23**
* Compile SDK version updated to **34**
### Cards UI 2.2.0
What's New:
* AGP Version update from **8.2.2** to **8.4.0**
* Kotlin Version update from **1.7.10** to **1.9.23**
* Compile SDK version updated to **34**
### Encrypted Storage 2.1.0
What's New:
* AGP Version update from **8.2.2** to **8.4.0**
* Kotlin Version update from **1.7.10** to **1.9.23**
* Compile SDK version updated to **34**
### Geofence 4.1.0
What's New:
* AGP Version update from **8.2.2** to **8.4.0**
* Kotlin Version update from **1.7.10** to **1.9.23**
* Compile SDK version updated to **34**
### HMS PushKit 5.1.0
What's New:
* AGP Version update from **8.2.2** to **8.4.0**
* Kotlin Version update from **1.7.10** to **1.9.23**
* Compile SDK version updated to **34**
### InApp 8.4.0
What's New:
* AGP Version update from **8.2.2** to **8.4.0**
* Kotlin Version update from **1.7.10** to **1.9.23**
* Compile SDK version updated to **34**
* JSONArray / JSONObject support in UserAttributes for HTML campaign
Fixes: Crash fix for video non-intrusive inapp in some of the OEMs.
### Inbox Core 3.1.0
What's New:
* AGP Version update from **8.2.2** to **8.4.0**
* Kotlin Version update from **1.7.10** to **1.9.23**
* Compile SDK version updated to **34**
### Inbox UI 3.1.0
What's New:
* AGP Version update from **8.2.2** to **8.4.0**
* Kotlin Version update from **1.7.10** to **1.9.23**
* Compile SDK version updated to **34**
### Integration Verifier 5.1.0
What's New:
* AGP Version update from **8.2.2** to **8.4.0**
* Kotlin Version update from **1.7.10** to **1.9.23**
* Compile SDK version updated to **34**
### PushAmp 5.1.0
What's New:
* AGP Version update from **8.2.2** to **8.4.0**
* Kotlin Version update from **1.7.10** to **1.9.23**
* Compile SDK version updated to **34**
### Realtime Trigger 3.2.0
What's New:
* AGP Version update from **8.2.2** to **8.4.0**
* Kotlin Version update from **1.7.10** to **1.9.23**
* Compile SDK version updated to **34**
### RichNotification 5.1.0
What's New:
* AGP Version update from **8.2.2** to **8.4.0**
* Kotlin Version update from **1.7.10** to **1.9.23**
* Compile SDK version updated to **34**
### Security 3.1.0
What's New:
* AGP Version update from **8.2.2** to **8.4.0**
* Kotlin Version update from **1.7.10** to **1.9.23**
* Compile SDK version updated to **34**
***
## 10th June 2024
### Core 13.02.00
What's New:
* JSONArray and JSONObject support for User Attribute Tracking
* Deprecated `MoEngageBuilderKtx`
* Enforce SDK to specific environment
* Internal improvements
### Inbox UI 3.0.2
Improvements: Enforce SDK to specific environment.
### Inbox Core 3.0.2
Improvements: Enforce SDK to specific environment.
### Goefence 4.0.2
Improvements: Enforce SDK to specific environment.
### InApp 8.3.1
Fixes: Video nudge changes to black screen after app comes to foreground.
Improvements: Internal improvements.
### Integration Verifier 5.0.2
Improvements: Enforce SDK to specific environment.
### Push Amp 5.0.2
Improvements: Enforce SDK to specific environment.
***
## 16th May 2024
### Core 13.01.00
What's New: Adding support for Data Center 6.
### Cards UI 2.1.0
Improvements: Internal fixes and improvements.
### InApp 8.3.0
What's New:
* Adding support of JSONArray in triggered-based InApps.
* Removing the usage of the ***com.github.bumptech.glide:compiler***.
Fixes: Background Views are clickable when InApp is shown.
### Realtime Trigger 3.1.0
What's New: Adding support of JSONArray in triggered condition.
***
## 29th April 2024
### Core 13.00.03
Improvements: Internal Improvements.
### InApp 8.2.1
What's New:
* Intrusive TV InApp support for cross-platform frameworks.
* Internal Improvements.
* No longer needs additional API call for registering the Activity in the onResume() callback.
Deprecated Methods:
| Then | Now |
| :--------------------------------------------------- | :------------------------------------- |
| MoEInAppHelper#enableActivityRegistrationOnResume() | Default behavior, need not be enabled. |
| MoEInAppHelper#disableActivityRegistrationOnResume() | Default behavior, cannot be disabled. |
***
## 8th April 2024
### Core 13.00.00
What's New:
* Life cycle process library update to 2.7.0, use at least 2.6.2.
* AGP Version update from **8.0.2** to **8.2.2**.
* Restructuring APIs for Push Callbacks and Customisation:
* API with behaviour changes in ***PushMessageListener.kt***:
* ***onCreateNotification()***: Allows the application to return null as well. If null is returned SDK will render the notification with default SDK styling.
* ***isNotificationRequired()***: Calling ***super()*** is not required.
* ***onNotificationClick()***: API needs to return true/false. If the application wants to handle the re-direction the method should return true, else false.
Deprecated APIs:
| Then | Now |
| :------------------------------------------------- | :--------------------------------------------------------------------------------------- |
| MoEngage.Builder#configureGeofence() | MoEGeofenceHelper.startGeofenceMonitoring() & MoEGeofenceHelper.stopGeofenceMonitoring() |
| MoEngage#isSdkInitialised() | isSdkInitialised() |
| MoEngage#isSdkInitialised(YOUR\_APP\_ID) | isSdkInitialised(YOUR\_APP\_ID) |
| MoEngage#initialise(MoEngage) | MoEngage#initialiseDefaultInstance(MoEngage) |
| MoEngage.Builder#configureMiPush(MiPushConfig) | Support For MiPush removed |
| PushMessageListener#logNotificationClicked() | MoEPushHelper.getInstance().logNotificationClick() |
| PushMessageListener#logCampaignImpression() | MoEPushHelper.getInstance().logNotificationReceived() |
| PushMessageListener#onNonMoEngageMessageReceived() | NonMoEngagePushListener#onPushReceived() |
### Cards Core 2.0.0
What's New:
* AGP Version update from **8.0.2** to **8.2.2**
* Requires Core version **13.00.00 and above**
### Cards UI 2.0.0
What's New:
* AGP Version update from **8.0.2** to **8.2.2**
* Requires Core version **13.00.00 and above**
### Encrypted Storage 2.0.0
What's New:
* AGP Version update from **8.0.2** to **8.2.2**
* Requires Core version **13.00.00 and above**
### Geofence 4.0.0
What's New:
* AGP Version update from **8.0.2** to **8.2.2**
* Requires Core version **13.00.00 and above**
### HMS Pushkit 5.0.0
What's New:
* AGP Version update from **8.0.2** to **8.2.2**
* Requires Core version **13.00.00 and above**
### InApps 8.0.0
What's New:
* AGP Version update from **8.0.2** to **8.2.2**
* New Test InApp Experience support
* Requires Core version **13.00.00 and above**
Fixes: App crashes while removing Nudges when the Activity is **null**.
PushAmpPlus is no longer supported due to MI Push Service Shutdown.
***
## 07th February 2024
### Inbox UI 2.6.1
Fixes:
* Application getting crashed while using multiple nested fragments with backstack in ***InboxFragment.kt***.
* Memory leak fixed in ***InboxFragment.kt***.
# 2025
Source: https://moengage.com/docs/developer-guide/release-notes/android-sdk/2025-1
View the 2025 release notes and changelogs for the MoEngage Android Native SDK.
**Information**
You can now get notified whenever MoEngage releases a new version of the Android Native SDK. For more information, refer to [Subscribe to MoEngage SDK Releases](/developer-guide/release-notes/subscribe-to-moengage-sdk-releases/subscribe-to-mo-engage-sdk-releases).
Module Status Legend
■ Updated: Module version has been updated in this release.
■ Unchanged: Module remains on the previous version.
■ Deprecated: Module is deprecated and will be removed in a future release.
### Core SDK 14.04.04
Improvements:
You can now initialize the SDK by passing only the required values to *NotificationConfig*, other values can be ignored.
### InApp 9.7.0
What's New:
Introduced trigger-time segment re-evaluation to ensure In-App messages are only shown to currently eligible users.
Fixes:
Session trigger in-app not working.
## 11th December 2025
### Core SDK 14.04.03
Fixes:
WorkManager dependency downgraded from 2.11.0 to 2.10.5 due to the Kotlin version mismatch compilation error.
### InApp 9.6.1
Fixes:
WorkManager dependency downgraded from 2.11.0 to 2.10.0 due to the Kotlin version mismatch compilation error.
### Push Amp 6.2.2
Fixes:
WorkManager dependency downgraded from 2.11.0 to 2.10.0 due to the Kotlin version mismatch compilation error.
### Realtime Trigger 4.2.2
Fixes:
WorkManager dependency downgraded from 2.11.0 to 2.10.0 due to the Kotlin version mismatch compilation error.
## 10th December 2025
### Core SDK 14.03.04
New Feature:
Adding an option to configure the Project ID to support multiple projects in a given workspace.
### Cards Core 3.1.3
Improvements:
Support for Multi-User Identifiers.
### Cards UI 3.1.3
Improvements:
Support for Multi-User Identifiers.
### Geofence 5.0.3
Improvements:
Internal improvements.
### InApp 9.4.0
BugFixes:
Fullscreen video nudge becomes elongated after minimizing and switching the activity.
### Realtime Trigger 4.1.1
Improvements:
Internal improvements.
## 8th September 2025
### Core SDK 14.03.03
Improvements:
Internal improvements.
Fixes:
The copy coupon code pop-up was incorrectly shown on `remind later` click action.
### Cards Core 3.1.2
Fixes:
Card categories and card info are no longer returned when the SDK is disabled.
### Cards UI 3.1.2
Fixes:
The first click on the card item is not working when accessibility is enabled.
### Geofence 5.0.2
Improvements:
Internal improvements.
### InApp 9.3.0
Improvements:
* Support for campaign delivery breakdown.
* Internal Improvements.
### Push Amp 6.1.1
Improvements:
Support for campaign delivery breakdown.
## 12th August 2025
### Core SDK 14.03.02
Fixes:
Resolved a `NoSuchMethodError` exception thrown due to build incompatibility.
### PushKit 6.1.1
Fixes:
Resolved a `NoSuchMethodError` exception thrown due to build incompatibility.
### RichNotification 6.2.1
Fixes:
Resolved a `NoSuchMethodError` exception thrown due to build incompatibility.
## 4th August 2025
### Core SDK 14.03.01
Improvements:
Internal Improvements.
### InApp 9.2.1
Fixes:
* Corrected an issue with test InApp events synchronization.
* The InApp `onClick()` callback is now correctly sent on the Main Thread for HTML InApps.
### Cards Core 3.1.1
Fixes:
Cards are no longer returned to the user when the SDK is disabled.
### Cards UI 3.1.1
Fixes:
Cards are no longer returned to the user when the SDK is disabled.
## 15th July 2025
### Core SDK 14.03.00
What's New:
Added support for configuring the MoEngage SDK initialisation using the XML value resource.
### InApp 9.2.0
What's New:
Added support for configuring the MoEngage SDK initialisation using the XML value resource.
### Pushkit 6.1.0
What's New:
Added support for configuring the MoEngage SDK initialisation using the XML value resource.
### Realtime Trigger 4.1.0
What's New:
Added support for configuring the MoEngage SDK initialisation using the XML value resource.
### PushAmp 6.1.0
What's New:
Added support for configuring the MoEngage SDK initialisation using the XML value resource.
### RichNotification 6.2.0
What's New:
Added support for configuring the MoEngage SDK initialisation using the XML value resource.
## 27th June 2025
### Core SDK 14.02.01
Improvements:
Internal improvements.
### InApp 9.1.1
Improvements:
Internal improvements for compatibility with **Core version 14.02.01**.
Fixes:
Crash due to ConcurrentModificationException in InAppCache.
### Cards Core 3.1.0
What's New:
Support for Accessibility in Cards.
Improvements:
Internal improvements for compatibility with **Core version 14.02.01**.
### Cards UI 3.1.0
What's New:
Support for Accessibility in Cards.
Improvements:
Internal improvements for compatibility with **Core version 14.02.01**.
### Geofence 5.0.1
Improvements:
Internal improvements for compatibility with **Core version 14.02.01**.
### Push Amp 6.0.1
Improvements:
Internal improvements for compatibility with **Core version 14.02.01**.
### Realtime Trigger 4.0.1
Improvements:
Internal improvements for compatibility with **Core version 14.02.01**.
## 16th June 2025
### Core SDK 14.02.00
What's New:
APIs to track Personalize shown and click events, refer [here](https://moengage.github.io/android-api-reference/campaigns-core/com.moengage.campaigns.personalize/-mo-e-personalize-helper/index.html) for more details.
## 5th June 2025
### Core SDK 14.01.00
What's New:
Support for Accessibility in Push and InApps.
### InApp 9.1.0
What's New:
Support for Accessibility in In-app Campaigns.
### Inbox Core 4.1.0
What's New:
Support for Accessibility in Push Inbox.
Fixes:
Crash when the basic notification is clicked from the Push Inbox.
### Inbox UI 4.1.0
What's New:
Support for Accessibility in Push Inbox.
Fixes:
Crash when the basic notification is clicked from the Push Inbox.
### Rich Notification 6.1.0
What's New:
Support for Accessibility in Push Campaigns.
## 26th May 2025
### Core SDK 14.00.00
Breaking Changes:
Removed deprecated Classes and APIs.
What's New:
* Min supported SDK version updated to 23.
* Compile SDK version updated to 35.
* Support for grouping multiple Push Notifications.
* New trigger conditions for displaying the InApps.
* Support for GIFs in Push Notification.
Fixes:
Cancelling the Scheduled Job with Job Scheduler to avoid crashes in some OEMs.
### Cards Core 3.0.0
What's New:
* Min supported SDK version updated to 23.
* Compile SDK version updated to 35.
## 11th March 2025
### Core SDK 13.06.00
What's New:
* Added support for Multi User Identities.
* Support for Heads-up notification using Direct Posting Mechanism.
* AGP version updated to **8.7.3**.
Deprecated APIs:
| Then | Now |
| :------------------------------- | :-------------------------------- |
| MoEAnalyticsHelper.setUniqueId() | MoEAnalyticsHelper.identifyUser() |
| MoEAnalyticsHelper.setAlias() | MoEAnalyticsHelper.identifyUser() |
Fixes:
* ISO 8601 string before 1970 discarded due to negative epoch value.
* Crash due to ConcurrentModification in some places.
## 22nd January 2025
### InApp 8.7.1
Fixes:
* GIF image pixelation issue.
* **Has not** condition handling for event-triggered InApps.
# 2026
Source: https://moengage.com/docs/developer-guide/release-notes/android-sdk/2026-1
View the 2026 release notes and changelogs for the MoEngage Android Native SDK.
**Information**
You can now get notified whenever MoEngage releases a new version of the Android Native SDK. For more information, refer to [Subscribe to MoEngage SDK Releases](/developer-guide/release-notes/subscribe-to-moengage-sdk-releases/subscribe-to-mo-engage-sdk-releases).
Module Status Legend
■ Updated: Module version has been updated in this release.
■ Unchanged: Module remains on the previous version.
■ Deprecated: Module is deprecated and will be removed in a future release.
## Core SDK 14.8.00
Fixes
* Resolved an issue with self-handled push notifications where the same campaign was delivered twice (once via FCM and once via Push-Amp).
Improvements
* Android Gradle Plugin Version updated from **8.7.3** to **8.13.2**.
## InApp 10.1.0
What's New
* Added support for **Edge-to-Edge** display.
Fixes
* Internal bugfixes for Orientation-related rendering.
Improvements
* Android Gradle Plugin Version updated from **8.7.3** to **8.13.2**.
## Push Amp 6.4.0
Improvements
* Android Gradle Plugin Version updated from **8.7.3** to **8.13.2**.
## Realtime Trigger 4.4.0
Improvements
* Android Gradle Plugin Version updated from **8.7.3** to **8.13.2**.
## Cards Core 3.4.0
Fixes
* Internal fixes.
Improvements
* Android Gradle Plugin Version updated from **8.7.3** to **8.13.2**.
## Cards UI 3.4.0
Improvements
* Android Gradle Plugin Version updated from **8.7.3** to **8.13.2**.
## Geofence 5.3.0
Improvements
* Android Gradle Plugin Version updated from **8.7.3** to **8.13.2**.
## Rich Notification 6.5.0
Improvements
* Android Gradle Plugin Version updated from **8.7.3** to **8.13.2**.
## Inbox 4.4.0
Improvements
* Android Gradle Plugin Version updated from **8.7.3** to **8.13.2**.
## Pushkit 6.4.0
Improvements
* Android Gradle Plugin Version updated from **8.7.3** to **8.13.2**.
## Inbox UI 4.40
Improvements
* Android Gradle Plugin Version updated from **8.7.3** to **8.13.2**.
## Security 4.3.0
Improvements
* Android Gradle Plugin Version updated from **8.7.3** to **8.13.2**.
## Encrypted Storage 3.3.0
Improvements
* Android Gradle Plugin Version updated from **8.7.3** to **8.13.2**.
# 11th March 2026
## Core SDK 14.07.00
Fixes
* Fixed an issue where a blank notification was shown on certain OEMs upon clicking the last notification within a notification group.
## InApp 9.10.0
What's New
* **Callback-based APIs**: Introduced new public APIs to fetch self-handled In-Apps. These APIs provide a `FailureCallback` instead of returning `null`, ensuring better error handling.
Deprecations
* **Listener-based APIs**: All listener-based APIs for self-handled In-Apps are now deprecated and will be removed in version **11.0.0**. We recommend migrating to the new Success/Failure callback-based APIs.
| Deprecated APIs | Replacement APIs |
| :--------------------------------------------------------------------- | :------------------------------------------------------------------------------------------- |
| `getSelfHandledInApp(context, SelfHandledAvailableListener)` | `getSelfHandledInApp(context, SuccessCallback, FailureCallback)` |
| `getSelfHandledInApps(context, SelfHandledCampaignsAvailableListener)` | `getSelfHandledInApps(context, SuccessCallback, FailureCallback)` |
For more information, refer to the [Self-Handled InApps](/developer-guide/android-sdk/in-app-messages/in-app-nativ).
# 4th February 2026
## Core MoE SDK 14.06.00
What's New
* **Self-Handled Background Push**: Added support for the Self-Handled Background Push template. Refer to the [doc](/developer-guide/android-sdk/Push/Advanced/Push-Display-Handled-by-Application#h_manual_handling) for more information.
## InApp 9.9.0
Improvements
* Internal improvements.
## RichNotification 6.4.1
Fixes
* Sticky notification with notification id not removed on dismiss click.
# 20th January 2026
## Core SDK 14.05.01
Fixes
Fixed an issue where some constants were causing unresolved errors in specific build configurations.
## InApp 9.8.1
Fixes
Fixed an issue where some constants were causing unresolved errors in specific build configurations.
# 19th January 2026
## All Modules
Improvements
MoEngage has optimized memory usage on app launch.
## Core SDK 14.05.00
What's New
* **Custom Proxy Domain**: Introduced support for Custom Proxy Domains to route SDK traffic through a customer-owned subdomain for bypassing ad blockers and private DNS services. For more information, refer [here](/hc/en-us/articles/45199747520148).
## InApp 9.8.0
What's New
* **Frequency Capping:** Introduced frequency capping to limit the number of campaigns displayed to users.
## richNotification 6.4.0
What's New
Updates to support Custom Proxy Domain.
## cards-ui 3.3.0
What's New
Updates to support Custom Proxy Domain.
## pushkit 6.3.0
What's New
Updates to support Custom Proxy Domain.
# Changelog
Source: https://moengage.com/docs/developer-guide/release-notes/capacitor-sdk/changelog-2
View the changelog and release notes for the MoEngage Capacitor SDK plugins.
For privacy manifest support on iOS, please make sure that you are on Capacitor SDK Version 3.3.0 or above and iOS SDK Version 9.16.2 or above. Want to know more about privacy manifest ? Refer this [link](https://help.moengage.com/hc/en-us/articles/23893067070996-Apple-Privacy-Manifest-Update)
# 27-03-2025
## Core 6.0.0
* Bug Fix
* Incorrect keys being passed on **MoEInAppNavigationData**, **MoEInAppSelfHandledCampaignData**, **MoEPushCampaign**, **MoEInAppLifecycleData**, and **MoEInAppCustomActionData** JSON Payload to Hybrid listener
* Android
* Add support for Nudges
* ***moe-android-sdk*** version was updated to ***13.05.00***
* ***inapp*** version updated to ***8.6.0***
* iOS
* MoEngage-iOS-SDK dependency updated to ****9.18.1****
| New API |
| :----------------------------------------------------------------------------------------- |
| showNudge(options: \{ position: MoENudgePosition; appId: string; }): Promise; |
## Geofence 5.1.0
* Internal Improvements
# 07-08-2024
## Core 5.0.0
* Removed peer dependency from ***package.json***
* Added support for AGP ***8.4.0*** and above
* Kotlin version updated to ***1.9.23***
* Compile SDK version updated to ***34***
* iOS
* Added support for tracking custom boolean attributes in two formats: ***0/1*** and ***TRUE/FALSE*** Refer to the [documentation](/developer-guide/react-native-sdk/data-tracking/Tracking-User-Attributes#Custom-Boolean-User-Attribute) for more information.
**Custom Boolean Attribute Tracking in iOS.**
Updating to this version of the SDK will cause MoEngage to start tracking custom user attributes in Boolean syntax as TRUE/FALSE instead of the current 1/0 for iOS devices. This may affect your segmentation and trigger conditions.
In this version, you now have the flexibility to choose how to track custom user attributes with boolean data types. By default, iOS will align with the Android tracking method using TRUE/FALSE. However, you still have the option to continue using the existing 1/0 tracking method if it better suits your campaign requirements.
We recommend migrating to the new TRUE/FALSE method for consistency across platforms. However, we understand that you may have specific use cases where the 1/0 tracking method is preferred. To set your preference, please refer to the [custom attribute tracking section](/developer-guide/react-native-sdk/data-tracking/Tracking-User-Attributes#Custom-Boolean-User-Attribute) in our developer documentation.
* MoEngage-iOS-SDK dependency updated to ***9.18.1***
## Geofence 5.0.0
* Removed peer dependency from ***package.json***
* Android
* Removed version catalog dependency
* ***`geofence`***version updated to***`4.2.0`***
* Added support for AGP\*\*\*`8.4.0`\*\*\*and above
* Kotlin version updated to\*\*\*`1.9.23`\*\*\*
* Compile SDK version updated to ***`34`***
* iOS
* MoEngageGeofence SDK version updated to ***5.17.1***
# 03-07-2024
## Core 4.1.0
Updating to this version of the SDK will cause MoEngage to start tracking custom user attributes in Boolean syntax as TRUE/FALSE instead of the current 1/0 for iOS devices. This may have an effect to your segmentation and trigger conditions. If you wish to continue with the current 1/0 system, we recommend to skip upgrading this version, this will be configurable from 5.0.0 onwards.
* Support for forcing SDK to a specific MoEngage Environment
* Android
* ***moe-android-sdk*** version updated to ***13.02.00***
* ***inapp***version updated to ***8.3.1***
## Geofence 4.1.0
* Android
* ***geofence*** version updated to ***4.0.2***
* iOS
* MoEngageGeofence SDK version updated to ***\~>5.16.0***
# 03-05-2024
## Core 4.0.0
Updating to this version of the SDK will cause MoEngage to start tracking custom user attributes in Boolean syntax as TRUE/FALSE instead of the current 1/0 for iOS devices. This may have an effect to your segmentation and trigger conditions. If you wish to continue with the current 1/0 system, we recommend to skip upgrading this version, this will be configurable from 5.0.0 onwards.
* Capacitor 6 support
* Send SelfHandled InApp Callback when data is null
* Android
* Support for catalog version [4.1.4](https://github.com/moengage/android-dependency-catalog/releases/tag/v4.1.4). Refer to [release notes](/developer-guide/release-notes/android-sdk/2024#29th-April-2024).
* Removed Support for **PushAmpPlus**due to MI Push service shutdown.
* iOS
* Support for iOS SDK version ***9.17.0*** and above. Refer to [release notes](/developer-guide/release-notes/ios-sdk/2024#8th-April-2024) for more details.
## Geofence 3.3.0
* Capacitor 6 support
* Android
* Support for catalog version [4.1.4](https://github.com/moengage/android-dependency-catalog/releases/tag/v4.1.4). Refer to [release notes](/developer-guide/release-notes/android-sdk/2024#29th-April-2024).
* iOS
* MoEngageGeofence SDK dependency updated to ***5.16.0*** and above. Refer to [release notes](/developer-guide/release-notes/ios-sdk/2024#geofence-v5-6-0-0-3) for more details
# 08-04-2024
## Core 3.3.0
* iOS
* Support for iOS SDK version ***9.16.1*** and above. Refer to [release notes](/developer-guide/release-notes/ios-sdk/2024#18th-March-2024) for more details.
## Geofence 3.3.0
* iOS
* MoEngageGeofence SDK dependency updated to ***5.15.0*** and above.Refer to [release notes](/developer-guide/release-notes/ios-sdk/2024##18th-March-2024) for more details
# 30-01-2024
# Core 3.2.0
* iOS
* Updated the dependency to MoEngage-iOS-SDK ***9.15.0***
# Geofence 3.2.0
* iOS
* MoEngageGeofence SDK version updated to ***5.14.0***.
# 29-11-2023
# Core 3.1.0
* Android
* Support for android-dependency-catalog version ***3.2.1***, refer to the [release notes](/developer-guide/release-notes/android-sdk/2023-and-older#15-11-2023) for more details.
* Google Policy - API to delete User details.
* Android 14 policy updates.
* iOS
* Updated the dependency to MoEngage-iOS-SDK ***9.13.0***
# Geofence 3.1.0
* Android
* Support for android-dependency-catalog version ***3.2.1***, refer to the [release notes](/developer-guide/release-notes/android-sdk/2023-and-older#15-11-2023) for more details.
* iOS
* MoEngageGeofence SDK version updated to ***5.12.0***.
# 11-09-2023
## Core 3.0.0
* Migrated from Capacitor 4 to Capacitor 5
* Android
* Updated Target SDK version & Compile SDK version to 33
* iOS
* MoEngageGeofence dependency updated to **9.11.0.**
## Geofence 3.0.0
* Migrated from Capacitor 4 to Capacitor 5
* Android
* Updated Target SDK version & Compile SDK version to 33
* iOS
* MoEngageGeofence dependency updated to **5.11.0**.
# 16-05-2023
## Core 2.2.1
* Android
* Bugfix
* Self-handled callback not working for test InApp and event-triggered InApp.
# Core v2.2.0 (28-02-2023)
* Android
* Support for Android 13 push notification Opt-in with rationale via In-Apps.
* Device Id enable/disable support
# Geofence v2.2.0 (28-02-2023)
* Android
* **configureGeofence()** is deprecated.Use **startGeofenceMonitoring()** **stopGeofenceMonitoring()** in the Geofence module.
* iOS
* Support for ***stopGeofenceMonitoring()*** API.
# Core v2.1.0 (15-02-2023)
* iOS
* MoEngage-iOS-SDK dependency updated to **9.4.0**
# Geofence v2.1.0 (15-02-2023)
* iOS
* MoEngageGeofence dependency updated to **5.4.0**
# Core v2.0.0 (09-01-2023)
* Support for Android SDK version **12.5.04** and above.
* Support for iOS SDK version **9.2.0** and above.
* Breaking Changes
* All exposed API will have **appId** as an additional trailing parameter.
* Following are the renamed API
| Then | Now |
| :-------------------------------------------- | :---------------------------------------------------------------------------- |
| `optOutDataTracking({ shouldOptOut: true })` | enableDataTracking(options: \{ appId: string }): Promise\; |
| `optOutDataTracking({ shouldOptOut: false })` | disableDataTracking(options: \{ appId: string }): Promise; |
* The push token Model is renamed from **MoEPushToken** to **MoEPushTokenData**
* Removed APIs
| Removed APIs |
| :----------------------------------------------------------------------------------------------------- |
| selfHandledPrimaryClicked(campaignData: MoEInAppSelfHandledCampaignData): Promise\; |
| enableSDKLogs(): Promise\; |
| optOutInAppNotification(options: \{ shouldOptOut: boolean }): Promise\; |
| optOutPushNotification(options: \{ shouldOptOut: boolean }): Promise\; |
* Android
* Support for Android 13 notification permission
* Support for Android Gradle Plugin version 7.3.1
* Build Configuration Updates
* Target SDK version - 31
* Compile SDK Version - 31
* Removed and replaced APIs
| Then | Now |
| --------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| MoEInitializer.initialize(context: Context, builder: MoEngage.Builder) | MoEInitializer.initialiseDefaultInstance(context: Context, builder: MoEngage.Builder) |
| MoEInitializer.initialize(context: Context, builder: MoEngage.Builder, isSdkEnabled: Boolean) | MoEInitializer.initialiseDefaultInstance(context: Context, builder: MoEngage.Builder, sdkState: SdkState) |
* iOS
* Removed and replaced APIs
| Then | Now |
| ------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| initializeWithSDKConfig(\_ config: MOSDKConfig, andLaunchOptions launchOptions: \[UIApplication.LaunchOptionsKey: Any]?) | initializeDefaultInstance(\_ config: MoEngageSDKConfig, andLaunchOptions launchOptions: \[UIApplication.LaunchOptionsKey: Any]?) |
| initializeWithSDKConfig(\_ config: MOSDKConfig, withSDKState state:Bool, andLaunchOptions launchOptions: \[UIApplication.LaunchOptionsKey: Any]?) | initializeDefaultInstance(\_ config: MoEngageSDKConfig, withSDKState state:MoEngageSDKState, andLaunchOptions launchOptions: \[UIApplication.LaunchOptionsKey: Any]?) |
# Geofence v2.0.0 (09-01-2023)
* Updated the dependency to MoEngageGeofence **5.2.0** and above
* All exposed API will have **appId** as an additional trailing parameter
# Core v1.1.1 (23-12-2022)
* Bugfix
* Peer dependency resolution error fix.
# Geofence v1.1.1 (23-12-2022)
* Bugfix
* Peer dependency resolution error fix.
# Core v1.1.0 (20-12-2022)
* Migrated to Capacitor 4.
# Geofence v1.1.0 (20-12-2022)
* Migrated to Capacitor 4.
# Core v1.0.3 (27-09-2022)
* iOS
* BugFix: Registered `logoutUser` method to make it available for Javascript.
# Core v1.0.2 (25-07-2022)
* Android
* Device identifier tracking update as per Google's User Data policy. Advertising Id is only tracked after user consent. Along with the plugin update the Native Android dependency to `11.6.02`.
* iOS
* Native dependencies updated to support `MoEngage-iOS-SDK` version `7.2.0`.
# Core v1.0.1 (09-02-2022)
* Bugfix
* Android Push click callback is not working when a notification is clicked in the app's killed state.
# Core v1.0.0 (01-02-2022)
* Initial Release
# Geofence v1.0.0 (01-02-2022)
* Initial Release
# Changelog
Source: https://moengage.com/docs/developer-guide/release-notes/cordova-sdk/changelog-4
View the changelog and release notes for the MoEngage Cordova SDK plugins.
For privacy manifest support on iOS, please make sure that you are on Cordova SDK Version 8.6.0 or above and iOS SDK Version 9.16.2 or above. Want to know more about privacy manifest ? Refer this [link](https://help.moengage.com/hc/en-us/articles/23893067070996-Apple-Privacy-Manifest-Update)
# 24-03-2026
## Core 10.1.0
* Added support for fetching multiple self-handled In-App messages simultaneously using the `getSelfHandledInApps()` method.
* Added support for a logout complete callback to notify the application once the user session has been successfully cleared.
* Added support for `SDK file based initialization.`
* iOS
* Added support for the provisional Push API via the `registerForProvisionalPush()` method.
* Updated the MoEngage-iOS-SDK dependency version to 10.10.1.
* Android
* Added support for Self-Handled push notification clicks in the foreground state.
* Updated the native Android SDK BOM version to [1.5.1](https://github.com/moengage/android-dependency-catalog/tree/bom-v1.5.1).
## Geofence 3.1.1
* Android
* Updated the native Android SDK BOM version to [1.5.1](https://github.com/moengage/android-dependency-catalog/tree/bom-v1.5.1).
* iOS
* Updated the MoEngageGeofence dependency version to 6.00.6.
# 03-02-2026
## Core 10.0.1
* Bugfix
* `identifyUser` API accepting null and non-primitive data types
## 22-09-2025
## Core 10.0.0
* Adding support for identifying a user based on multiple identities
* Added support for session-triggered InApps and support multiple screen names in ***DisplayRules***.
| Then | Now |
| -------------------------- | --------------------------------- |
| MoECordova#setUniqueId(id) | MoECordova#identifyUser(identity) |
| MoECordova#setAlias(alias) | MoECordova#identifyUser(identity) |
* Android
* moe-android-sdk updated to ***14.03.03***
* Geofence version updated to ***5.0.2***
* iOS
* Updated the dependency to MoEngage-iOS-SDK ***10.06.0***
## Geofence 3.0.0
* Android
* moe-android-sdk updated to ***14.03.03***
* InApp version updated to ***8.6.0***
* iOS
* Updated the MoEngageGeofence dependency version to ***6.00.2***
# 14-04-2025
## Core 9.1.0
* Added Nudges support.
* Android
* MoEAndroidSDK version updated to `13.05.00`
* InApp version updated to `8.6.0`
* iOS
* SDK version is `9.18.1`
* Fixed data race issue.
## Geofence 2.0.1
* * Android
* moe-android-sdk version updated to 13.05.00
# 07-08-2024
## Core 9.0.0
* Android
* Bundling Native SDK versions
* ***moe-android-sdk*** version updated to ***13.04.00***
* ***inapp*** version updated to ***8.5.0***
* Added support for AGP ***8.4.0*** and above
* Kotlin version updated to ***1.9.23***
* Compile SDK version updated to ***34***
* iOS
* Added support for tracking custom boolean attributes in two formats: ***0/1*** and ***TRUE/FALSE*** Refer to the [documentation](/developer-guide/react-native-sdk/data-tracking/Tracking-User-Attributes#Custom-Boolean-User-Attribute) for more information.
**Custom Boolean Attribute Tracking in iOS.**
Updating to this version of the SDK will cause MoEngage to start tracking custom user attributes in Boolean syntax as TRUE/FALSE instead of the current 1/0 for iOS devices. This may affect your segmentation and trigger conditions.
In this version, you now have the flexibility to choose how to track custom user attributes with boolean data types. By default, iOS will align with the Android tracking method using TRUE/FALSE. However, you still have the option to continue using the existing 1/0 tracking method if it better suits your campaign requirements.
We recommend migrating to the new TRUE/FALSE method for consistency across platforms. However, we understand that you may have specific use cases where the 1/0 tracking method is preferred. To set your preference, please refer to the [custom attribute tracking section](/developer-guide/react-native-sdk/data-tracking/Tracking-User-Attributes#Custom-Boolean-User-Attribute) in our developer documentation.
* Support for ***MoEngage-iOS-SDK*** version ***9.18.1.***
## Geofence 2.0.0
* Android
* Bundling Native Geofence SDK version
* ***geofence*** version updated to ***4.2.0***
* iOS
* ***MoEngageGeofence*** SDK version updated to ***5.17.1***
# 03-07-2024
## 8.7.0 compatible packages
com.moengage:moe-android-sdk:13.02.00
com.moengage:cards-core:2.0.2 //self handled cards
com.moengage:inapp:8.3.1
com.moengage:rich-notification:5.0.1
com.moengage:geofence:4.0.2
androidx.lifecycle:lifecycle-process:2.7.0
## Core 8.7.0
Updating to this version of the SDK will cause MoEngage to start tracking custom user attributes in Boolean syntax as TRUE/FALSE instead of the current 1/0 for iOS devices. This may have an effect to your segmentation and trigger conditions. If you wish to continue with the current 1/0 system, we recommend to skip upgrading this version, this will be configurable from 9.0.0 onwards.
* Support for forcing SDK to a specific MoEngage Environment
* Android
* ***moe-android-sdk*** version updated to ***13.02.00***
* iOS
* Support for iOS SDK version ***9.17.1*** and above.
## Geofence 1.7.0
* Android
* ***geofence*** version updated to ***4.0.2***
* iOS
* MoEngageGeofence SDK version updated to ***\~>5.16.0***
# 08-04-2024
## Core 8.6.0
* iOS
* Support for iOS SDK version ***9.16.1*** and above. Refer to [release notes](/developer-guide/release-notes/ios-sdk/2024#8th-April-2024) for more details.
## Geofence 1.6.0
* iOS
* MoEngageGeofence SDK dependency updated to ***5.15.0*** and above.Refer to [release notes](/developer-guide/release-notes/ios-sdk/2024#8th-April-2024) for more details
# 30-01-2024
## Core 8.5.0
* iOS
* Support for iOS SDK version ***9.15.0*** and above.
## Geofence 1.5.0
* iOS
* MoEngageGeofence SDK dependency updated to ***5.14.0*** and above.
# 29-11-2023
## Core 8.4.0
* iOS
* Support for iOS SDK version `9.8.0` and above.
* Android
* Support for Android version `12.10.01` and above, refer to the [release notes](/developer-guide/release-notes/android-sdk/2023-and-older#29-11-2023) for more details.
* Google Policy - API to Delete User details
* BugFix
* Self Handled InApp delivery controls not working
## Geofence 1.4.0
* iOS
* MoEngageGeofence SDK dependency updated to `5.8.0` and above.
* Android
* MoEngageGeofence SDK dependency updated to `3.4.0` and above.
16-05-2023
## Core 8.3.1
* Android
* Bugfix
* Self-handled callback not working for test InApp and event-triggered InApp.
# 28-02-2023
## Core 8.3.0
* Android
* Support for Android 13 push notification Opt-in with rationale via In-Apps.
* Device Id enable/disable support
# 28-02-2023
## Geofence 1.3.0
* Android
* **configureGeofence()** is deprecated.Use **startGeofenceMonitoring()** **stopGeofenceMonitoring()** in the Geofence module.
* iOS
* Support for ***stopGeofenceMonitoring()*** API.
# 16-02-2023
## Core 8.2.0
* iOS
* MoEngage-iOS-SDK dependency updated to **9.4.0**
* Following are the deprecated API
| Then | Now |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| - (void)initializeDefaultSDKConfig:(MOSDKConfig\**)sdkConfig andLaunchOptions:(NSDictionary*\*)launchOptions; | -(void)initializeDefaultSDKConfig:(MoEngageSDKConfig\**)sdkConfig andLaunchOptions:(NSDictionary*\*)launchOptions; |
| - (void)initializeDefaultSDKConfigWithState:(MOSDKConfig\**)sdkConfig withSDKState:(MoEngageSDKState)sdkState andLaunchOptions:(NSDictionary*\*)launchOptions; | - (void)initializeDefaultSDKConfigWithState:(MoEngageSDKConfig\**)sdkConfig withSDKState:(MoEngageSDKState)sdkState andLaunchOptions:(NSDictionary*\*)launchOptions; |
## Geofence 1.2.0
* MoEngageGeofence SDK dependency updated to **5.4.0**
# 31-10-2022
## Core 8.1.0
* Android
* Support for Android 13 notification permission
* Support for Android Gradle Plugin version **7.3.1**
* Build Configuration Update
* Compile SDK version - 31
* Target SDK version - 31
* Support for Android SDK version **12.4.00** and above
* iOS
* Initialization APIs are updated to initialize SDK with the state.
| Then | Now |
| ---------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| (void)initializeDefaultSDKConfig:(MOSDKConfig\*)sdkConfig withSDKState:(BOOL)isSdkEnabled andLaunchOptions:(NSDictionary\*)launchOptions | (void)initializeDefaultSDKConfig:(MOSDKConfig\*)sdkConfig withMoEngageSDKState:(MoEngageSDKState)sdkState andLaunchOptions:(NSDictionary\*)launchOptions |
## Geofence 1.1.0
* MoEngagePluginGeofence dependency version updated to **1.1.0**.
# 06-10-2022
## Core 8.0.0
* Support for Android SDK version **12.2.05** and above.
* Support for iOS SDK version **8.3.1** and above.
* Breaking changes
| Then | Now |
| ----------------- | ------------------------------ |
| MoECordova.init() | MoECordova.init(YOUR\_APP\_ID) |
* Removed APIs
| Removed APIs |
| --------------------------- |
| selfHandledPrimaryClicked() |
| enableSDKLogs() |
| optOutInAppNotification() |
| optOutPushNotification() |
| startGeofenceMonitoring() |
* Android
* Build Configuration Updates
* Minimum SDK version - 21
* Target SDK version - 30
* Compile SDK Version - 30
* Mi SDK update to Version 5.x.x, refer to the [Configuring Xiaomi Push](https://developers.moengage.com/hc/en-us/articles/4403466194708) and update the integration.
* Removed and replaced APIs
| Then | Now |
| ------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| MoEInitializer.initialize(Context, MoEngage.Builder) | MoEInitializer.initialiseDefaultInstance(Context, MoEngage.Builder) |
| MoEInitializer.initialize(Context, MoEngage.Builder, Boolean) | MoEInitializer.initialiseDefaultInstance(Context, MoEngage.Builder, SdkState) |
* iOS
| Then | Now |
| ----------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| - (void)initializeMoEngageSDKWithConfig:(MOSDKConfig\*)sdkConfig andLaunchOptions:(NSDictionary\*)launchOptions; | - (void)initializeDefaultSDKConfig:(MOSDKConfig\*)sdkConfig andLaunchOptions:(NSDictionary\*)launchOptions; |
| - (void)initializeMoEngageSDKWithConfig:(MOSDKConfig\*)sdkConfig withSDKState:(BOOL)isSdkEnabled andLaunchOptions:(NSDictionary\*)launchOptions | - (void)initializeDefaultSDKConfig:(MOSDKConfig\*)sdkConfig withSDKState:(BOOL)isSdkEnabled andLaunchOptions:(NSDictionary\*)launchOptions; |
## Geofence 1.0.0
* Added a new plugin to support the region monitoring.
# 7.3.3
**Release Date:** 25th July 2022
* Device identifier tracking update as per Google's User Data policy. Advertising Id is only tracked after user consent. Along with the plugin update the Native Android dependency to **11.6.02**.
# 7.3.1
**Release Date:** 29th April 2022
* Bugfix
* Fixed the appearance of a thin grey line above the label in the InApp when displayed on larger screen devices.
# 7.3.0
Release Date: 16th September 2021
* HTML InApp Support Added.
* iOS
* Native SDK version updated to `~>7.1.0`.
* Base plugin version dependency updated to `~>2.1.0`
* Android
* Native SDK updated to support version `11.4.00` and above.
# 7.2.0
Release Date: 11th May 2021
* Android SDK updated to support `11.2.00` and above.
# 7.1.0
**Release Date:** 31st March 2021
* On iOS added support to explicitly initialize the plugin instead of the default Info.plist initialization.
# 7.0.0
**Release Date:** 26th February 2021
* Support added for Native iOS SDK version `7.0` and above.
* Android Native SDK updated to support version `11.0.04` and above. Refer to the [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#11-0-04-24-02-2021) for behavior changes.
* Added APIs to enable/disable SDK.
* Added push token generated callback listener.
# 6.1.3
**Release Date:** 18th January 2021
* Updated iOS MoEPluginBase dependency to support version 1.2 and above.
# 6.1.2
**Release Date:** 7th December 2020
* Support for extending Native Android Callbacks if required.
* Native Android SDK version required is `10.5.00` or above
# 6.1.1
**Release Date:** 23rd October 2020
* Bugfix
* Events not being marked as non-interactive on Android
* On iOS payload sent in callback was incorrect, it was sent inside another "payload" key earlier
# 6.1.0
**Release Date**: 21st September 2020
* Migration to `androidx` namespace.
# 6.0.0
**Release Date**: 19th September 2020
* Support for Self-Handled In-App
* Support for In-App V3
* Android Native SDK dependency changed to support versions greater than `10.3.02` and above.
* iOS Native SDK dependency changed to support versions greater than `6.0.0`.
| Then | Now |
| ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| MoECordova#passToken(token) | MoECardova#passFcmToken(token) |
| MoECordova#pushPayload(pushPayload) | MoECordova#passFcmPayload(pushPayload) |
| MoECordova#setExistingUser(isExisting) | MoECordova#setAppStatus(status) |
| MoECordova#trackEvent (eventName, eventAttributes) | MoECordova#trackEvent(eventName, generalAttributes, locationAttributes, dataTimeAttributes , isNonInteractive) |
| MoECordova#setLogLevelForAndroid (loglevel)/setLogLevelForiOS(loglevel) | MoECordova#enableSDKLogs() |
| MoECordova#setUserAttributeLocation (attributeName, attributeLatValue, attributeLonValue) | MoECordova#setUserLocation(latitude, longitude) |
| MoECordova#setUserAttributeTimestamp (attributeName, epochTimeStampVal) | MoECordova#setUserAttributeISODateString (attributeName, date) |
# 5.0.1
**Release Date**: 30th August 2019\
Updated the integration to support CocoaPods for integrating the iOS SDK - [link](/developer-guide/cordova-sdk/sdk-integration/sdk-installation/ios-installation).\
Updated Android integration to support integration via gradle.\
Native Android SDK version updated to 9.6.01
# 4.2.0
**Release Date**: 30th August 2019\
Updated native iOS SDK version to 5.0.2\
Update native Android SDK version to 9.6.0
# 4.0.0
**Release Date**: 29th June 2018\
Support provided for Android Oreo.\
Support for both GCM and FCM in Android\
Push Amp is supported.\
iOS SDK is now a Dynamic Framework.\
Support for Real-time Triggers.\
Support to update Unique ID User Attribute using `setAlias()`.\
Support for Conditional navigation in In-App Rating Template.
**Migration to 4.\* :**
For migration from existing plugin to this version follow this [link](/developer-guide/cordova-sdk/migration/migrating-to-4xx)
# 3.0.0
**Release Date**: 22nd June, 2017\
Javascript callbacks for navigation actions
# 2.1.0
**Release Date**: 24th November, 2016
* iOS 10 changes for Rich Notifications added.
# 2.0.2
**Release Date**: 19th September, 2016
* iOS: Now plugin adds AppID from the plugin add command variables, no need to provide it in AppDelegate.
* iOS : Plugin is updated to handle all the lifecycle callbacks on its own, therefore no changes are required in AppDelegate.
* iOS : Notifications provided to Remote Notification registration methods and push notification receiving method.
# 2.0.0
**Release Date**: 8th August, 2016
* Support for iOS added in the plugin.
# 1.0.0
**Release Date**: 12th July, 2016
* First release of the plugin with support for Android.
# Changelog
Source: https://moengage.com/docs/developer-guide/release-notes/expo-react-native-sdk/changelog
View the changelog and release notes for the MoEngage Expo React Native SDK plugins.
You can now get notified whenever MoEngage releases a new version of the Expo React-Native SDK. For more information, refer to [Subscribe to MoEngage SDK Releases](/developer-guide/release-notes/subscribe-to-moengage-sdk-releases/subscribe-to-mo-engage-sdk-releases).
# 9th Feb 2026
| Plugins | Dependencies |
| :---------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| expo: 1.1.0 |
|
### Expo 1.0.1
### **BugFixes**
* Removed the ***postinstall*** script to avoid running the ***tsc*** command on all projects.
# 29th July 2025
| Plugins | Dependencies |
| :---------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| expo: 1.0.0 |
**Android**
AGP: 8.7.3
Kotlin: 1.9.23
Compile SDK Version: 35
Gradle Version: 8.9
**iOS**
iOS deployment target: 13
tvOS deployment target: 13
|
### Expo 1.0.0
### **What's New**
* Adding support to integrate the MoEngage [React-Native SDK](/developer-guide/react-native-sdk) with the Expo framework.
# Changelog
Source: https://moengage.com/docs/developer-guide/release-notes/flutter-sdk/changelog-6
View the changelog and release notes for the MoEngage Flutter SDK plugins.
* You can now get notified whenever MoEngage releases a new version of the Flutter SDK. For more information, refer to [Subscribe to MoEngage SDK Releases](developer-guide/release-notes/subscribe-to-moengage-sdk-releases/subscribe-to-mo-engage-sdk-releases).
* For privacy manifest support on iOS, please make sure that you are on Flutter SDK Version 7.0.0 or above and iOS SDK Version 9.16.2 or above. Want to know more about privacy manifest? Refer this [link](https://help.moengage.com/hc/en-us/articles/23893067070996-Apple-Privacy-Manifest-Update).
* Support for [Swift Package Manager](https://docs.flutter.dev/packages-and-plugins/swift-package-manager/for-app-developers) is available from version 10.3.0.
# 11th February 2026
| **Plugins** | **Android Dependencies** |
| --------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| core: 10.5.0 cards:6.3.0 inbox:9.3.0 geofence:6.3.0 | AGP: 8.7.3 Kotlin: 1.9.23 Compile SDK Version: 35 Gradle Version: 8.9 Min SDK version: 23 |
#
Core 10.5.0
### **What's New**
* Android
* Support for the MoEngage SDK BOM version [1.5.1](/developer-guide/release-notes/android-sdk/2026/4th-February-2026)
* iOS
* Added support for SDK initialization without Swift/Objective-C code.
* Updated MoEngage-iOS-SDK to ***10.10.0***
# Cards 6.3.0
* Android
* Support for the MoEngage SDK BOM version [1.5.1](/developer-guide/release-notes/android-sdk/2026/4th-February-2026)
* iOS
* Updated MoEngage-iOS-SDK to ***10.10.0***
# Geofence 6.3.0
* Android
* Support for the MoEngage SDK BOM version [1.5.1](/developer-guide/release-notes/android-sdk/2026/4th-February-2026)
* iOS
* Updated MoEngage-iOS-SDK to ***10.10.0***
# Inbox 9.3.0
* Android
* Support for the MoEngage SDK BOM version [1.5.1](/developer-guide/release-notes/android-sdk/2026/4th-February-2026)
* iOS
* Updated MoEngage-iOS-SDK to ***10.10.0***
# 3rd February 2026
| **Plugins** | **Android Dependencies** |
| --------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| core: 10.4.0 cards:6.2.0 inbox:9.2.0 geofence:6.2.0 | AGP: 8.7.3 Kotlin: 1.9.23 Compile SDK Version: 35 Gradle Version: 8.9 Min SDK version: 23 |
#
#
Core 10.4.0
### **What's New**
* Web
* Added support for `enableDataTracking()` and `disableDataTracking()` methods
* Updated web deprecated packages like **dart:js** which will enable WASM support
* Android
* Bundling `MoEFireBaseMessagingService` in MoEngage Flutter Plugin's manifest to reduce integration steps for developers using FCM Push.
# 19th November 2025
| **Plugins** | **Android Dependencies** |
| --------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| core: 10.3.0 cards:6.2.0 inbox:9.2.0 geofence:6.2.0 | AGP: 8.7.3 Kotlin: 1.9.23 Compile SDK Version: 35 Gradle Version: 8.9 Min SDK version: 23 |
#
#
Core 10.3.0
### **What's New**
* Android
* Moving the native dependencies to the bill-of-materials (BOM) for better version management.
* Initial supported MoEngage BOM version ***1.1.1***
* iOS
* Added SPM integration support
* Updated MoEngage-iOS-SDK to ***10.08.0***
Cards 6.2.0
### **What's New**
* Android
* Moving the native dependencies to the bill-of-materials (BOM) for better version management.
* Initial supported MoEngage BOM version ***1.1.1***
* iOS
* Added SPM integration support
* Updated MoEngage-iOS-SDK to ***10.08.0***
Inbox 9.2.0
### **What's New**
* Android
* Moving the native dependencies to the bill-of-materials (BOM) for better version management.
* Initial supported MoEngage BOM version ***1.1.1***
* iOS
* Added SPM integration support
* Updated MoEngage-iOS-SDK to ***10.08.0***
Geofence 6.2.0
### **What's New**
* Android
* Moving the native dependencies to the bill-of-materials (BOM) for better version management.
* Initial supported MoEngage BOM version ***1.1.1***
* iOS
* Added SPM integration support
* Updated MoEngage-iOS-SDK to ***10.08.0***
# 14th October 2025
| **Plugins** | **Android Dependencies** |
| --------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| core: 10.2.0 cards:6.1.1 inbox:9.1.1 geofence:6.1.1 | AGP: 8.7.3 Kotlin: 1.9.23 Compile SDK Version: 35 Gradle Version: 8.9 Min SDK version: 23 |
#
#
Core 10.2.0
### **What's New**
* Android
* ***moe-android-sdk*** version updated to ***14.03.05***
* ***inapp***version updated to ***9.4.0***
* iOS
* ***MoEngage-iOS-SDK***version updated to***10.07.1***
Cards 6.1.0
### **What's New**
* Android
* ***cards-core*** version updated to ***3.1.3***
* iOS
* ***MoEngageCards***version updated to ***5.01.5***
Inbox 9.1.0
### **What's New**
* iOS
* ***MoEngageInbox***version updated to ***3.01.2***
Geofence 6.1.1
### **What's New**
* Android
* ***geofence*** version updated to ***5.0.3***
# 9th September 2025
| **Plugins** | **Android Dependencies** |
| --------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| core: 10.1.0 cards:6.1.0 inbox:9.1.0 geofence:6.1.0 | AGP: 8.7.3 Kotlin: 1.9.23 Compile SDK Version: 35 Gradle Version: 8.9 Min SDK version: 23 |
#
#
Core 10.1.0
### **What's New**
* Android
* ***moe-android-sdk*** version updated to ***14.03.03***
* ***inapp***version updated to ***9.3.0***
* iOS
* ***MoEngage-iOS-SDK***version updated to***10.05.0***
Cards 6.1.0
### **What's New**
* Android
* ***cards-core*** version updated to ***3.1.2***
* iOS
* ***MoEngageCards***version updated to ***5.01.4***
Inbox 9.1.0
### **What's New**
* iOS
* ***MoEngageInbox***version updated to ***3.01.1***
Geofence 6.1.0
### **What's New**
* Android
* ***geofence*** version updated to ***5.0.2***
* iOS
* ***MoEngageGeofence***version updated to***6.00.2***
# 18th July 2025
| **Plugins** | **Android Dependencies** |
| -------------------------- | ------------------------------------------------------------------------------------------------- |
| cards:6.0.1 core: 10.0.1 | AGP: 8.7.3 Kotlin: 1.9.23 Compile SDK Version: 35 Gradle Version: 8.9 Min SDK version: 23 |
Core 10.0.1
### **Fixes**
* Export ***platforms.dart*** in the platform interface barrel file
Cards 6.0.1
### **Fixes**
* Export ***static\_image\_type.dart*** in the platform interface barrel file
# 3rd July 2025
| **Plugins** | **Android Dependencies** |
| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| cards:6.0.0 geofence:6.0.0 inbox: 9.0.0 core: 10.0.0 | AGP: 8.7.3 Kotlin: 1.9.23 Compile SDK Version: 35 Gradle Version: 8.9 Min SDK version: 23 |
## Compatible Android packages
com.moengage:cards-core:3.1.0
com.moengage:inapp:9.1.1
com.moengage:moe-android-sdk:14.02.02
com.moengage:geofence:5.0.1
com.moengage:inbox-core:4.1.0\
**Note: The above versions are already bundled as part of the respective Flutter plugins, so you do not need to include them.**
com.moengage:rich-notification:6.1.0
**Compatible MoE Android version catalog - 5.3.1**
Core 10.0.0
### **What's New**
* New trigger conditions for displaying the InApps
* Support for grouping multiple Push Notifications & notification replacement
* Support for GIFs in Push Notification
* Support for accessibility in Push and InApps
* Android
* ***moe-android-sdk*** version updated to ***14.02.02***
* ***inapp***version updated to ***9.1.1***
* \*\*\*Breaking change:\*\*\*Min SDK Version updated to 23
* Compiled SDK Version updated to 35
* iOS
* ***MoEngage-iOS-SDK***version updated to***10.02.1***
* ***MoEngageInApp***version updated to ***7.01.1***
* \*\*Breaking change:\*\*Minimum deployment target updated to 13
* Web
* Added SDK Opt-out support using ***enableSdk()*** and ***disableSdk()*** methods
Cards 6.0.0
### **What's New**
* Support for accessibility in Cards
* Android
* ***cards-core*** version updated to ***3.1.0***
* \*\*\*Breaking change:\*\*\*Min SDK Version updated to 23
* Compiled SDK Version updated to 35
* iOS
* ***MoEngageCards***version updated to ***5.01.1***
* \*\*Breaking change:\*\*Minimum deployment target updated to 13
Inbox 9.0.0
### **What's New**
* Support for accessibility in Push Inbox
* Android
* ***inbox-core*** version updated to ***4.1.0***
* \*\*\*Breaking change:\*\*\*Min SDK Version updated to 23
* Compiled SDK Version updated to 35
* iOS
* ***MoEngageInbox***version updated to ***3.01.1***
* \*\*Breaking change:\*\*Minimum deployment target updated to 13
Geofence 6.0.0
### **What's New**
* Android
* ***geofence*** version updated to ***5.0.1***
* \*\*\*Breaking change:\*\*\*Min SDK Version updated to 23
* Compiled SDK Version updated to 35
* iOS
* ***MoEngageGeofence***version updated to***6.00.1***
* \*\*Breaking change:\*\*Minimum deployment target updated to 13
# 24th April 2025
| **Plugins** | **Android Dependencies** |
| -------------------------- | --------------------------------------------------------------------------- |
| inbox: 8.2.1 core: 9.2.1 | AGP: 8.7.3 Kotlin: 1.9.23 Compile SDK Version: 34 Gradle Version: 8.9 |
## Compatible Android packages
com.moengage:cards-core:2.4.0
com.moengage:inapp:8.8.1
com.moengage:moe-android-sdk:13.06.00
com.moengage:geofence:4.3.0
com.moengage:inbox-core:3.3.0\
**Note: The above versions are already bundled as part of the respective Flutter plugins, so you do not need to include them.**
com.moengage:rich-notification:5.2.0
**Compatible MoE Android version catalog - 4.8.0**
Core 9.2.1
* Internal improvements
* Android
* ***inapp***version updated to ***8.8.1***
*
Inbox 8.2.1
* Bugfix
* ANR in `fetchAllMessages` API
# 25th March 2025
| **Plugins** | **Android Dependencies** |
| --------------------------------------------------------- | --------------------------------------------------------------------------- |
| cards:5.2.0 geofence:5.2.0 inbox: 8.2.0 core: 9.2.0 | AGP: 8.7.3 Kotlin: 1.9.23 Compile SDK Version: 34 Gradle Version: 8.9 |
## Compatible Android packages
com.moengage:cards-core:2.4.0
com.moengage:inapp:8.8.0
com.moengage:moe-android-sdk:13.06.00
com.moengage:geofence:4.3.0
com.moengage:inbox-core:3.3.0\
**Note: The above versions are already bundled as part of the respective Flutter plugins, so you do not need to include them.**
com.moengage:rich-notification:5.2.0
**Compatible MoE Android version catalog - 4.7.0**
Core 9.2.0
### **What's New**
* Added support for Multi-User Identities. Refer to the [developer docs](/developer-guide/android-sdk/data-tracking/basic/track-user-attributes#Multiple-Identifiers) on how to migrate from existing APIs to the new APIs. Refer to the [user guide](https://help.moengage.com/hc/en-us/articles/24050999467284-User-Identity-Management) to learn more about the feature.
* Android
* Added support for AGP 8.7.3 and above
* ***moe-android-sdk*** version updated to ***13.06.00***
* ***inapp***version updated to ***8.8.0***
* iOS
* ***MoEngage-iOS-SDK*** version updated to ***9.23.1***
* Fixed Inapp navigation callback not received when key value pair is missing.
Cards 5.2.0
### **What's New**
* Android
* Added support for AGP 8.7.3 and above
* ***cards-core*** version updated to ***2.4.0***
Inbox 8.2.0
### **What's New**
* Android
* Added support for AGP 8.7.3 and above
* ***inbox-core*** version updated to ***3.3.0***
Geofence 5.2.0
### **What's New**
* Android
* Added support for AGP 8.7.3 and above
* ***geofence*** version updated to ***4.3.0***
# 18th February 2025
| **Plugins** | **Android Dependencies** |
| --------------------------------------------------------- | --------------------------------------------------------------------------- |
| cards:5.1.1 geofence:5.1.1 inbox: 8.1.1 core: 9.1.1 | AGP: 8.4.0 Kotlin: 1.9.23 Compile SDK Version: 34 Gradle Version: 8.6 |
## Compatible Android packages
com.moengage:moe-android-sdk:13.05.02
com.moengage:inapp:8.7.1
com.moengage:cards-core:2.3.2
com.moengage:geofence:4.2.1
com.moengage:inbox-core:3.2.1\
**Note:** The above versions already bundled part of respective Flutter plugins, so you do not need to include them.
com.moengage:rich-notification:5.1.2\
Compatible MoE Android version catalog - 4.5.3
Cards 5.1.1
* iOS
* ***MoEngage-Cards*** version updated to ***4.19.2***.
Inbox 8.1.1
* * Internal improvements
Geofence 5.1.1
* Internal improvements
Core 9.1.1
* iOS
* ***MoEngage-iOS-SDK*** version updated to ***9.22.2***
# 29th January 2025
| **Plugins** | **Android Dependencies** |
| --------------------------------------------------------- | --------------------------------------------------------------------------- |
| cards:5.1.0 geofence:5.1.0 inbox: 8.1.0 core: 9.1.0 | AGP: 8.4.0 Kotlin: 1.9.23 Compile SDK Version: 34 Gradle Version: 8.6 |
## Compatible Android packages
com.moengage:moe-android-sdk:13.05.02
com.moengage:inapp:8.7.1
com.moengage:cards-core:2.3.2
com.moengage:geofence:4.2.1
com.moengage:inbox-core:3.2.1\
**Note:** The above versions already bundled part of respective Flutter plugins, so you do not need to include them.
com.moengage:rich-notification:5.1.2\
Compatible MoE Android version catalog - 4.5.3
Cards 5.1.0
* Android
* ***cards-core** version updated to **2.3.2.***
* iOS
* ***MoEngage-Cards*** version updated to ***4.19.1***.
Inbox 8.1.0
* Android
* ***inbox-core*** version updated to ***4.2.1***
* iOS
* Updated ***MoEngageGeofence*** to ***5.19.0***
Geofence 5.1.0
* Android
* ***geofence*** version updated to ***4.2.1***
* iOS
* Updated ***MoEngageGeofence*** to ***5.19.0***
Core 9.1.0
* Android
* ***moe-android-sdk*** version updated to ***13.05.02.***
* ***inapp** version updated to **8.7.1***
* iOS
* ***MoEngage-iOS-SDK*** version updated to ***9.22.1***
* Updated ***MoEngageInApp*** to ***6.04.0***
# 25th November 2024
| **Plugins** | **Android Dependencies** |
| --------------------------------------------------------- | --------------------------------------------------------------------------- |
| cards:5.0.2 geofence:5.0.2 inbox: 8.0.2 core: 9.0.1 | AGP: 8.4.0 Kotlin: 1.9.23 Compile SDK Version: 34 Gradle Version: 8.6 |
## Compatible Android packages
com.moengage:moe-android-sdk:13.05.00
com.moengage:inapp:8.6.0
com.moengage:cards-core:2.3.0
com.moengage:geofence:4.2.0
com.moengage:inbox-core:3.2.0\
**Note:** The above versions already bundled part of respective flutter plugins, so you no need to include them.
com.moengage:rich-notification:5.1.0\
Compatible MoE Android version catalog - 4.5.0
Cards 5.0.2
* Internal Improvements
Inbox 8.0.2
* Internal Improvements
Geofence 5.0.2
* Internal Improvements
Core 9.0.1
* Internal Improvements
# 3rd October 2024
| **Plugins** | **Android Dependencies** |
| ------------------------------------------- | --------------------------------------------------------------------------- |
| cards:5.0.1 geofence:5.0.1 inbox: 8.0.1 | AGP: 8.4.0 Kotlin: 1.9.23 Compile SDK Version: 34 Gradle Version: 8.6 |
Cards 5.0.1
### **Fixes**
* Fixed dependency incompatibility issue when upgrading to **moengage\_flutter** version **9.0.0**
Inbox 8.0.1
### **Fixes**
* Fixed dependency incompatibility issue when upgrading to **moengage\_flutter** version **9.0.0**
Geofence 5.0.1
### **Fixes**
* Fixed dependency incompatibility issue when upgrading to **moengage\_flutter** version **9.0.0**
# 30th September 2024
| **Plugins** | **Android Dependencies** |
| --------------------------------------------------------- | --------------------------------------------------------------------------- |
| core: 9.0.0 cards:5.0.0 geofence:5.0.0 inbox: 8.0.0 | AGP: 8.4.0 Kotlin: 1.9.23 Compile SDK Version: 34 Gradle Version: 8.6 |
An issue has been identified regarding compatibility between **moengage\_flutter** version **9.0.0** and the dependent packages. Please note the affected packages and their incompatible versions:
**moengage\_geofence** version **5.0.0**\
**moengage\_inbox** version **8.0.0**\
**moengage\_cards** version **5.0.0**
If you are planning to upgrade to **moengage\_flutter** version **9.0.0**, it is crucial to update the following packages to their respective versions to ensure compatibility and avoid any disruptions:
**moengage\_geofence** should be upgraded to version **5.0.1** or above\
**moengage\_inbox** should be upgraded to version **8.0.1** or above\
**moengage\_cards** should be upgraded to version **5.0.1** or above
Core 9.0.0
### **What's New**
* Support multiple self-handled InApps fetch using ***getSelfHandledInApps()**.*
* Android
* Bundling native ***moe-android-sdk*** & ***inapp*** dependencies with the plugin.
* ***moe-android-sdk*** version updated to ***13.05.00.***
* ***inapp** version updated to **8.6.0.***
* \*\*Breaking change:\*\*Developers should remove the **com.moengage:moe-android-sdk** and **com.moengage:inapp** dependencies from the ***build.gradle*** as it is now included with the plugin.
* **Note:** If using features like ***hms-pushkit***, ***rich-push***, ***push-amp,*** etc. please ensure you still need to manually add those dependencies.
* iOS
* Added support for **Provisional Push**.
* ***MoEngage-iOS-SDK*** version updated to ***9.20.0***.
Cards 5.0.0
### **What's New**
* Cards fetch on new user attribute unique ID set.
* Breaking changes in API
| Then | Now |
| --------------------------------------- | ---------------------------------------- |
| MoEngageCards.#setAppOpenSyncListener() | MoEngageCards.#setSyncCompleteListener() |
* Android
* Bundling native ***cards-core*** dependency with the plugin
* ***cards-core*** version updated to ***2.3.0***
* \*\*Breaking change:\*\*Developers should remove the ***cards-core*** dependency from the `**build.gradle**` as it is now included with the plugin.
* iOS
* ***MoEngageCards*** version updated to ***4.18.0***
Inbox 8.0.0
### **What's New**
* Android
* Bundling native ***inbox-core*** dependency with the plugin
* ***inbox-core*** version updated to ***3.2.0***
* \*\*Breaking change:\*\*Developers should remove the ***inbox-core*** dependency from the `**build.gradle**` as it is now included with the plugin.
* iOS
* ***MoEngageInbox*** version updated to ***2.18.0***
Geofence 5.0.0
### **What's New**
* Android
* Bundling native ***geofence*** dependency with the plugin
* ***geofence*** version updated to ***4.2.0***
* \*\*Breaking change:\*\*Developers should remove the ***geofence*** dependency from the `**build.gradle**` as it is now included with the plugin.
* iOS
* ***MoEngageGeofence*** version updated to ***5.18.0***
Core 8.1.0
This version might have unintentional breaking changes. We recommend not to use this version. Please upgrade to **9.0.0**and please ensure you review the documented changes and integrate these modifications as necessary.
Geofence 4.1.0
This version might have unintentional breaking changes. We recommend not to use this version. Please upgrade to **5.0.1** and please ensure you review the documented changes and integrate these modifications as necessary
Inbox 7.1.0
This version might have unintentional breaking changes. We recommend not to use this version. Please upgrade to **8.0.1** and please ensure you review the documented changes and integrate these modifications as necessary
# 07-08-2024
# Core 8.0.0
* Exact version pinning for Core Module dependencies
* iOS
* Added support for tracking custom boolean attributes in two formats: ***0/1*** and ***TRUE/FALSE*** Refer to the [documentation](/developer-guide/react-native-sdk/data-tracking/Tracking-User-Attributes#Custom-Boolean-User-Attribute) for more information.
**Custom Boolean Attribute Tracking in iOS.**
Updating to this version of the SDK will cause MoEngage to start tracking custom user attributes in Boolean syntax as TRUE/FALSE instead of the current 1/0 for iOS devices. This may affect your segmentation and trigger conditions.
In this version, you now have the flexibility to choose how to track custom user attributes with boolean data types. By default, iOS will align with the Android tracking method using TRUE/FALSE. However, you still have the option to continue using the existing 1/0 tracking method if it better suits your campaign requirements.
We recommend migrating to the new TRUE/FALSE method for consistency across platforms. However, we understand that you may have specific use cases where the 1/0 tracking method is preferred. To set your preference, please refer to the [custom attribute tracking section](/developer-guide/react-native-sdk/data-tracking/Tracking-User-Attributes#Custom-Boolean-User-Attribute) in our developer documentation.
# Cards 4.0.0
* Exact version pinning for Cards Module dependencies
* iOS
* Internal Improvements
# Geofence 4.0.0
* Exact version pinning for Geofence Module dependencies
* iOS
* Internal Improvements
# Inbox 7.0.0
* Exact version pinning for Inbox Module dependencies
* iOS
* Internal Improvements
# 31-07-2024
# Core 7.2.0
Updating to this version of the SDK will cause MoEngage to start tracking custom user attributes in Boolean syntax as TRUE/FALSE instead of the current 1/0 for iOS devices. This may have an effect to your segmentation and trigger conditions. If you wish to continue with the current 1/0 system, we recommend to skip upgrading this version, this will be configurable from 8.0.0 onwards.
* Exact version pinning for Core Module dependencies
* iOS
* Updated MoEngage-iOS-SDK to 9.18.0
* Updated MoEngageInApp to 6.01.0
# Cards 3.2.0
* Exact version pinning for Cards Module dependencies
* iOS
* Updated MoEngageCards to 4.17.0
# Geofence 3.2.0
* Exact version pinning for Geofence Module dependencies
* iOS
* Updated MoEngageGeofence to 5.17.0
# Inbox 6.2.0
* Exact version pinning for Inbox Module dependencies
* iOS
* Updated MoEngageInbox to 2.17.0
# 15-07-2024
## 7.1.1 compatible packages
com.moengage:moe-android-sdk:13.03.00
com.moengage:cards-core:2.1.0 //self handled cards
com.moengage:inbox-core:3.1.0
com.moengage:inapp:8.4.0
com.moengage:rich-notification:5.1.0
com.moengage:geofence:4.1.0
androidx.lifecycle:lifecycle-process:2.7.0
# Core 7.1.1
Updating to this version of the SDK will cause MoEngage to start tracking custom user attributes in Boolean syntax as TRUE/FALSE instead of the current 1/0 for iOS devices. This may have an effect to your segmentation and trigger conditions. If you wish to continue with the current 1/0 system, we recommend to skip upgrading this version, this will be configurable from 8.0.0 onwards.
* Android: Support for Android SDK version ***13.03.00***
# Cards 3.1.1
* Android
* Support for Android SDK version ***13.03.00***
* cards-core version updated to ***2.1.0***
# Geofence 3.1.1
* Android
* Support for Android SDK version ***13.03.00***
* geofence version updated to ***4.1.0***
# Inbox 6.1.1
* Android
* Support for Android SDK version ***13.03.00***
* inbox-core updated to version ***3.1.0***
# 03-07-2024
## 7.1.0 compatible packages
com.moengage:moe-android-sdk:13.02.00
com.moengage:cards-core:2.0.2 //self handled cards
com.moengage:inapp:8.3.1
com.moengage:rich-notification:5.0.1
com.moengage:geofence:4.0.2
androidx.lifecycle:lifecycle-process:2.7.0
# Core 7.1.0
Updating to this version of the SDK will cause MoEngage to start tracking custom user attributes in Boolean syntax as TRUE/FALSE instead of the current 1/0 for iOS devices. This may have an effect to your segmentation and trigger conditions. If you wish to continue with the current 1/0 system, we recommend to skip upgrading this version, this will be configurable from 8.0.0 onwards.
* Added support for JSONObject values in user attributes
* Added Support for Enforcing SDK into Specific Environments
* Internal Improvements
* Android
* **BugFix**
* Event attributes not getting tracked when using MoEngage Android SDK **13.02.00** or above
# Cards 3.1.0
* Internal Improvements
# Geofence 3.1.0
* Internal Improvements
* IOS
* MoEngageGeofence version updated to **5.16.0**
# Inbox 6.1.0
* Internal Improvements
# 18-06-2024
# Core 7.0.1
Updating to this version of the SDK will cause MoEngage to start tracking custom user attributes in Boolean syntax as TRUE/FALSE instead of the current 1/0 for iOS devices. This may have an effect to your segmentation and trigger conditions. If you wish to continue with the current 1/0 system, we recommend to skip upgrading this version, this will be configurable from 8.0.0 onwards.
* Android
* ANR while accessing the Plugin version from assets in the Main Thread
# Inbox 6.0.1
* Android
* ANR while accessing the Plugin version from assets in the Main Thread
# 21-03-2024
Release of moengage-flutter version 7.0.0
## 7.0.0 compatible packages
com.moengage:moe-android-sdk:13.00.03
androidx.lifecycle:lifecycle-process:2.7.0
com.moengage:cards-core:2.0.2 //self handled cards
com.moengage:inapp:8.2.0
com.moengage:rich-notification:5.0.1
com.moengage:geofence:4.0.1
## Core 7.0.0
* Added support for Non-Intrusive Nudge InApps.
* Removed support for MI Push
* Send SelfHandled InApp Callback when data is null\
**Breaking Change:** \
***SelfHandledCampaignData***will be of type nullable.
| Then | Now |
| ----------------------------------------------------------- | ------------------------------------------------------------ |
| setSelfHandledInAppHandler((SelfHandledCampaignData data)); | setSelfHandledInAppHandler((SelfHandledCampaignData? data)); |
* Android
* Native SDK Updated to support version **13.00.00** and above. Refer to the [Release Notes](/developer-guide/release-notes/android-sdk/2024/#27th-February-2024) for behavior changes.
* Add support for AGP **8.2.2** and above
* \*\*Note:\*\*Use minimum Native Inapp version [8.1.1](/developer-guide/release-notes/android-sdk/2024/#21st-March-2024). There is a known issue regarding in-app rendering in Flutter in InApp versions **8.0.0** & **8.1.0.**
* IOS
* MoEngage-iOS-SDK version updated to **9.16.0** and above
* MoEngageInApp version updated to **4.15.0** and above
## Inbox 6.0.0
* Updated Minimum Supported **moengage\_flutter** version to **7.0.0**
* Android
* Native SDK Updated to support version **13.00.00** and above
* Add support for AGP **8.2.2** and above
* Support for native **inbox-core** version **3.0.0** and above
* IOS
* MoEngageInbox version updated to **2.15.0**
## Geofence 3.0.0
* Updated Minimum Supported **moengage\_flutter** version to **7.0.0**
* Android
* Native SDK Updated to support version **13.00.00** and above
* Add support for AGP **8.2.2** and above
* Support for native **geofence** version **4.0.0** and above
* IOS
* MoEngageGeofence version updated to **5.15.0**
## Cards 3.0.0
* Updated Minimum Supported **moengage\_flutter** version to **7.0.0**
* Android
* Native SDK Updated to support version **13.00.00** and above
* Add support for AGP **8.2.2** and above
* Support for native **cards-core** version **2.0.0** and above
* IOS
* MoEngageGeofence version updated to **4.15.0**
# 24-1-2024
## Core 6.1.1
* Fix MoEngage undefined error handling if web SDK not integrated
* Web
* Fix MoEngage undefined error handling if web SDK not integrated
# 07-12-2023
## Core 6.1.0
* Added support for array in User attributes
* Android
* Native SDK Updated to support version **12.10.01** and above
* Google Policy - Delete User details API
* Add support for Android Gradle Plugin **8.0.2** and above
* Upgrade Kotlin Version to **1.7.10**
* Handled cases where native to dart callbacks were not working with background isolate created by ***FirebaseMessaging.onBackgroundMessage*** or any other background message handlers
* IOS
* MoEngage-iOS-SDK version updated to **9.14.0**
* MoEngageInApp version updated to **4.13.0**
## Inbox 5.1.0
* Android
* Support for native **inbox-core** version **2.6.0** and above
* Add support for Android Gradle Plugin **8.0.2** and above
* Upgrade Kotlin Version to **1.7.10**
* IOS
* MoEngageInbox version updated to **2.13.0**
## Geofence 2.1.0
* Android
* Support for native **geofence** version **3.4.0** and above
* Add support for Android Gradle Plugin **8.0.2** and above
* Upgrade Kotlin Version to **1.7.10**
* IOS
* MoEngageGeofence version updated to **5.13.0**
## Cards 2.1.0
* Android
* Support for native **cards-core** version **1.6.0** and above
* Add support for Android Gradle Plugin **8.0.2** and above
* Upgrade Kotlin Version to **1.7.10**
* Handled cases where native to dart callbacks were not working with background isolate created by ***FirebaseMessaging.onBackgroundMessage*** or any other background message handlers
* IOS
* MoEngageCards version updated to **4.13.0**
# 13-09-2023
## Core 6.0.0
* Federated Plugin Implementation
* Breaking Change: Use ***import 'package:moengage\_flutter/moengage\_flutter.dart'***; to import any files in the ***moengage\_flutter*** package. Remove the existing import related to ***moengage\_flutter***
* Android
* Native SDK Updated to support version **12.9.00** and above
## Inbox 5.0.0
* Federated Plugin Implementation
* **Breaking Change:** Use ***import 'package:moengage\_inbox/moengage\_inbox.dart'***; to import any files in the ***moengage\_inbox*** package. Remove the existing import related to ***moengage\_inbox***
* Android
* Native SDK updated to support version **12.9.00** and above.
## Geofence 2.0.0
* Federated Plugin Implementation
* **Breaking Change:** Use ***import 'package:moengage\_geofence/moengage\_goefence.dart'***; to import any files in the ***moengage\_geofence*** package. Remove the existing import related to ***moengage\_geofence***
## Cards 2.0.0
* Federated Plugin Implementation
# 26-07-2023
## Core 5.5.1
* Android
* Bugfix
* Self Handled InApp delivery controls not working.
## Inbox 4.5.1
* iOS
* Bugfix
* Fixed parsing issue in ***fetchAllMessages*** API.
# 19-07-2023
## Core 5.5.0
* Android
* Plugin Base Version Updated to `~>3.3.2`
* iOS
* MoEngage-iOS-SDK version updated to `~>9.10.0`
## Inbox 4.5.0
* iOS
* MoEngageInbox SDK version updated to `~>2.8.0`.
## Geofence 1.6.0
* iOS
* MoEngageGeofence SDK version Updated to `~>5.10.0`
## Cards 1.0.0
* Initial Release - Support For Self-Handled Cards
# 31-05-2023
## Core 5.4.0
* Android
* Compile SDK Version Updated to 33.
* Support For SelfHandled Push Notification Clicks In Foreground State.
* Support for Android SDK version **12.8.00** and above
* iOS
* MoEngage-iOS-SDK version updated to **9.8.0**.
## Inbox 4.4.0
* Android
* Target & Compile SDK Version Updated to 33.
* iOS
* MoEngageInbox SDK version updated to `~>2.8.0`.
## Geofence 1.5.0
* Android
* Target & Compile SDK Version Updated to 33.
* iOS
* MoEngageInbox SDK version updated to `~>5.8.0`.
# 16-05-2023
## Core 5.3.1
* Android
* Bugfix
* Self-handled callback not working for test InApp and event-triggered InApp.
# 21-02-2023
## Geofence 1.4.0
* Android
* \*\*\*configureGeofence()\*\*\*is deprecated. Use ***startGeofenceMonitoring()*** and \*\*\*stopGeofenceMonitoring()\*\*\*in the Geofence module.
* iOS
* MoEngageGeofence SDK version updated to **5.4.0**.
* Support for ***stopGeofenceMonitoring()*** API.
# 08-02-2023
## Core 5.3.0
* Security improvement: Controlled logging
* Android
* Support for Android 13 push notification Opt-in with rationale via In-Apps.
* Device Id enable/disable support
* iOS
* MoEngage-iOS-SDK version updated to **\~>9.4.0**
## Inbox 4.3.0
* Security improvement: Controlled logging
* iOS
* MoEngageInbox SDK version updated to **\~>2.4.0**
## Geofence 1.3.0
* Security improvement: Controlled logging
* iOS
* MoEngageInbox SDK version updated to **\~>5.4.0**
## Core 5.2.0
* iOS
* MoEngage-iOS-SDK version updated to **9.2.0**
* Updated APIs
| Then | Now |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| public func initializeDefaultInstance(config: MOSDKConfig, sdkState: MoEngageSDKState = .enabled, launchOptions: \[UIApplication.LaunchOptionsKey: Any]? = nil) | public func initializeDefaultInstance(config: MoEngageSDKConfig, sdkState: MoEngageSDKState = .enabled, launchOptions: \[UIApplication.LaunchOptionsKey: Any]? = nil) |
| public func initializeDefaultInstance(\_ *config: MOSDKConfig, launchOptions: \[UIApplication.LaunchOptionsKey: Any]? = nil)* | *public func initializeDefaultInstance(*\_ config: MoEngageSDKConfig, launchOptions: \[UIApplication.LaunchOptionsKey: Any]? = nil) |
## Inbox 4.2.0
* iOS
* MoEngageInbox SDK version updated to **2.2.0**.
## Geofence 1.2.0
* iOS
* MoEngageGeofence SDK version updated to **5.2.0**.
# 04-11-2022
## Core 5.1.1
* Bugfix
* Typo fixed in ***enableAdIdTracking()***
# 27-10-2022
## Core 5.1.0
* Android
* Support for Android 13 notification permission
* Support for Android Gradle Plugin version **7.3.1**
* Build Configuration Update
* Compile SDK version - 31
* Target SDK version - 31
* Support for Android SDK version **12.4.00** and above
* iOS
* Initialization APIs are updated to initialize SDK with the state.
| Then | Now |
| -------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| initializeDefaultInstance(\_ config: MOSDKConfig, sdkState: Bool = true, launchOptions: \[UIApplication.LaunchOptionsKey: Any]? = nil) | initializeDefaultInstance(config: MOSDKConfig, sdkState: MoEngageSDKState = .enabled, launchOptions: \[UIApplication.LaunchOptionsKey: Any]? = nil) |
## Inbox 4.1.0
* Android
* Android Gradle Plugin version updated to `7.3.1`
* Gradle version updated to `7.4`
* Compile SDK Version - 31
* Target SDK version - 31
* Support for Android SDK version `12.4.00`
* Inbox Core `2.2.0`
## Geofence 1.1.0
* iOS
* MoEngageGeofence SDK version updated to `~>4.4.0`.
# 27-09-2022
## Core 5.0.0
* * Support for Android SDK version **12.2.05** and above.
* Support for iOS SDK version **8.3.1** and above.
* Breaking Changes in Dart
*
| Then | Now |
| ------------------------- | -------------------------------- |
| MoEngageFlutter() | MoEngageFlutter("YOUR\_APP\_ID") |
| optOutDataTracking(false) | enableDataTracking() |
| optOutDataTracking(true) | disableDataTracking() |
* InApp Model **InAppCampaign** broken down from a single object to multiple objects
* **InAppData**
* **ClickData**
* **SelfHandledCampaignData**
* InApp **setUpInAppCallbacks** removed and callbacks are broken down into multiple listeners.
| Callback Type | Method |
| ---------------------------------------- | --------------------------------------------------------------- |
| InApp Shown | setInAppShownCallbackHandler(InAppShownCallbackHandler) |
| InApp Dismissed | setInAppDismissedCallbackHandler(InAppDismissedCallbackHandler) |
| InApp Clicked(Navigation, Custom Action) | setInAppClickHandler(InAppClickCallbackHandler) |
| InApp Self Handled | setSelfHandledInAppHandler(SelfHandledInAppCallbackHandler) |
* The push campaign Model is restructured and renamed from **PushCampaign** to **PushCampaignData**.
* Push callback APIs are renamed.
| Then | Now |
| --------------------------------------------------- | ----------------------------------------------------- |
| setUpPushCallbacks (PushCallbackHandler) | setPushClickCallbackHandler(PushClickCallbackHandler) |
| setUpPushTokenCallback (PushTokenCallbackHandler) | setPushTokenCallbackHandler(PushTokenCallbackHandler) |
* Removed APIs
| Removed APIs |
| --------------------------- |
| selfHandledPrimaryClicked() |
| enableSDKLogs() |
| optOutInAppNotification() |
| optOutPushNotification() |
| startGeofenceMonitoring() |
* Android
* Build Configuration Updates
* Minimum SDK version - 21
* Target SDK version - 30
* Compile SDK Version - 30
* Mi SDK update to Version 5.x.x, refer to the [Configuring Xiaomi Push](https://developers.moengage.com/hc/en-us/articles/4403466194708)%20and%20update%20the%20integration).
* Removed and replaced APIs
| Then | Now |
| ------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| MoEInitializer.initialize(Context, MoEngage.Builder) | MoEInitializer.initialiseDefaultInstance(Context, MoEngage.Builder) |
| MoEInitializer.initialize(Context, MoEngage.Builder, Boolean) | MoEInitializer.initialiseDefaultInstance(Context, MoEngage.Builder, SdkState) |
* iOS
* **MOFlutterInitializer** has been renamed to **MoEngageInitialize**
* Removed and replaced APIs
| Then | Now |
| ------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| initializeWithSDKConfig(\_ config: MOSDKConfig, andLaunchOptions launchOptions: \[UIApplication.LaunchOptionsKey: Any]?) | initializeDefaultInstance(\_ config: MOSDKConfig, launchOptions: \[UIApplication.LaunchOptionsKey: Any]? = nil) |
| initializeWithSDKConfig(\_ config: MOSDKConfig, withSDKState state:Bool, andLaunchOptions launchOptions: \[UIApplication.LaunchOptionsKey: Any]?) | initializeDefaultInstance(\_ config: MOSDKConfig, sdkState: Bool = true, launchOptions: \[UIApplication.LaunchOptionsKey: Any]? = nil) |
## Inbox 4.0.0
* * Support for Android SDK version **12.2.05** and above and Native Inbox SDK Version **2.1.1** and above.
* Support for iOS SDK version **8.3.1** and above Native Inbox SDK Version **1.3.0** and above.
* Breaking changes
| Then | Now |
| --------------- | ------------------------------ |
| MoEngageInbox() | MoEngageInbox("YOUR\_APP\_ID") |
* Android
* Build Configuration Updates
* Minimum SDK version - 21
* Target SDK version - 30
* Compile SDK Version - 30
## Geofence 1.0.0
* * iOS
* Initial Release with MoEngageGeofence SDK version `~>4.3.0`.
# Core v4.2.0
**Release Date**: 29th July 2022
* * Support for Flutter 3
* Device identifier tracking update as per Google's User Data policy. Advertising Id is only tracked after user consent.
* Android
* Native SDK updated to support version `11.6.02` and above.
# Inbox v3.2.0
**Release Date**: 29th July 2022
* * Support for Flutter 3
# Core v4.1.0
**Release Date:** 6th September 2021
* * Support for HTML InApps
* Android
* Native SDK updated to support version `11.4.00` and above.
* iOS
* Native Dependencies updated to support MoEngage-iOS-SDK `7.1.0` and above
# Inbox v3.1.0
**Release Date:** 6th September 2021
* * Android
* Native SDK updated to support version `11.4.00` and above.
# Core v4.0.2
**Release Date:** 21st August 2021
* Bugfix
* Calling SDK APIs when the application is in the background throws an error on Android.
# Core v4.0.1
**Release Date:** 15th June 2021
* Fixes: Push click callback failing due to parsing error.
# Core v4.0.0
**Release Date:** 12th May 2021
* Migrated the library to null safety.
* Require Dart 2.12 or greater.
* Bumped flutter dependency constraint to min version `1.17.0`
* Android
* Native SDK updated to support version `11.2.00` and above.
# Inbox v3.0.0
**Release Date:** 12th May 2021
* Migrated the library to null safety.
* Require Dart 2.12 or greater.
* Android
* Native SDK updated to support version `11.2.00` and above.
* Migrated Native Inbox artifact from `addon-inbox` to `inbox-core`.
# Core v3.0.1
**Release Date:** 28th April 2021
* iOS
* Added ObjC support for `MOFlutterInitializer` class
* PodSpec changes to set deployment target to iOS 10.0.
# Inbox v2.0.0
**Release Date:** 26th February 2021
* Native Dependencies updated to support MoEngage-iOS-SDK `7.*` and above
* Native SDK updated to support version `6.0.2` and above. Refer to the [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#11-0-04-24-02-2021) for behavior changes.
* Native Inbox SDK updated to support version `6.0.2` and above.
# Core v3.0.0
**Release Date:** 26th February 2021
* Android Native SDK updated to support version `11.0.04` and above. Refer to the [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#11-0-04-24-02-2021) for behavior changes.
* Plugin now supports iOS 10.0 and above.
* iOS Native Dependencies updated to support MoEngage-iOS-SDK `7.*` and above
* Added Dart APIs to enable and disable MoEngage SDK.
* Added Dart API to register a callback for push token-generated event.
# Core v2.0.2
**Release Date:** 15th November 2021
* Android dependencies updated to use versions published on Maven Central.
# Inbox v1.0.2
**Release Date:** 15th November 2021
* Android dependencies updated to use versions published on Maven Central.
# Web v0.0.1
**Release Date:** 30th December 2020
* Support for Moengage Web SDK for Flutter.
# v3.0.0-beta.1
**Release Date:** 30th December 2020
* Support for Moengage Web SDK for Flutter.
# v Core v2.0.2
**Release Date:** 7th December 2020
* Support for extending Native Android Callbacks if required.
* Native Android SDK version required is `10.5.00` or above
# Inbox v.1.0.0, v1.0.1
**Release Date**: 6th November 2020
* Initial release
* APIs
* Fetch All Messages
* Get unclicked count
* Track message clicked
* Delete message
# Core v2.0.1
**Release Date**: 6th November 2020
* Fixes: Set AppStatus method was getting called internally with other plugin channel methods.
# Core v2.0.0
**Release Date**: 23rd October 2020
* Support for In-App V3
* Support for Self-Handled In-App
* Support for Push Templates
* Support for Huawei Push Kit
* Android SDK updated to support `10.4.03` and above.
* iOS SDK dependency changed to support versions greater than `6.0.0`.
* Deprecated APIs
| Then | Now |
| --------------------------------------------------- | ---------------------------------------------- |
| MoEProperties().addInteger(String, int) | MoEProperties().addAttribute.(String, dynamic) |
| MoEProperties().addString(String, String) | MoEProperties().addAttribute(String, dynamic) |
| MoEProperties().addBoolean(String, bool) | MoEProperties().addAttribute(String, dynamic) |
| MoEProperties().addDouble(String, double) | MoEProperties().addAttribute(String, dynamic) |
| MoEProperties().addLocation(String, MoEGeoLocation) | MoEProperties().addAttribute(String, dynamic) |
* Removed APIs
| Then | Now |
| --------------------- | --------------------------- |
| onPushClick(Map) | onPushClick(PushCampaign) |
| onInAppClick(Map) | onInAppClick(InAppCampaign) |
| onInAppShown(Map) | onInAppShown(InAppCampaign) |
| passPushToken(String) | passFCMPushToken(String) |
| passPushPayload(Map) | passFCMPushPayload(Map) |
* Removed APIs Android
| Then | Now |
| ----------------------------------- | ---------------------------------------------------- |
| MoEInitializer.initialize(MoEngage) | MoEInitializer.initialize(Context, MoEngage.Builder) |
# Core v1.1.0
**Release Date**: 10th February 2020
* Add Dart APIs for passing FCM Push Token and FCM Push Payload from the Android Platform.
# Core v1.0.1
**Release Date**: 17th December 2019
* Sample Updated
* ReadMe Updated
* Improved logging
# Core v1.0.0
**Release Date**: 16th December 2019
* Initial Release
# 2023 and Older
Source: https://moengage.com/docs/developer-guide/release-notes/ios-sdk/2023-and-older
View the 2023 and older release notes and changelogs for the MoEngage iOS Native SDK.
**Information**
You can now get notified whenever MoEngage releases a new version of the iOS Native SDK. For more information, refer to [Subscribe to MoEngage SDK Releases](/developer-guide/release-notes/subscribe-to-moengage-sdk-releases/subscribe-to-mo-engage-sdk-releases).
■ Updated: Module version has been updated in this release.
■ Unchanged: Module remains on the previous version.
~~■ Deprecated:~~ Module is deprecated and will be removed in a future release.
# 30th November 2023
### Release Summary
| Module | Version | Update/Dependencies |
| :------------------------------ | :------ | :------------------------ |
| Core | 9.14.0 | swift = 5.0.0, iOS = 11.0 |
| InApp | 4.13.0 | SHA256 Algorithm |
| Cards | 4.13.0 | SHA256 Algorithm |
| Geofence | 5.13.0 | Core SDK 9.14.0 |
| RichNotification | 7.13.0 | SHA256 Algorithm |
| Inbox | 2.13.0 | Core SDK 9.14.0 |
| RealTimeTrigger | 2.13.0 | Core SDK 9.14.0 |
## Core
* Updated hashing algorithm usages to SHA256.
Fixes:
* Handled removing of invalid value from an array of user attributes and parsing the rest.
* Fixed redirection URLs being percent encoded.
* Bug fix for processing notifications action for Screen-Navigation from Inbox(Notification Center) is not behaving the same in SDK version 9.xx as it used to be in 7.xx series.
## InApp
* Updated hashing algorithm usages to SHA256.
## Cards
* Updated hashing algorithm usages to SHA256.
## Geofence
* Updated the dependency to MoEngage-iOS-SDK 9.14.0.
## RichNotification
* Updated hashing algorithm usages to SHA256.
## Inbox
* Updated the dependency to MoEngage-iOS-SDK 9.14.0.
## RealTimeTrigger
* Updated the dependency to MoEngage-iOS-SDK 9.14.0.
# 16th November 2023
### Release Summary
| Module | Version | Update/Dependencies |
| :------------------- | :------ | :------------------ |
| InApp | 4.12.1 | Core SDK 9.13.0 |
| Cards | 4.12.1 | Core SDK 9.13.0 |
## InApp
* Added self-handled inapps for tvOS.
## Cards
* Added self-handled cards for tvOS.
# 15th November 2023
### Release Summary
| Module | Version | Update/Dependencies |
| :------------------------------ | :------ | :------------------ |
| Core | 9.13.0 | Impression API |
| InApp | 4.12.0 | OR Conditions |
| Cards | 4.12.0 | tvOS Support |
| Geofence | 5.12.0 | Core SDK 9.13.0 |
| RichNotification | 7.12.0 | Impression API |
| Inbox | 2.12.0 | background sync fix |
| RealTimeTrigger | 2.12.0 | Core SDK 9.13.0 |
## Core
* Added notification impression and click API.
* Cards in first app.
Fixes:
* Fixed the common logs issue.
* Incorrect model\_name tracked for iPhone 14 Pro.
## InApp
* Added self-handled inapps for tvOS.
* Added OR condition support for trigger events.
## Cards
* Added self-handled cards for tvOS.
## Geofence
* Updated the dependency to MoEngage-iOS-SDK 9.13.0.
## RichNotification
* Added notification impression and click API.
## Inbox
Fixes:
* Notification are not listed in the inbox when app is in background and storage encryption is enabled.
* Fixed the clicked state for inbox message when the notification is clicked from terminate state.
## RealTimeTrigger
* Updated the dependency to MoEngage-iOS-SDK 9.13.0.
# 26th September 2023
### Release Summary
| Module | Version | Update/Dependencies |
| :------------------------------ | :------ | :------------------ |
| Core | 9.12.0 | Extension Fix |
| InApp | 4.11.2 | Core SDK 9.12.0 |
| Cards | 4.11.1 | Card UI Fixes |
| Geofence | 5.11.1 | Core SDK 9.12.0 |
| RichNotification | 7.11.1 | Gif handling |
| Inbox | 2.11.1 | Core SDK 9.12.0 |
| RealTimeTrigger | 2.11.1 | Core SDK 9.12.0 |
## Core
Fixes:
* Fixed **setImage** and **setGIF**\* extension methods name collision.
## InApp
* Updated the dependency to MoEngage-iOS-SDK 9.12.0.
## Cards
Fixes:
* Fixed **setImage** and **setGIF**\* extension methods name collision.
* Fixed invalid gif data not falling back to static image.
* Fixed text styles getting duplicated in Card UI.
* Updated the dependency to MoEngage-iOS-SDK 9.12.0.
## Geofence
* Updated the dependency to MoEngage-iOS-SDK 9.12.0.
## RichNotification
Fixes:
* Fixed **setImage** and **setGIF**\* extension methods name collision.
* Fixed invalid gif data not falling back to static image.
* Fixed gif getting duplicated in carousal.
* Updated the dependency to MoEngage-iOS-SDK 9.12.0.
## Inbox
* Updated the dependency to MoEngage-iOS-SDK 9.12.0.
## RealTimeTrigger
* Updated the dependency to MoEngage-iOS-SDK 9.12.0.
# 19th September 2023
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :----------- |
| Core | 9.11.3 | Optimization |
## Core
* Internal code optimizations.
# 14th September 2023
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :----------- |
| Core | 9.11.2 | Gzip Support |
## Core
* Updated the default Gzip state.
# 12th September 2023
### Release Summary
| Module | Version | Update |
| :------------------- | :------ | :------------- |
| Core | 9.11.1 | Delayed InApps |
| InApp | 4.11.1 | Delayed InApps |
## Core
* Added delayed InApps support.
## InApp
* Added delayed InApps support.
* Updated the dependency to MoEngage-iOS-SDK to 9.11.1.
# 30th August 2023
### Release Summary
| Module | Version | Update/Dependencies |
| :------------------------------ | :------ | :------------------ |
| Core | 9.11.0 | GZIP support |
| InApp | 4.11.0 | HTML InApp fix |
| Cards | 4.11.0 | Category API fix |
| Geofence | 5.11.0 | Core SDK 9.11.0 |
| RichNotification | 7.11.0 | Optimizations |
| Inbox | 2.11.0 | Core SDK 9.11.0 |
| RealTimeTrigger | 2.11.0 | Core SDK 9.11.0 |
## Core
* Added GZIP Support in all API calls.
* Internal Code Optimizations.
## InApp
Fixes:
* Fixed the boolean value tracked as 0/1 in HTML InApp.
* Fixed API failure tracked when the campaign is paused.
* Updated the dependency to MoEngage-iOS-SDK 9.11.0.
## Cards
Fixes:
* **getCardsForCategory** API returns all cards if the category is **All**.
* Updated the dependency to MoEngage-iOS-SDK 9.11.0.
## Geofence
* Updated the dependency to MoEngage-iOS-SDK 9.11.0.
## RichNotification
* Updated the dependency to MoEngage-iOS-SDK 9.11.0.
* Internal Code Optimizations.
## Inbox
* Updated the dependency to MoEngage-iOS-SDK 9.11.0.
## RealTimeTrigger
* Updated the dependency to MoEngage-iOS-SDK 9.11.0.
# 16th August 2023
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :-------------- |
| Core | 9.10.2 | Migration Crash |
## Core
CrashFix:
* Fixed crash while serializing the JSON by removing invalid values on migration.
# 7th August 2023
### Release Summary
| Module | Version | Update |
| :---------------------- | :------ | :------------ |
| Geofence | 5.10.1 | Threading Fix |
## Geofence
* Fixed the threading issue in geofence module by unblocking the main thread.
# 1st August 2023
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :---------- |
| Core | 9.10.1 | SSL Pinning |
## Core
* Added SSL pinning support for network requests.
# 18th July 2023
### Release Summary
| Module | Version | Update/Dependencies |
| :------------------------------ | :------ | :------------------ |
| Core | 9.10.0 | DC-100 support |
| InApp | 4.10.0 | nil handling |
| Cards | 4.10.0 | Sync API |
| Geofence | 5.10.0 | Xcode Config |
| RichNotification | 7.10.0 | Xcode Config |
| Inbox | 2.10.0 | Xcode Config |
| RealTimeTrigger | 2.10.0 | Xcode Config |
## Core
* Added DC-100 data centre.
* iOS breakpoint issue fix by changing the Xcode config settings.
Fixes:
* Handled duplicate tracking of Push-Preference.
* Fixed API connection timeout.
## InApp
* iOS breakpoint issue fix by changing the Xcode config settings.
CrashFix:
* Fixed crash by handling the nil value.
## Cards
* Added Cards sync API and Cards delivered API.
* iOS breakpoint issue fix by changing the Xcode config settings.
## Geofence
* iOS breakpoint issue fix by changing the Xcode config settings.
## RichNotification
* iOS breakpoint issue fix by changing the Xcode config settings.
## Inbox
* iOS breakpoint issue fix by changing the Xcode config settings.
## RealTimeTrigger
* iOS breakpoint issue fix by changing the Xcode config settings.
# 20th June 2023
### Release Summary
| Module | Version | Update/Dependencies |
| :------------------------------ | :------ | :------------------ |
| Core | 9.9.0 | Xcode 14.3.1 |
| InApp | 4.9.0 | Xcode 14.3.1 |
| Cards | 4.9.0 | Xcode 14.3.1 |
| Geofence | 5.9.0 | Xcode 14.3.1 |
| RichNotification | 7.9.0 | Xcode 14.3.1 |
| Inbox | 2.9.0 | Xcode 14.3.1 |
| RealTimeTrigger | 2.9.0 | Xcode 14.3.1 |
## All Modules
* iOS breakpoint issue fix by creating framework from Xcode 14.3.1.
# 16th June 2023
### Release Summary
| Module | Version | Update |
| :------------------- | :------ | :------- |
| Cards | 4.8.1 | Sync API |
## Cards
* Added cards sync API for self-handled cards.
CrashFix:
* Fixed crash by returning the completion handler in main thread.
# 2nd June 2023
### Release Summary
| Module | Version | Update |
| :------------------- | :------ | :--------- |
| InApp | 4.8.3 | Sync Logic |
## InApp
Fixes:
* Handled the callback for selfHandled InApp when called before sync API.
# 31st May 2023
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :---------------- |
| Core | 9.8.2 | Extension details |
## Core
Fixes:
* Added integration details in Extension API call.
# 25th May 2023
### Release Summary
| Module | Version | Update |
| :------------------- | :------ | :---------------- |
| Core | 9.8.1 | Primitive Arrays |
| InApp | 4.8.2 | General fetch fix |
## Core
* Adding support to track primitive arrays in UserAttributes.
* Additional Constructor with Data Center Support.
## InApp
CrashFix:
* Fixed crash by adding null check while fetching general in-apps.
# 12th May 2023
### Release Summary
| Module | Version | Update |
| :------------------- | :------ | :--------------- |
| InApp | 4.8.1 | completion crash |
| Inbox | 2.8.1 | RTL Support |
## InApp
CrashFix:
* Fixed crash due to completion handler.
## Inbox
* Added RTL support for Inbox message and date.
# 4th May 2023
### Release Summary
| Module | Version | Update |
| :------------------------------ | :------ | :---------------------- |
| Core | 9.8.0 | Target 11.0, Encryption |
| InApp | 4.8.0 | Encryption Support |
| Cards | 4.8.0 | Encryption Support |
| Geofence | 5.8.0 | Encryption Support |
| RichNotification | 7.8.0 | Encryption Support |
| Inbox | 2.8.0 | Encryption Support |
| RealTimeTrigger | 2.8.0 | Encryption Support |
## All Modules
* Updated the deployment target to 11.0.
* Added support for API and Storage Encryption.
## Core
* Added MoEngageSecurity framework.
# 17th April 2023
### Release Summary
| Module | Version | Update/Dependencies |
| :------------------------------ | :------ | :------------------ |
| Core | 9.7.0 | DC-05 support |
| InApp | 4.7.0 | Core SDK 9.7.0 |
| Cards | 4.7.0 | Core SDK 9.7.0 |
| Geofence | 5.7.0 | Core SDK 9.7.0 |
| RichNotification | 7.7.0 | Core SDK 9.7.0 |
| Inbox | 2.7.0 | Core SDK 9.7.0 |
| RealTimeTrigger | 2.7.0 | Core SDK 9.7.0 |
## Core
* Added DC-05 support.
# 11th April 2023
### Release Summary
| Module | Version | Update/Dependencies |
| :------------------------------ | :------ | :------------------ |
| Core | 9.6.0 | deviceType track |
| InApp | 4.6.0 | optimisation |
| Cards | 4.6.0 | optimisation |
| Geofence | 5.6.0 | Core SDK 9.6.0 |
| RichNotification | 7.6.0 | Core SDK 9.6.0 |
| Inbox | 2.6.0 | Core SDK 9.6.0 |
| RealTimeTrigger | 2.6.0 | Core SDK 9.6.0 |
## Core
* Added support to track **deviceType**.
* Internal Code optimization.
## InApp
* Updated the dependency to MoEngage-iOS-SDK 9.6.0.
* Internal Code optimisation.
## Cards
* Updated the dependency to MoEngage-iOS-SDK 9.6.0.
* Internal Code optimisation.
# 17th March 2023
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :---------------- |
| Core | 9.5.1 | SceneDelegate fix |
## Core
Fixes:
* Handled the deep link callback to **SceneDelegate** class.
CrashFix:
* Fixed crash due to data race condition in the Core module.
# 6th March 2023
### Release Summary
| Module | Version | Update |
| :------------------- | :------ | :----------- |
| Inbox | 2.5.1 | Optimization |
## Inbox
* Internal code optimization.
# 22nd February 2023
### Release Summary
| Module | Version | Update/Dependencies |
| :------------------------------ | :------ | :------------------ |
| Core | 9.5.0 | optimization |
| InApp | 4.5.0 | Core SDK 9.5.0 |
| Cards | 4.5.0 | Core SDK 9.5.0 |
| Geofence | 5.5.0 | Core SDK 9.5.0 |
| RichNotification | 7.5.0 | Core SDK 9.5.0 |
| Inbox | 2.5.0 | Core SDK 9.5.0 |
| RealTimeTrigger | 2.5.0 | Core SDK 9.5.0 |
## Core
* Code optimization.
# 7th February 2023
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :-------------- |
| Core | 9.4.1 | Migration crash |
## Core
CrashFix:
* Fixed the crash when migrating from 8.2.0 to 9.x.x.
# 6th February 2023
### Release Summary
| Module | Version | Update/Dependencies |
| :--------------------------- | :------ | :------------------ |
| Core | 9.4.0 | External Browser |
| InApp | 4.4.0 | SMS action fix |
| Cards, Geofence, Rich, Inbox | vX.4.0 | Core SDK 9.4.0 |
## Core
* Code optimization.
Fixes:
* Handled the logic to open the URL in an external browser.
CrashFix:
* Fixed the crash by handling data race conditions in Messaging module.
## InApp
* Code optimization.
Fixes:
* Handled sms action when message contains space.
# 1st February 2023
### Release Summary
| Module | Version | Update |
| :------------------- | :------ | :------------- |
| InApp | 4.3.1 | validation fix |
## InApp
* Fixed the validation condition to consider non-expired campaigns for displaying.
# 25th January 2023
### Release Summary
| Module | Version | Update/Dependencies |
| :----------------------------- | :------ | :------------------ |
| Core | 9.3.0 | stopGeofence |
| InApp | 4.3.0 | Core SDK 9.3.0 |
| Cards | 4.3.0 | Core SDK 9.3.0 |
| Geofence | 5.3.0 | stop API |
| Rich, Inbox, RTT | vX.3.0 | Core SDK 9.3.0 |
| RealTimeTrigger | 2.4.0 | Core SDK 9.4.0 |
## Core
* Support for **stopGeofenceMonitoring** API in Geofence module.
## Geofence
* Added **stopGeofenceMonitoring** API to support stop geofence monitoring.
# 24th January 2023
### Release Summary
| Module | Version | Update |
| :------------------- | :------ | :------------- |
| InApp | 4.2.2 | NULL timestamp |
## InApp
CrashFix:
* Fixed the crash by handling **NULL** in inapp timestamp.
# 20th January 2023
### Release Summary
| Module | Version | Update |
| :------------------- | :------ | :-------------- |
| Core | 9.2.3 | migration crash |
| InApp | 4.2.1 | stats migration |
## Core
CrashFix:
* Fixed migration crash for session and source.
## InApp
CrashFix:
* Fixed the migration crash for inapp stats.
# 11th January 2023
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :----- |
| Core | 9.2.2 | DC-04 |
## Core
Fixes:
* Added DC-04 support.
# 6th January 2023
### Release Summary
| Module | Version | Update |
| :------------------- | :------------ | :--------------- |
| Cards | 4.2.1 / 3.7.1 | Click update fix |
## Cards
Fixes:
* Cards clicked status is not being updated for self handled cards.
# 3rd January 2023
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :----------- |
| Core | 9.2.1 | Deeplink Fix |
## Core
Fixes:
* Fixed the delay in deeplink callback for the custom URL scheme.
CrashFix:
* Handled the crash when registering for remote notifications.
# 28th December 2022
### Release Summary
| Module | Version | Update/Dependencies |
| :------------------------------ | :------ | :------------------ |
| Core | 9.2.0 | Carousel fix |
| RichNotification | 7.2.0 | Carousel fix |
| InApp, Cards, Geofence | vX.2.0 | Core SDK 9.2.0 |
| Inbox, RTT | vX.2.0 | Core SDK 9.2.0 |
## Core
Fixes:
* Fixed Carousel image not displaying multiple images.
CrashFix:
* Fixed the crash when migrating from 8.2.0 to 9.1.0.
## RichNotification
Fixes:
* Fixed Carousel image not displaying multiple images.
# 23rd December 2022
### Release Summary
| Module | Version | Update/Dependencies |
| :------------------------------ | :------ | :------------------ |
| Core | 8.7.0 | Carousel fix |
| RichNotification | 6.7.0 | Carousel fix |
| InApp, Cards, Geofence | vX.7.0 | Core SDK 8.7.0 |
| Inbox, RTT | 1.7.0 | Core SDK 8.7.0 |
## Core
Fixes:
* Carousel image not displaying multiple images.
## RichNotification
* Carousel image not displaying multiple images.
# 13th December 2022
### Release Summary
| Module | Version | Update |
| :------------------------------ | :------ | :----------------- |
| Core | 9.1.0 | Landing action fix |
| InApp | 4.1.0 | dSYM Support |
| Cards | 4.1.0 | Sorting Fix |
| Geofence | 5.1.0 | dSYMs Files |
| RichNotification | 7.1.0 | Carousel Mismatch |
| Inbox | 2.1.0 | dSYMs Files |
| RealTimeTrigger | 2.1.0 | dSYMs Files |
## Core
Fixes:
* Handling the logic to discard RichLanding action if the url does not start with **http:** or **https:**.
* Carousel Image Order Mismatch in collapsed mode for rich notifications.
## InApp
* Added dSYM file support for debugging.
## Cards
Fixes:
* Handle sorting of self handled cards based on the pinned cards and updated time for cards.
* Cards clicked status is not being updated for self handled cards.
## Geofence
* Added dSYMs files for debugging.
## RichNotification
Fixes:
* Carousel Image Order Mismatch in collapsed mode for rich notifications.
## Inbox
* Added dSYMs files for debugging.
## RealTimeTrigger
* Added dSYMs files for debugging.
# 12th December 2022
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :---------- |
| Core | 8.6.0 | dSYMs Files |
| Sub-modules | vX.6.0 | dSYMs Files |
## All Modules
* Added dSYMs files for debugging.
# 12th December 2022 (v8.5.0)
### Release Summary
| Module | Version | Update/Dependencies |
| :------------------------------ | :------ | :------------------ |
| Core | 8.5.0 | Carousel Order |
| InApp | 3.5.0 | Core SDK 8.5.0 |
| Cards | 3.5.0 | sorting fix |
| Geofence | 4.5.0 | Core SDK 8.5.0 |
| RichNotification | 6.5.0 | Carousel Order |
| Inbox, RTT | 1.5.0 | Core SDK 8.5.0 |
## Core
Fixes:
* Handled Carousel Image Order Mismatch in collapsed mode for rich notifications.
## Cards
Fixes:
* Handle sorting of self handled cards based on the pinned cards and updated time for cards.
* Cards clicked status is not being updated for self handled cards.
## RichNotification
* Handled Carousel Image Order Mismatch in collapsed mode for rich notifications.
# 8th December 2022
### Release Summary
| Module | Version | Update |
| :------------------- | :------------ | :--------------- |
| InApp | 4.0.1 / 3.4.2 | Duplicate Events |
## InApp
Fixes:
* Fixed duplicate events being tracked for inapps.
# 7th December 2022
### Release Summary
| Module | Version | Update/Dependencies |
| :------------------- | :------ | :------------------ |
| Core | 9.0.0 | modular Separation |
| InApp | 4.0.0 | Swift Migration |
| Sub-modules | vX.0.0 | MoEngage prefix |
## Core
Breaking Changes:
* Removed optional modules from MoEngageSDK target.
* Updated **disableBadgeReset** method of **MoEngageSDKMessaging** to take Bool as its parameter.
* All the classes and modules are prefixed with **MoEngage**.
* Renamed **MOCore** to **MoEngageCore** for iphone SDK and TVOS SDK.
Fixes:
* Badge is not getting reset when the disableBadgeReset is set as false.
* Fixed test inapp api getting called multiple times on clicking the test inapp Pushnotification.
## InApp
* Migrated **MoEngageInApp**, **MoEngageInAppCampaign**, **MoEngageInAppSelfHandledCampaign**, **MoEngageInAppAction**, **MoEngageInAppNativeDelegate** from Objective-C to Swift.
* Added API documentation.
* All the classes and modules are prefixed with **MoEngage**.
Fixes:
* Fixed Inapp getting auto dismissed before the auto dismiss interval expires.
## Sub-modules
* All the classes and modules are prefixed with **MoEngage**.
# 1st December 2022
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :------------ |
| Core | 8.4.3 | DC-04 support |
## Core
* Added DC-04 support.
# 30th November 2022
### Release Summary
| Module | Version | Update |
| :----------------------------- | :------ | :------------- |
| Inbox | 1.4.1 | Duplicate sync |
| RealTimeTrigger | 1.4.1 | Duplicate sync |
## Inbox
Fixes:
* Handled removing of duplicate inbox messages when received via sync API.
* Updated the logic for persistent storage of inbox messages.
## RealTimeTrigger
Fixes:
* Handled removing of duplicate RTT campaigns when received via sync API.
# 17th November 2022
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :-------------- |
| Core | 8.4.2 | NaN Payload fix |
## Core
CrashFix:
* Updated AppDelegate swizzler to handle crash while registering for remote notifications.
* Handled removing of **infinity** and **NaN** from the payload on migration.
# 11th November 2022
### Release Summary
| Module | Version | Update |
| :------------------- | :------ | :---------------- |
| Cards | 3.4.2 | All category hide |
## Cards
* Handled the "All" category in Cards UI to be hidden by default for landscape mode.
# 9th November 2022
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :------------- |
| Core | 8.4.1 | Float tracking |
## Core
CrashFix:
* Fixed Crash while passing **infinity** and **NaN** to SDK via user attributes and track event properties.
Fixes:
* Added support to track userAttribute of type **Float**.
# 28th October 2022
### Release Summary
| Module | Version | Update |
| :------------------- | :------ | :---------------- |
| Cards | 3.4.1 | All category hide |
## Cards
* Handled the "All" category in Cards UI to be hidden by default.
# 21st October 2022
### Release Summary
| Module | Version | Update |
| :------------------- | :------ | :------------------ |
| InApp | 3.4.1 | SceneDelegate inset |
## InApp
* Added support to take safeArea inset for Applications with SceneDelegate.
# 18th October 2022
### Release Summary
| Module | Version | Update/Dependencies |
| :------------------- | :------ | :------------------- |
| Core | 8.4.0 | state initialization |
| InApp | 3.4.0 | Custom inset |
| Sub-modules | vX.4.0 | Core SDK 8.4.0 |
## Core
* Added MoEngageSDK Initialization method with SDK State.
* Fixed handling of notification observers to avoid runtime crashes.
* Added exception handling to fix the crashes in a few scenarios.
## InApp
* Added support to take the custom inset for InApp nudge in **MOSDKConfig** using **MoEngageInAppConfig** class.
# 3rd October 2022
### Release Summary
| Module | Version | Update |
| :------------------------------ | :------ | :----------------- |
| RichNotification | 6.3.2 | badge count update |
| RealTimeTrigger | 1.3.1 | badge count update |
## RichNotification & RealTimeTrigger
* Handled updating of badge count for Notifications.
# 22nd September 2022
### Release Summary
| Module | Version | Update |
| :------------------- | :------ | :---------------- |
| Core | 8.3.1 | ISO date format |
| Inbox | 1.3.1 | click Mark Read |
| InApp | 3.3.1 | dataType mismatch |
## Core
* Added support for **setUserAttributeISODate** in the ISO format **yyyy-MM-dd'T'HH:mm:ss.SSS'Z'**.
* Added API **setDateOfBirthInISO** to track Date of birth in ISO format.
* Added API **MoESdkStateHelper.isSDKInitialized** to check if SDK is initialised.
## Inbox
* Added completionHandler for API **markInboxNotificationClick**, **removeInboxMessage** and **removeInboxMessages**.
* On calling **trackInboxClick**, the notification will be marked as read.
## InApp
* Handled dataType mismatch in **trackDismiss** of HTML InApp.
# 1st August 2022
### Release Summary
| Module | Version | Update |
| :------------------------------ | :------ | :---------------- |
| RichNotification | 6.3.1 | resource download |
## RichNotification
* Handled downloading of resources for Basic notification.
# 20th July 2022
### Release Summary
| Module | Version | Update/Dependencies |
| :------------------------------ | :------ | :------------------- |
| Core | 8.3.0 | multithreading Fix |
| InApp, Inbox, RTT | vX.3.0 | Core SDK 8.3.0 |
| RichNotification | 6.3.0 | stats tracking fix |
| Cards | 3.3.0 | UIRefreshControl fix |
| Geofence | 4.3.0 | Core SDK 8.3.0 |
## Core
* Fixed multithreading issue in SDK, which led to crashes in few cases.
* Added API **MoESdkStateHelper.isSDKEnabled** to fetch current state of the SDK.
## RichNotification
* Updated the dependency to MoEngage-iOS-SDK 8.3.0.
* Campaign stats tracking was missed in some cases from the Notification Service extension.
## Cards
* Updated the dependency to MoEngage-iOS-SDK 8.3.0.
Fixes:
* Fixed issue in UIRefreshControl.
# 22nd June 2022
### Release Summary
| Module | Version | Update |
| :------------------------------ | :------ | :------------------ |
| Core | 8.2.1 | lldb Swift fix |
| InApp | 3.2.1 | lldb Swift fix |
| Inbox | 1.2.1 | color customisation |
| RealTimeTrigger, Rich, Geofence | vX.2.1 | lldb Swift fix |
| Cards | 3.2.1 | color customisation |
## Core
Fixes:
* Fixed the lldb issue when integrating MoEngage-iOS-SDK to Swift application.
* Removed public init method for UIColor.
## InApp
* Fixed the lldb issue when integrating MoEngage-iOS-SDK to Swift application.
## Inbox
Fixes:
* Fixed the lldb issue when integrating MoEngage-iOS-SDK to Swift application.
* Handled customisation of **navigationBarColor** when pushing the InboxController.
## Cards
Fixes:
* Fixed the lldb issue when integrating MoEngage-iOS-SDK to Swift application.
* Handled the customisation of **cardSelectionTintColor** and **navigationBarColor** when presenting and pushing the CardsController.
# 15th June 2022
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :------------- |
| Core | 7.2.2 | user reset fix |
## Core
* Handled removing of UniqueID from storage on resetting the user.
# 7th June 2022
### Release Summary
| Module | Version | Update/Dependencies |
| :------------------------------ | :------ | :------------------ |
| Core | 8.2.0 | **SPM support** |
| InApp | 3.2.0 | Trigger Changes |
| Inbox | 1.2.0 | module separation |
| RealTimeTrigger | 1.2.0 | module separation |
| RichNotification | 6.2.0 | name change |
| Cards | 3.2.0 | name change |
| Geofence | 4.2.0 | name change |
## Core
* Updated the framework name from MoEngage to **MoEngageSDK**.
* RealTimeTrigger and Inbox feature is separated from MoEngageSDK. Hence these modules must be integrated explicitly.
* Deprecated existing UserAttribute methods.
* Provided Swift Package manager support to install the SDK.
## InApp
* Changes to support App version, SDK version and platform in the trigger condition of InApps.
* Updated the dependency to MoEngage-iOS-SDK 8.2.0.
* Renamed the module to **MoEngageInApps**.
* Provided Swift Package manager support to install the SDK.
Fixes:
* Fixed the parsing error in InApp payload due to datatype mismatch.
## Other Modules
* Updated the dependency to MoEngage-iOS-SDK 8.2.0.
* Renamed modules (e.g., **MoEngageRichNotification**, **MoEngageCards**, **MoEngageGeofence**).
* Provided Swift Package manager support to install the SDK.
* Breaking Inbox and RTT from the main SDK.
# 14th April 2022
### Release Summary
| Module | Version | Update |
| :------------------- | :------ | :------------- |
| InApp | 2.2.1 | label line fix |
## InApp
* Fixed the appearance of thin grey line above the label in the InApp when displayed in larger screen devices.
# 11th February 2022
### Release Summary
| Module | Version | Update |
| :------------------- | :------ | :------------ |
| Core | 7.2.1 | Threading |
| Cards | 2.2.1 | OS 12.4 crash |
## Core
* Handled SDK initialisation from background thread.
## Cards
* Handled crash in CardsController in 12.4 OS version.
# 31st January 2022
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :---------------- |
| Core | 7.2.0 | Capacitor support |
## Core
* Added **Capacitor** integration type.
* MORichNotification dependency updated to **\~> 5.3.0** (Fixed height for the message in the notification).
* InApp, Cards dependency updated to **\~> 2.2.0**.
* Geofence dependency updated to **\~> 3.2.0**.
# 29th December 2021
### Release Summary
| Module | Version | Update |
| :------------------- | :------ | :--------------- |
| Core | 7.1.4 | version tracking |
| InApp | 2.1.2 | version tracking |
## Core & InApp
* SDK version tracking fix, version was being tracked incorrectly in a few cases.
# 24th December 2021
### Release Summary
| Module | Version | Update |
| :------------------- | :------ | :------------ |
| InApp | 2.1.1 | text clipping |
## InApp
* Handled multiline text in text widget getting clipped in some of the devices.
# 2nd December 2021
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :--------------------- |
| Core | 7.1.3 | Version Implementation |
## Core
* Changed the implementation to determine SDK version, as in a few instances App Version was getting tracked as SDK version.
# 29th October 2021
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :-------------- |
| Core | 7.1.2 | Nullability fix |
## Core
* Handled warning in **MoEngageCore** due to missing nullability type specifier.
# 23rd September 2021
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :--------------------- |
| Core | 7.1.1 | RichNotification 5.2.0 |
## Core
* MORichNotification dependency updated to **\~> 5.2.0**.
* Changes in custom Push Template implementation to have layout in-line with iOS 15.0 standard notifications UI.
# 31st August 2021
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :-------------- |
| Core | 7.1.0 | **XCFramework** |
## Core
* Released SDK Modules as **XCFramework**.
* HTML InApp Support Added.
* Delivery Funnel implementation for InApps.
* Handling of Control Group Error in InApps.
* Campaign Context tracking for in-app Stats.
* Added a method to detect App Launches due to MoEngage silent push notifications.
# 5th August 2021
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :---------------------- |
| Core | 7.0.5 | URL percentage encoding |
## Core
* Image resources, Deep links, and Richlanding URLs are now percentage encoded if not already and then processed.
# 6th April 2021
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :----------------- |
| Core | 7.0.3 | multithreading Fix |
## Core
* Fixed a multithreading issue in Analytics Module, which led to crashes in a few cases.
# 25th February 2021
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :----------- |
| Core | 7.0.2 | Blacklisting |
## Core
* Support for User Attribute Blacklisting with the remote config.
# 18th January 2021
### Release Summary
| Module | Version | Update |
| :------------------ | :------------ | :---------------- |
| Core | 7.0.0 / 7.0.1 | **Dropped iOS 9** |
## Core
* **MOSDKConfig** class introduced to initialize the SDK with new initialization methods.
* Remote Logger added for debugging.
* API Encryption option provided in the SDK.
* SDK UserDefault keys saved in a separate suite and not in standard User Defaults.
* SDK API Hosts are updated, configure the same by setting appropriate Data Center in **MOSDKConfig**.
* SDK to support iOS 10.0 and above, iOS 9.\* support dropped.
* Internal optimizations.
# 29th December 2020
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :-------------- |
| Core | 6.3.1 | weak linked ATT |
## Core
* Weak linked AppTrackingTransparency framework.
# 17th December 2020
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :--------- |
| Core | 6.3.0 | Compliance |
## Core
* Enable/Disable SDK methods added to unblock/block all SDK features.
# 30th November 2020
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :-------------- |
| Core | 6.2.5 | sync background |
## Core
Fixes:
* Bugfix: One of the SDK background tasks while syncing the data was getting terminated prematurely.
# 24th November 2020
### Release Summary
| Module | Version | Update |
| :------------------- | :------ | :----------- |
| Cards | 6.2.4 | rename class |
## Cards
* Changes to support **MoEngageCards**\[Version: **1.1.0**] Module.
* **BUILD\_LIBRARY\_FOR\_DISTRIBUTION** enabled for **MOCards**.
* **MOCards** class renamed to **MoEngageCards**.
# 12th November 2020
### Release Summary
| Module | Version | Update |
| :------------------- | :------ | :---------- |
| Cards | 6.2.3 | module maps |
## Cards
* Fixes for including the simulator module maps for **MoEngageCards**\[Version: **1.0.2**] Module.
# 2nd November 2020
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :--------------------- |
| Core | 6.2.2 | Universal Links Safari |
## Core
Fixes:
* Bugfix: Universal Links was taking the user to Safari, instead of processing it inside the app.
* Xcode 12 Build settings changes to exclude arm64 architecture for Simulator.
# 6th September 2020
### Release Summary
| Module | Version | Update |
| :------------------ | :------------ | :------------- |
| Core | 6.2.0 / 6.2.1 | Push Templates |
## Core
* Support For **Push Templates** added \[Simple Image Carousel & Stylized Basic].
* Inbox support with the same app group id for multiple apps supported.
# 2nd July 2020
### Release Summary
| Module | Version | Update |
| :------------------- | :------ | :------------- |
| Cards | 6.1.0 | Campaign Added |
## Cards
* Support For **Cards Campaign** added.
Fixes:
* BugFix: InApp exit animation was not being applied correctly.
* Fixed an intermittent crash occurring in MONetworkUtils while determining the SDK Version.
# 18th May 2020
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :-------------- |
| Core | 6.0.3 | source tracking |
## Core
Fixes:
* BugFix: Universal Links were not considered for Source tracking in Analytics Module.
# 28th March 2020
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :----------- |
| Core | 6.0.2 | weak linking |
## Core
* Fixed an issue where weak linking of **MoEngageInApp** and **MOGeofence** was not working, which was causing an issue while submitting the build to AppStore.
# 18th March 2020
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :------------ |
| Core | 6.0.1 | India cluster |
## Core
* Support for India cluster.
# 21st February 2020
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :---------------- |
| Core | 6.0.0 | **Dropped iOS 8** |
## Core
* Removed support for iOS 8.
* SDK Rearchitected and split into 5 modules: **MoEngageCore**, **MOAnalytics**, **MOMessaging**, **MOInApp** and **MoEngage**(Umbrella).
* InApp Module revamped and integrated separately.
* Initialization Methods are deprecated.
* **MOPayloadBuilder** is deprecated, use **MOProperties** for tracking events.
* Added new methods to track date event and user attributes using ISO date string.
# 16th December 2019
### Release Summary
| Module | Version | Update |
| :------------------ | :------------ | :----------------- |
| Core | 5.2.7 / 5.2.6 | minor Optimization |
## Core
Fixes:
* BugFix: Universal Links were not considered for Source tracking in Analytics Module.
* Minor optimizations.
# 30th October 2019
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :------------ |
| Core | 5.2.5 | Gregorian fix |
## Core
* Changes in data tracking where the event time is tracked in the Gregorian calendar irrespective of user calendar settings.
# 23rd October 2019
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :---------------- |
| Core | 5.2.3 | persistence crash |
## Core
* Fixed a crash occurring while trying to persist tracked user attributes.
# 22nd October 2019
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :----------------------- |
| Core | 5.2.2 | session tracking enabled |
## Core
* Session and Source Tracking Enabled by default in SDK.
# 14th October 2019
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :--------------------- |
| Core | 5.2.0 | termination expiry fix |
## Core
Fixes:
* Bugfix: Session expiry check was failing whenever the app was opened from terminated state.
* Bugfix: Notification Clicks were not processed from terminated state (fix for versions 5.0.0 to 5.1.0).
# 1st October 2019
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :--------------- |
| Core | 5.1.0 | start format fix |
## Core
Fixes:
* Bugfix: Session start time was tracked in an incorrect format.
# 4th September 2019
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :-------------- |
| Core | 5.0.3 | swizzling check |
## Core
* Added a main thread check for AppDelegate Swizzling and launch option processing.
# 30th August 2019
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :--------------- |
| Core | 5.0.2 | InApp Screen fix |
## Core
Fixes:
* BugFix: InApp Show Only in Screen was failing, it is fixed.
# 8th August 2019
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :----------------- |
| Core | 5.0.1 | GMT timezone track |
## Core
* Session start time is tracked in the GMT timezone instead of the device time zone.
# 26th July 2019
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :------------------ |
| Core | 5.0.0 | **Swizzling proxy** |
## Core
* Session and Source tracking is possible in the SDK.
* **AppDelegate Swizzling** implemented. Can be disabled via **MoEngageAppDelegateProxyEnabled** in **Info.plist**.
* Removed support for previously deprecated methods.
# 4th January 2019
### Release Summary
| Module | Version | Update |
| :------------------- | :------ | :----------------- |
| Inbox | 4.4.0 | sync secure revamp |
## Inbox
* Inbox module revamp.
* Notifications synced from Notification Service Extension using **MORichNotification**(version 3.0.0).
* Internal changes for secure SDK API calls.
# 10th October 2018
### Release Summary
| Module | Version | Update |
| :---------------------- | :------ | :--------- |
| Geofence | 4.3.0 | separation |
## Geofence
* Geofence Module separated from Core SDK.
# 4th October 2018
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :------------------ |
| Core | 4.2.4 | Universal Links fix |
## Core
Fixes:
* Bug Fix: Universal links when sent as deep links were not working.
# 13th August 2018
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :------------------ |
| Core | 4.2.3 | Offline RTT Payload |
## Core
Fixes:
* Real-time trigger bugfix for wrong payload in offline scenario for personalization.
# 26th July 2018
### Release Summary
| Module | Version | Update |
| :------------------- | :------ | :--------------- |
| Inbox | 4.2.2 | Payload Delegate |
## Inbox
* Delegate method **inboxCellSelectedWithPushDict:** provided for Push Notification Payload on clicking inbox notification.
* Added **shouldProcessNotificationActions** to MOInboxViewController.
# 24th May 2018
### Release Summary
| Module | Version | Update |
| :------- | :------ | :-------------- |
| **GDPR** | 4.1.0 | opt-out methods |
## GDPR
* SDK changes to make it GDPR compliant.
* Provided opt-out methods for tracking, push, and in-app.
* Added **resetUserWithCompletionBlock:** and **flushWithCompletionBlock:**.
# 23rd April 2018
### Release Summary
| Module | Version | Update |
| :---------------- | :------ | :--------------- |
| Dynamic framework | 4.0.0 | RTT introduction |
## Dynamic framework
* SDK converted from static library to **dynamic framework**.
* Implementation of Real-Time Triggers.
# 14th March 2018
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :------------------ |
| Core | 3.9.2 | dismiss richlanding |
## Core
Fixes:
* Issue fixed where SDK crashed due to calling sync in multiple threads.
* Added **dismissRichLandingWebViewControllerWithAnimation:**.
# 23rd February 2018
### Release Summary
| Module | Version | Update |
| :------------------- | :------ | :------------- |
| InApp | 3.9.1 | black tint fix |
## InApp
Fixes:
* Bugfix: Black tint view added on screen in case of Self Handled Smart Trigger InApp.
# 1st February 2018
### Release Summary
| Module | Version | Update |
| :------------ | :------ | :----------------- |
| rating action | 3.9.0 | Device Model track |
## Core
* Conditional Action supported in inApp for rating template.
* Periodic Flush of events introduced.
* Tracking of Device Model implemented.
# 26th December 2017
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :-------------- |
| Core | 3.8.1 | reset crash fix |
## Core
Fixes:
* Fixed issue where calling **resetUser** simultaneously with **syncNow** caused a crash.
# 22nd November 2017
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :----------- |
| Core | 3.8.0 | Alias method |
## Core
* Provided **setAlias:** method to update UNIQUE\_ID.
* **setUserUniqueID:** now resets current user if a new value is provided.
# 13th November 2017
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :------------- |
| Core | 3.7.3 | EU redirection |
## Core
* Provided **redirectDataToRegion:** for EU servers.
# 2nd November 2017
### Release Summary
| Module | Version | Update |
| :------------------- | :------ | :------------- |
| Inbox | 3.7.2 | click tracking |
## Inbox
* Provided method to track inbox notification clicks.
* Removed Show Only In Screen check for Test InApp.
# 1st November 2017
### Release Summary
| Module | Version | Update |
| :------------------- | :------ | :------------ |
| Inbox | 3.7.1 | mark read API |
## Inbox
* Provided methods to mark an inbox notification as read.
* Added additional debug logs for InApp.
# 27th September 2017
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :------------------- |
| Core | 3.7.0 | blacklisting Support |
## Core
* SDK supports blacklisting of events to be tracked in the app.
# 6th September 2017
### Release Summary
| Module | Version | Update |
| :------------------- | :------ | :------------------ |
| Inbox | 3.6.0 | notification expiry |
## Inbox
* Inbox notifications have an expiry value (default 30 days).
* Locale tracking is no longer default; use **trackLocale** method.
# 17th August 2017
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :------------------- |
| Core | 3.5.0 | deep-link foreground |
## Core
Fixes:
* Fixed Locale tracking issue in iOS9 and below.
* Fixed delay in processing deep-linking when push clicked in foreground.
# 12th July 2017
### Release Summary
| Module | Version | Update |
| :------------------- | :------ | :------------- |
| Inbox | 3.4.1 | remove All API |
## Inbox
* **removeInboxMessages** method provided to delete all messages.
Fixes:
* Fixed a crash that occurred while showing self-handled inApp.
# 1st June 2017
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :------------------ |
| Core | 3.4.0 | device Locale track |
## Core
* Device Locale tracked through SDK.
Fixes:
* Fixed bug where self-handled inApp data wasn't passed in test pushes.
* Additional parameters for self-handled inApp: expiry, max times, autoDismiss, persistent.
# 17th February 2017
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :----------------- |
| Core | 3.3.0 | internal lifecycle |
## Core
Breaking Change:
* App Lifecycle methods deprecated; handled internally now.
* Syncing optimization for tracked events.
* Separate methods for default User Attributes (EmailID, User Name, etc).
# 9th January 2017
### Release Summary
| Module | Version | Update |
| :------------------- | :------ | :------------------- |
| InApp | 3.2.2 | storyboard discovery |
## InApp
Fixes:
* Fixed bug locating MOInbox.storyboard as framework.
* InApp permission/settings handling efficiency.
# 24th November 2016
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :------------------ |
| Core | 3.2.0 | push delivery track |
## Core
* Enabled tracking of push delivery via Notification Extension and AppGroups.
* Enabled Test InApp foreground receipt.
* Media-attachment support for iOS Rich Notifications in Inbox.
# 24th October 2016
### Release Summary
| Module | Version | Update |
| :------------------- | :------ | :----------- |
| InApp | 3.1.0 | Keyboard fix |
## InApp
Fixes:
* Fixed bug where InApp was shown over the keyboard.
* Improved logging mechanism.
# 4th October 2016
### Release Summary
| Module | Version | Update |
| :-------------------- | :------ | :------------- |
| **UserNotifications** | 3.0.0 | iOS 10 Support |
## Core
* Using **UserNotifications** framework for iOS 10.
* Changes for supporting Notification Actions in iOS 10.
* **MORichNotifications** added to handle rich notifications in extensions.
# 5th September 2016
### Release Summary
| Module | Version | Update |
| :------------ | :------ | :------------- |
| nudge support | 2.4.0 | exception logs |
## Core
* Supporting Nudges for testing InApps.
* Inbox module supports dictionary alerts.
Fixes:
* Bugfix: InApp can be shown along with Nudges.
* Handle Rich Landing from push fixes.
# 18th August 2016
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :--------------- |
| Core | 2.3.2 | SFSafari support |
## Core
* RichLanding content shown in **SFSafariViewController** (iOS 9+).
* Tracking change in Push Preference status event.
* Unity iOS Support included.
# 30th June 2016
### Release Summary
| Module | Version | Update |
| :------------------- | :------ | :---------------- |
| InApp | 2.3.1 | campaign ID track |
## InApp
Fixes:
* Bug Fix to track campaign ID with events tracked in InApps.
# 10th June 2016
### Release Summary
| Module | Version | Update |
| :------------- | :------ | :------------ |
| ID Unification | 2.3.0 | DEBUG/RELEASE |
## Core
* Unified App for both testing and production.
* Separate methods for SDK initialization to differentiate test (DEBUG) vs production (RELEASE) devices.
# 18th May 2016
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :--------------- |
| Core | 2.2.2 | deep linking fix |
## Core
Fixes:
* Bugfix for deep linking.
# 16th May 2016
### Release Summary
| Module | Version | Update |
| :----------------- | :------ | :----------- |
| Actionable buttons | 2.2.0 | Custom Sound |
## Core
* Notification Categories for action buttons.
* SDK handles Deeplinking, Coupon Code, and Rich landing by default.
* Support for custom notification sounds.
# 30th March 2016
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :---------- |
| Core | 2.1.0 | minor fixes |
## Core
* Minor bug fixes.
# 14th March 2016
### Release Summary
| Module | Version | Update |
| :--------------- | :------ | :----------- |
| **in-app Nativ** | 2.0.0 | Self Handled |
## Core
* Introduced **in-app Nativ**.
* Old callbacks removed; new callback structure introduced.
* Self Handled in-apps support.
# 7th March 2016
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :------------- |
| Core | 1.9.5 | IDFV nil check |
## Core
* Handled rare cases where IDFV can be nil if device is restarted and not unlocked.
# 29th February 2016
### Release Summary
| Module | Version | Update |
| :---------------------- | :------ | :------------- |
| Geofence | 1.9.4 | iOS 7 matching |
## Geofence
Fixes:
* iOS 7 crash while string match for Geofence.
* Attributes set to nil are now discarded with a log.
* Deprecated **setLocationwithLat:lng:**.
# 29th January 2016
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :--------------- |
| Core | 1.9.3 | Sync failure fix |
## Core
Fixes:
* Bugfix for events lost if sync fails.
* Inbox Storyboard fix for Xcode version types.
# 13th January 2016
### Release Summary
| Module | Version | Update |
| :----- | :------ | :-------------- |
| Nudges | 1.9.2 | Screen specific |
## Core
* Support specific screen nudges using **getNudgeViewForScreen**.
# 6th January 2016
### Release Summary
| Module | Version | Update |
| :----- | :------ | :----------- |
| Inbox | 1.9.1 | swipe delete |
## Inbox
* Ability to delete Inbox messages by swiping.
Fixes:
* Fixed bug where some Inbox messages appeared blank.
# 22nd December 2015
### Release Summary
| Module | Version | Update |
| :--------- | :------ | :------------- |
| log levels | 1.9.0 | active receipt |
## Core
* Control logs via **\[MoEngage debug:YES/NO]**.
* New event for notification receipt when app is active.
* Events during **resetUser** are now preserved and attributed to new user.
# 16th November 2015
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :------------- |
| Core | 1.8.5 | IDFA colección |
## Core
* Ad Support Framework is weakly linked. IDFA collected only if framework is present.
# 28th October 2015
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :---------------- |
| Core | 1.8.4 | compiler warnings |
## Core
Fixes:
* Warnings from **CLANG\_ENABLE\_MODULES** and **GCC\_PRECOMPILE\_PREFIX\_HEADER** fixed.
# 22nd October 2015
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :--------------- |
| Core | 1.8.3 | duplicate symbol |
## Core
Fixes:
* Duplicate symbols fix.
* NSLogs restricted to simulators.
* PushTime Swift compatibility fix.
# 13th October 2015
### Release Summary
| Module | Version | Update |
| :------ | :------------ | :---------------- |
| builder | 1.8.1 / 1.8.2 | separate location |
## Core
* Send location and time attributes separately via **MOPayloadBuilder**.
# 28th September 2015
### Release Summary
| Module | Version | Update |
| :------- | :------ | :------------------ |
| Main SDK | 1.8 | **Bitcode Support** |
## Core
* Includes Bitcode support for iOS 9 and Xcode 7.
* Geofencing completion handler added to notify tracked regions.
Fixes:
* Data sync fix for terminate immediately after background.
# 19th August 2015
### Release Summary
| Module | Version | Update |
| :-------------- | :------ | :---------------- |
| Multiple nudges | 1.7 | open-source inbox |
## Core
* Multiple nudges supported (expire-and-show-next).
* Reinstall event tracking.
* Open-source Inbox/Notification center.
* New callback for **UserNotificationSettings** (iOS 8).
# 15th July 2015
### Release Summary
| Module | Version | Update |
| :----------------- | :------ | :------------- |
| **Geofence intro** | 1.6 | in-app caching |
## Core
* Geofencing is now supported.
* In-app images are now cached.
Fixes:
* Nudge View fix where action was not tracked.
# 30th June 2015
### Release Summary
| Module | Version | Update |
| :------------- | :------ | :----------- |
| Install update | 1.5 | app id reset |
## Core
* Install/Update differentiation.
* Reset user triggered on MoEngage APP ID change.
# 27th May 2015
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :------------- |
| Core | 1.4.3 | iOS 7 behavior |
## Core
Fixes:
* Fixed Apple recognization of **NSFoundationVersionNumber\_iOS\_7\_0** to fix iOS 6 behavior on iOS 7.
# 18th May 2015
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :------------ |
| Core | 1.4.2 | badge disable |
## Core
* iOS 6 support for tracking and pushes only.
* Property to disable badge number control.
# 8th May 2015
### Release Summary
| Module | Version | Update |
| :------------------ | :------ | :----------- |
| Core | 1.4.1 | iPad support |
## Core
* iPad support for in-apps, landscape, and portrait.
* The ability to call initialize later in the lifecycle of the app.
Fixes:
* Json parsing handled for incompatible types like NSData, NSUrl etc.
* iOS6 crash handled if initialize call was skipped.
# 16th April 2015
### Release Summary
| Module | Version | Update |
| :------- | :------ | :--------------- |
| Main SDK | 1.4 | **Nudges intro** |
## Core
What's New:
* New Feature: **Nudges**.
* Reset User functionality for account switching/logouts.
* Improvements in data storage if sync fails.
# 2024
Source: https://moengage.com/docs/developer-guide/release-notes/ios-sdk/2024
View the 2024 release notes and changelogs for the MoEngage iOS Native SDK.
**Information**
You can now get notified whenever MoEngage releases a new version of the iOS Native SDK. For more information, refer to [Subscribe to MoEngage SDK Releases](/developer-guide/release-notes/subscribe-to-moengage-sdk-releases/subscribe-to-mo-engage-sdk-releases).
■ Updated: Module version has been updated in this release.
■ Unchanged: Module remains on the previous version.
~~■ Deprecated:~~ Module is deprecated and will be removed in a future release.
| swift = 5.0.0 iOS = 11.0 tvOS = 11.0 |
## Core
Fixes:\
Removed debug symbols from frameworks (introduced in 9.18.0).
# 26th September 2024
### Release Summary
| SDK Version | Modules | Dependencies |
| :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :--------------------------------------------- |
| 9.20.0 |
Core
Messaging
InApp
Cards
Inbox
Geofence
RichNotification
RealTimeTrigger
| swift = 5.0.0 iOS = 11.0 tvOS = 11.0 |
## Core
Fixes:
* Fixed integer in the following and timestamp/date based trigger conditions not working.
* Fixed the issue where Tablet device model is tracked as MOBILE.
* Send device time stamp and event time stamp in milliseconds.
## Messaging
Fixes:\
Available macro check failing fix.
## InApp
What's New:\
Added JSON Object support in campaign trigger condition evaluator.
Fixes:
* Video Nudge in unmute state when initially shown fix.
* Pointer Nullability type specifier warning fix.
# 5th September 2024
### Release Summary
| SDK Version | Modules | Dependencies |
| :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------- |
| 9.19.0 |
Core
Inbox
Cards
InApp
RichNotification
Device Triggered
Geofence
Messaging
RealTimeTrigger
| swift = 5.0.0 iOS = 11.0 tvOS = 11.0 |
## Core
Known Issues:\
Push opt-in device attribute tracked as false if banners notification settings is disabled.
What's New:\
Added support for provisional push.
Improvements:
* Expose app install/update API without appId input.
* Internal improvements.
* Added push opt-in device attribute and events tracking and navigate to settings page API.
Fixes:
* Fixed previous instance deinitialization when default instance changed.
* Fixed in-memory data not getting cleared on disable data tracking.
* Fixed Source tracking happening before flush.
* Fixed Device type not getting tracked after data tracking re-enabled from disabled.
* Fixed Analytics batch data migration from 8.7.0.
* Fixed User getting reset while on disabled state.
* Fixed No data tracked post tracking restricted unique id.
* Fixed No data tracked post tracking invalid timestamp or location.
* Fixed force logout happening for logged in user when invalid unique id passed.
## Inbox
Improvements:\
Internal improvements.
## Cards
What's New:\
Added Cards fetch on login support.
Improvements:\
Internal improvements.
## InApp
What's New:\
Multiple self handled inApp support.
Improvements:
* Internal improvements.
* Self handled in-App callback improvements to immediate call back in case of failures.
Fixes:
* inApp background image cropping issue in native inApps.
* Added showing push opt-in only if push permission not provided.
## RichNotification, Device Triggered, Geofence
Improvements:\
Internal improvements.
# 1st August 2024
### Release Summary
| SDK Version | Modules | Dependencies |
| :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------- |
| 9.18.1 |
| swift = 5.0.0 iOS = 11.0 tvOS = 11.0 |
## Core
Improvements:\
Internal improvements.
Breaking Changes:\
Deprecated SDK provided SSL Pinning in favour of OS provided one.
## Geofence
Fixes:\
Geofence API will be blocked, if data tracking is opted out.
# 12th June 2024
### Release Summary
| SDK Version | Modules | Dependencies |
| :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------- |
| 9.17.5 |
Core
InApps
Cards
Geofence
RichNotification
Inbox
RealTimeTrigger
Messaging
| swift = 5.0.0 iOS = 11.0 tvOS = 11.0 |
## Core
What's New:
* Added JSON object support to user attributes.
* Handled environment updates with the same installation.
Fixes:
* Fixed crash by handling data race when the application comes to foreground.
* Notification impression not tracked after app update.
* Fixed tracked object attribute duplication.
* Reset user completion handler not invoked.
## InApp, Cards, Geofence, RichNotification, Inbox, RealTimeTrigger
What's New:\
Handled environment updates with the same installation.
Fixes (InApp):\
InApp touch navigates to parent controller.
# 21st May 2024
### Release Summary
| SDK Version | Modules | Dependencies |
| :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :--------------------------------------------- |
| 9.17.4 |
Core
InApp
Geofence
Messaging
Cards
Inbox
RichNotification
RealTimeTrigger
| swift = 5.0.0 iOS = 11.0 tvOS = 11.0 |
## Core
What's New:\
Adding support of Array in triggered-based InApps.
Fixes:\
Fixed geofence enabled migration with encryption.
## InApp
Fixes:\
Fixed SwiftUI reference crash on iOS 12.
## Geofence
Fixes:
* Fixed the API issue that caused geofence campaigns to not be displayed.
* Fixed hang caused with CLLocationManger.
# 16th May 2024
### Release Summary
| SDK Version | Modules | Dependencies |
| :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------- |
| 9.17.3 |
Core
InApps
Messaging
Cards
Inbox
Geofence
RichNotification
RealTimeTrigger
| swift = 5.0.0 iOS = 11.0 tvOS = 11.0 |
## Core
What's New:\
Added DC-06 support.
Fixes:
* Fixed where notification received event was tracked when SDK was disabled.
* Fixed push token migration from 7.x version.
# 2nd May 2024
### Release Summary
| SDK Version | Modules | Dependencies |
| :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :--------------------------------------------- |
| 9.17.2 |
Core
InApp
Inbox
Messaging
Cards
Geofence
RichNotification
RealTimeTrigger
| swift = 5.0.0 iOS = 11.0 tvOS = 11.0 |
## Core
Fixes:
* Fixed migration crash from 8.2.0 to 9.17.0.
* Fixed the issue where push token was not being sent in API call when app group id is missing.
* Fixed the issue where API call is made when SDK is disabled.
* Fixed the issue where ReInstall was not getting tracked.
## InApp
Fixes:\
Fixed non-Intrusive InApp breaking with tabbar.
## Inbox
Improvements:\
Internal Optimization to handle the inbox storage.
# 18th April 2024
### Release Summary
| SDK Version | Modules | Dependencies |
| :---------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------- |
| 9.17.1 |
Core
InApp
Messaging
Cards
Inbox
Geofence
RichNotification
RealTimeTrigger
| swift = 5.0.0 iOS = 11.0 tvOS = 11.0 |
## Core
What's New:\
Added support to provide optional deep link callback to MoEngageInAppNativeDelegate protocol via MoEngageInAppConfig.
## InApp
What's New:\
Added support to provide optional deep link callback to MoEngageInAppNativeDelegate protocol via MoEngageInAppConfig.
Fixes:\
Fixed type name collision.
Breaking Changes:\
MoEngageInAppNativeDelegate protocol where MoEngageInAppAction is replaced with MoEngageInAppNavigationAction.
| Then | Now |
| :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `func inAppClicked(withCampaignInfo inappCampaign: MoEngageInAppCampaign, andNavigationActionInfo navigationAction: MoEngageInAppAction, forAccountMeta accountMeta: MoEngageAccountMeta)` | `func inAppClicked(withCampaignInfo inappCampaign: MoEngageInAppCampaign, andNavigationActionInfo navigationAction: MoEngageInAppNavigationAction, forAccountMeta accountMeta: MoEngageAccountMeta)` |
*`navigationAction.screenName` is dropped from MoEngageInAppAction. Instead Use `navigationAction.navigationUrl` of MoEngageInAppNavigationAction.*
# 8th April 2024
### Release Summary
| SDK Version | Modules | Dependencies |
| :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :--------------------------------------------- |
| 9.17.0 |
Core
InApp
Cards
Geofence
RichNotification
Inbox
RealTimeTrigger
Messaging
| swift = 5.0.0 iOS = 11.0 tvOS = 11.0 |
## Core
What's New:\
Added Intrusive InApp support for tvOS.
Improvements:\
Internal improvements.
## InApp
What's New:\
Added support for Non-Intrusive InApps.
Fixes:\
Fixed type name collision.
## Cards, Geofence, RichNotification, Inbox, RealTimeTrigger
Improvements:\
Internal improvements.
# 21st March 2024
### Release Summary
| SDK Version | Modules | Dependencies |
| :---------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------- |
| 9.16.2 |
Core
Inbox
InApps
Messaging
Cards
Geofence
RichNotification
RealTimeTrigger
| swift = 5.0.0 iOS = 11.0 tvOS = 11.0 |
## Core & Inbox
Fixes:\
Fixed app rejection issue due to privacy manifest.
# 18th March 2024
### Release Summary
| SDK Version | Modules | Dependencies |
| :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :--------------------------------------------- |
| 9.16.1 |
Core
InApp
Cards
Messaging
Inbox
Geofence
RichNotification
RealTimeTrigger
| swift = 5.0.0 iOS = 11.0 tvOS = 11.0 |
## Core
What's New:
* Added AND support in inApp trigger-campaign evaluation.
* Provided callback when force logout is completed.
* Added tvOS platform identifier changes.
* Removed linking to AdSupport by default. AdSupport and AppTrackingTransparency needs to be linked by app target for IDFA tracking.
Fixes:
* Fixed the issue where session start was not tracked in some cases.
* Fixed crash in network session delegate.
## InApp
What's New:
* Dismiss inApp on context change.
* Added tvOS platform identifier changes.
* Added AND support in inApp trigger-campaign evaluation.
## Cards
What's New:\
Added tvOS platform identifier changes.
# 7th March 2024
### Release Summary
| SDK Version | Modules | Dependencies |
| :------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :--------------------------------------------- |
| 9.16.1 (InApp) |
| swift = 5.0.0 iOS = 11.0 tvOS = 11.0 |
## Core
Fixes:
* Fixed crash in decryption.
* Fixed the extra new line rendering in notification.
## RichNotification
Fixes:\
Fixed the extra new line rendering.
# 23rd January 2024
### Release Summary
| SDK Version | Modules | Dependencies |
| :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :--------------------------------------------- |
| 9.15.0 |
Core
InApp
Cards
Geofence
RichNotification
Inbox
RealTimeTrigger
Messaging
| swift = 5.0.0 iOS = 11.0 tvOS = 11.0 |
## All Modules
What's New:
* Added Privacy manifest file for XCFramework.
* Added Code signature support for XCFramework.
## Cards
Fixes:\
Fixed memory leak with Cards screen.
# 2025
Source: https://moengage.com/docs/developer-guide/release-notes/ios-sdk/2025
View the 2025 release notes and changelogs for the MoEngage iOS Native SDK.
**Information**
You can now get notified whenever MoEngage releases a new version of the iOS Native SDK. For more information, refer to [Subscribe to MoEngage SDK Releases](/developer-guide/release-notes/subscribe-to-moengage-sdk-releases/subscribe-to-mo-engage-sdk-releases).
■ Updated: Module version has been updated in this release.
■ Unchanged: Module remains on the previous version.
~~■ Deprecated:~~ Module is deprecated and will be removed in a future release.
| swift = 5.0.0 iOS = 13.0 tvOS = 13.0 |
## InApps
Fixes:\
Fixed Inapp condition evaluator thread hang/crash.
## Messaging
Fixes:
* Added completion callback to `logNotificationReceived`. Deprecated older API without completion.
* Improve push notification received impression tracking performance.
## Cards
Fixes:\
Fixed Cards future qualifier with UID and MultiID on stats API.
# 21st August 2025
### Release Summary
| SDK Version | Modules | Dependencies |
| :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------- |
| 10.04.1 |
InApps
Messaging
Cards
Core
Inbox
Geofence
RichNotification
RealTimeTrigger
| swift = 5.0.0 iOS = 13.0 tvOS = 13.0 |
## InApps
Fixes:
* Fixed nullability specifier warnings/errors in ObjC files.
* Fixed the universal deeplink callback to SceneDelegate.
## Messaging
Fixes:\
Fixed the universal deeplink callback to SceneDelegate.
## Cards
Fixes:\
Fixed the universal deeplink callback to SceneDelegate.
# 05th August 2025
### Release Summary
| SDK Version | Modules | Dependencies |
| :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------- |
| 10.04.0 |
InApps
Core
Messaging
Cards
Inbox
Geofence
RichNotification
RealTimeTrigger
| swift = 5.0.0 iOS = 13.0 tvOS = 13.0 |
## InApps
What's New:
* Non-Intrusive HTML Nudges Support.
* New Test InApp Experience support.
# 25th July 2025
### Release Summary
| SDK Version | Modules | Dependencies |
| :---------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------- |
| 10.03.2 |
Core
InApps
Messaging
Cards
Inbox
Geofence
RichNotification
RealTimeTrigger
| swift = 5.0.0 iOS = 13.0 tvOS = 13.0 |
## Core
Fixes:\
Fixed an issue with impression tracking when signature validation is enabled on server.
## InApps
Fixes:
* Added accessibility support for gifs & images to remain visible in InApps nudges.
* Fixed the random crash in InApps on removing context.
# 16th July 2025
### Release Summary
| SDK Version | Modules | Dependencies |
| :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------- |
| 10.03.1 |
Core
Messaging
InApps
Cards
Inbox
Geofence
RichNotification
RealTimeTrigger
| swift = 5.0.0 iOS = 13.0 tvOS = 13.0 |
## Core
Fixes:\
Updated Xcode version to fix typed throws API not being added to swift module interface.
# 15th July 2025
### Release Summary
| SDK Version | Modules | Dependencies |
| :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------- |
| 10.03.0 |
Core
Messaging
InApps
Cards
Inbox
Geofence
RichNotification
RealTimeTrigger
| swift = 5.0.0 iOS = 13.0 tvOS = 13.0 |
## Core
What's New:\
Added support for initializing default SDK instance with configuration data in Application's Info.plist.
# 8th July 2025
### Release Summary
| SDK Version | Modules | Dependencies |
| :---------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------- |
| 10.02.3 |
Core
Cards
Messaging
InApps
Inbox
Geofence
RichNotification
RealTimeTrigger
| swift = 5.0.0 iOS = 13.0 tvOS = 13.0 |
## Core
Fixes:
* Order of Event tracking for Offering Clicked updated.
* Fixed data tracked immediately after logout being lost.
## Cards
Fixes:\
Added missing accessibility data inside metadata dictionary of cards for hybrid platforms.
# 27th June 2025
### Release Summary
| SDK Version | Modules | Dependencies |
| :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------- |
| 10.02.2 |
Core
Messaging
InApps
Cards
Inbox
Geofence
RichNotification
RealTimeTrigger
| swift = 5.0.0 iOS = 13.0 tvOS = 13.0 |
## Core
What's New:\
APIs for tracking clicks and impressions for offerings in personalization.
# 26th June 2025
### Release Summary
| SDK Version | Modules | Dependencies |
| :---------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------- |
| 10.02.1 |
Messaging
Cards
LiveActivity
Core
InApps
Inbox
Geofence
RichNotification
RealTimeTrigger
| swift = 5.0.0 iOS = 13.0 tvOS = 13.0 |
## Messaging
Fixes:\
Fixed Notification click Impressions not getting tracked with proxy enabled/disabled in scenarios when application launched from killed state with delayed initialization.
## Cards
What's New:\
Added Accessibility support for card campaigns.
## LiveActivity
What's New:\
[Added managing and tracking Live activities](https://help.moengage.com/hc/en-us/articles/37935320405012-Broadcast-Live-Activities-for-iOS-Push-Campaigns#h_01JWT5NFH9RQQTTN5B50QY2M2B)
# 16th June 2025
### Release Summary
| SDK Version | Modules | Dependencies |
| :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------- |
| 10.01.0 |
Core
Messaging
Inbox
InApps
RealTimeTrigger
Cards
Geofence
RichNotification
| swift = 5.0.0 iOS = 13.0 tvOS = 13.0 |
## Core
What's New:\
Added APIs for tracking personalization clicks and impressions.
## Messaging
What's New:\
Added Accessibility support for push campaigns.
Fixes:\
Fixed provisional opt-in device attribute not getting tracked after 24 hours.
## Inbox
What's New:\
Added Accessibility support for push campaigns.
## InApps
What's New:\
Added Accessibility support for InApp campaigns.
Fixes:\
Fixed issue where the app crashed if ***rootViewController*** was nil during an in-app campaign display.
Known Issues:
* The GIF nudge template cannot be resized when accessibility features are enabled.
* Additional border space is displayed in the maximize state for resizable nudge.
## RealTimeTrigger
What's New:\
Added Accessibility support for RTT push campaigns.
# 27th May 2025
### Release Summary
| SDK Version | Modules | Dependencies |
| :---------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------- |
| 10.00.0 |
Core
Inbox
InApps
RealTimeTrigger
Messaging
Cards
Geofence
RichNotification
| swift = 5.0.0 iOS = 13.0 tvOS = 13.0 |
## BREAKING CHANGES
Breaking Changes:
* Updated iOS and tvOS deployment target to 13.
* Removed support for Intel based simulators.
## Core
Breaking Changes:\
Removed deprecated APIs:
| Then | Now |
| :---------------------------------------------------- | :----------------------------------- |
| MoEngageSDKConfig(withAppID:) | MoEngageSDKConfig(appId:dataCenter:) |
| MoEngageSDKConfig.networkConfig.sslVerificationConfig | NA |
## Inbox
What's New:\
Added support for notification grouping, replacement & event tracking.
Fixes:\
Fixed the ***MoEngageInboxEntry.collapseId*** being set to empty instead of nil when the value is not present in payload (introduced in 9.24.0).
## InApps
What's New:\
Added Kotlin Multi-Platform based event trigger condition evaluator.
Fixes:\
Fixed persistent data migration failing from 7.x.x and 8.x.x to latest version.
## RealTimeTrigger
What's New:\
Added Kotlin Multi-Platform based event trigger condition evaluator.
# 29th April 2025
### Release Summary
| SDK Version | Modules | Dependencies |
| :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------- |
| 9.24.0 |
Messaging
Inbox
InApps
Core
Cards
Geofence
RichNotification
RealTimeTrigger
| swift = 5.0.0 iOS = 11.0 tvOS = 11.0 |
## Messaging
Fixes:
* Fixed Rich landing action for push notification when opened from inbox in killed state.
* Fixed push notification tracking in application killed state.
## Inbox
What's New:\
Added support for notification grouping, replacement & event tracking.
## InApps
What's New:\
Added support for Session Triggered InApps.
# 15th April 2025
### Release Summary
| SDK Version | Modules | Dependencies |
| :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------- |
| 9.23.4 |
Messaging
Core
InApps
Cards
Inbox
Geofence
RichNotification
RealTimeTrigger
| swift = 5.0.0 iOS = 11.0 tvOS = 11.0 |
## Messaging
Fixes:\
Fixed push opt-in tracked as false if banners notification settings is disabled (introduced in 9.19.0).
# 14th April 2025
### Release Summary
| SDK Version | Modules | Dependencies |
| :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------- |
| 9.23.3 |
Messaging
Core
InApps
Cards
Inbox
Geofence
RichNotification
RealTimeTrigger
| swift = 5.0.0 iOS = 11.0 tvOS = 11.0 |
## Messaging
Fixes:\
Notification Click not getting tracked when app launched from Killed state by clicking notification fix.
# 26th March 2025
### Release Summary
| SDK Version | Modules | Dependencies |
| :---------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------- |
| 9.23.2 |
Cards
Messaging
Core
InApps
Inbox
Geofence
RichNotification
RealTimeTrigger
| swift = 5.0.0 iOS = 11.0 tvOS = 11.0 |
## Cards
Fixes:\
Fixed Pinned card being returned as first element in `fetchCards` API.
## Messaging
Fixes:\
Fixed no navigation on Inbox messages click.
# 19th March 2025
### Release Summary
| SDK Version | Modules | Dependencies |
| :---------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------- |
| 9.23.1 |
Geofence
Device Triggered
Core
InApps
Cards
Inbox
Messaging
RichNotification
RealTimeTrigger
| swift = 5.0.0 iOS = 11.0 tvOS = 11.0 |
## Geofence
Fixes:\
Symbol not found exception (introduced in 9.23.0).
## Device Triggered
Fixes:\
Symbol not found exception (introduced in 9.23.0).
# 11th March 2025
### Release Summary
| SDK Version | Modules | Dependencies |
| :---------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------- |
| 9.23.0 |
Core
Cards
InApps
Inbox
Messaging
Geofence
Device Triggered
RichNotification
RealTimeTrigger
| swift = 5.0.0 iOS = 11.0 tvOS = 11.0 |
## Core
What's New:
* Added multiple identities support.
* Added integration validation exceptions.
## Cards
What's New:\
Cards sync on user identity set or update.
## InApps
What's New:
* InApp sync on user identity set or update.
* Added Click analysis support in HTML.
Fixes:
* Self Handled Trigger Callback switched from Background Queue to MainQueue for TestInapp flow (introduced in 9.19.0).
* Removed unused data from older versions (introduced in 9.21.0).
## Inbox
Fixes:\
Fixed inbox expiry time migration (introduced in 9.21.0).
## Messaging
Fixes:\
Removed unused data from older versions (introduced in 9.21.0).
## Geofence
Known Issues:\
Symbol not found exception (introduced in 9.23.0).
## Device Triggered
Known Issues:\
Symbol not found exception (introduced in 9.23.0).
# 18th February 2025
### Release Summary
| SDK Version | Modules | Dependencies |
| :---------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------- |
| 9.22.2 |
Core
Cards
Messaging
InApps
Inbox
Geofence
RichNotification
RealTimeTrigger
| swift = 5.0.0 iOS = 11.0 tvOS = 11.0 |
## Core
What's New:\
Updated repo URL to [https://github.com/moengage/apple-sdk](https://github.com/moengage/apple-sdk) for faster SPM dependency fetching.
## Cards
Fixes:\
Fixed campaigns navigation data parsing (introduced in 9.21.0).
# 27th January 2025 (9.22.1)
### Release Summary
| SDK Version | Modules | Dependencies |
| :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------- |
| 9.22.1 |
| swift = 5.0.0 iOS = 11.0 tvOS = 11.0 |
## Core
What's New:
* Added APIs for mParticle integration.
* Added SDK feature adoption tracking.
Improvements:\
Internal Improvements.
Fixes:\
Fixed Config API log\_level parsing.
## Inbox
Improvements:\
Internal improvements.
## Cards
Improvements:\
Internal improvements.
Fixes:\
Fixed the issue of images getting trimmed in Illustration Cards.
## InApp
Improvements:\
Internal improvements.
Fixes:\
Fixed Bottom margin issue in Nudges.
## RichNotification
Improvements:\
Internal improvements.
Fixes:\
Fixed the random crash seen due to memory limit.
## Geofence
Improvements:\
Internal improvements.
# 2026
Source: https://moengage.com/docs/developer-guide/release-notes/ios-sdk/2026
View the 2026 release notes and changelogs for the MoEngage iOS Native SDK.
**Information**
You can now get notified whenever MoEngage releases a new version of the iOS Native SDK. For more information, refer to [Subscribe to MoEngage SDK Releases](/developer-guide/release-notes/subscribe-to-moengage-sdk-releases/subscribe-to-mo-engage-sdk-releases).
■ Updated: Module version has been updated in this release.
■ Unchanged: Module remains on the previous version.
~~■ Deprecated:~~ Module is deprecated and will be removed in a future release.
**Custom Proxy Domain**: Introduced support for Custom Proxy Domains to route SDK traffic through a customer-owned subdomain for bypassing ad blockers and private DNS services. For more information, refer [here](/developer-guide/ios-sdk/sdk-integration/advanced/Custom-Proxy-Domain-iOS).
Improvements:
Fixed handling of KMM errors for CocoaPods integration.
## InApp
What's New:
* **Segment Re-evaluation:** Introduced trigger-time segment re-evaluation to ensure In-App messages are only shown to currently eligible users.
* **Frequency Capping:** Introduced frequency capping to limit the number of campaigns displayed to users.
## LiveActivity
What's New:
**Transactional Live Activity:** Added support for Transactional Live Activities. For more information, refer [here](https://developers.moengage.com/hc/en-us/articles/45243063940244-Transactional-Live-Activity).
## Messaging
What's New:
**Notification Click Tracking:** Added the new API `logNotificationClicked` that can accurately track clicks and dismiss of notifications.
# Android Kit Changelog
Source: https://moengage.com/docs/developer-guide/release-notes/mparticle-integration/android-kit-changelog
View the changelog for the MoEngage mParticle Android kit integration.
# 29-01-2026
## 2.3.0
* MoEngage SDK Version updated to **14.06.00**,
[Release Notes](/developer-guide/release-notes/android-sdk/2026#4th-February-2026)
# 20-01-2026
## 2.2.1
* MoEngage SDK Version updated to **14.05.01**,
[Release Notes](/developer-guide/release-notes/android-sdk/2026#20th-January-2026)
# 19-01-2026
## 2.2.0
* MoEngage SDK Version updated to **14.05.00**,
[Release Notes](/developer-guide/release-notes/android-sdk/2026#19th-January-2026)
# 11-12-2025
## 2.1.2
* MoEngage SDK Version updated to **14.04.03**,
[Release Notes](/developer-guide/release-notes/android-sdk/2025#11th-December-2025)
# 18-11-2025
## 2.1.1
* MoEngage SDK Version updated to **14.04.01**,
[Release Notes](/developer-guide/release-notes/android-sdk/2025#18th-November-2025)
# 29-10-2025
## 2.1.0
* MoEngage SDK Version updated to **14.04.00**,
[Release Notes](/developer-guide/release-notes/android-sdk/2025#29th-October-2025)
#
25-09-2025
## 2.0.1
* MoEngage SDK Version updated to **14.03.05**,
[Release Notes](/developer-guide/release-notes/android-sdk/2025#25th-September-2025)
# 24-09-2025
## 2.0.0
* MoEngage SDK Version updated to **14.03.04**,
[Release Notes](/developer-guide/release-notes/android-sdk/2025#24th-September-2025)
* Target SDK Version updated to **35**
* Min SDK Version updated to **23**
* AGP Version updated to **8.7.3**
* Added support for Multi-User Identities
# 22-01-2025
## 1.1.0
* Making the ***moe-android-sdk*** artifact part of
the
kit
* MoEngage SDK Version updated to **13.05.02**,
[Release Notes](/developer-guide/release-notes/android-sdk/2025#22nd-January-2025)
# 30-12-2024
## 1.0.0
* Initial Support for Integrating MoEngage SDK with mParticle SDK using
Kit.
Check
[Integration Doc](https://partners.moengage.com/hc/en-us/articles/32442927570580-Android-Kit-Integration)
for more details.
# iOS Kit Changelog
Source: https://moengage.com/docs/developer-guide/release-notes/mparticle-integration/i-os-kit-changelog
View the changelog for the MoEngage mParticle iOS kit integration.
# 29-01-2026
## 2.3.0
* Updated MoEngage-iOS-SDK to 10.10.0
# 19-01-2026
## 2.2.0
* Updated MoEngage-iOS-SDK to 10.09.0
# 29-10-2025
## 2.1.0
* Updated MoEngage-iOS-SDK to 10.08.0
# 24-09-2025
## 2.0.0
## BREAKING CHANGES
* Updated iOS and tvOS deployment target to 13.
* Updated MoEngage-iOS-SDK to 10.07.0
### Whats New
* Added support for multiple user identifiers.
* Added Info.plist based initialization.
### Fixes
* Fixed latest version of `mParticle-Apple-SDK` not included in dependency
# 07-01-2025
## 1.0.0
* Initial Release which supports mParticle Swift API integrations. Check [Integration Doc](https://partners.moengage.com/hc/en-us/articles/32950769289108-iOS-Kit-Integration) for more details.
# Changelog
Source: https://moengage.com/docs/developer-guide/release-notes/react-native-sdk/changelog-5
View the changelog and release notes for the MoEngage React Native SDK plugins.
You can now get notified whenever MoEngage releases a new version of the React Native SDK. For more information, refer to [Subscribe to MoEngage SDK Releases](developer-guide/release-notes/subscribe-to-moengage-sdk-releases/subscribe-to-mo-engage-sdk-releases).
For privacy manifest support on iOS, please make sure that you are on React Native SDK Version 9.0.0 or above and iOS SDK Version 9.16.2 or above. Want to know more about privacy manifest ? Refer this [link](https://help.moengage.com/hc/en-us/articles/23893067070996-Apple-Privacy-Manifest-Update)
# 9th February 2026
| **Plugins** | **Dependencies** |
| ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| core: 12.5.0 cards: 6.2.0 geofence: 7.2.0 inbox: 6.2.0 | \* **Android** + AGP: 8.7.3 + Kotlin: 1.9.23 + Compile SDK Version: 35 + Gradle Version: 8.9 \* **iOS** + iOS deployment target: 13 + tvOS deployment target: 13 |
Core 12.5.0
### **What's New**
* Android
* Reduced integration steps for using FCM Push.
* Updated MoEngage BOM version ***1.5.1***
* iOS
* Added support for SDK initialization without Swift/Objective-C code.
* Updated MoEngage-iOS-SDK to ***10.10.0***
Cards 6.2.0
### **What's New**
* Android
* Updated MoEngage BOM version ***1.5.1***
* iOS
* Updated MoEngage-iOS-SDK to ***10.10.0***
Geofence 7.2.0
### **What's New**
* Android
* Updated MoEngage BOM version ***1.5.1***
* iOS
* Updated MoEngage-iOS-SDK to ***10.10.0***
Inbox 6.2.0
### **What's New**
* Android
* Updated MoEngage BOM version ***1.5.1***
* iOS
* Updated MoEngage-iOS-SDK to ***10.10.0***
# 19th November 2025
| **Plugins** | **Dependencies** |
| ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| core: 12.4.0 cards: 6.1.0 geofence: 7.1.0 inbox: 6.1.0 | \* **Android** + AGP: 8.7.3 + Kotlin: 1.9.23 + Compile SDK Version: 35 + Gradle Version: 8.9 \* **iOS** + iOS deployment target: 13 + tvOS deployment target: 13 |
Core 12.4.0
### **What's New**
* Android
* Moving the native dependencies to the bill-of-materials (BOM) for better version management.
* Initial supported MoEngage BOM version ***1.1.1***
* iOS
* Updated MoEngage-iOS-SDK to ***10.08.0***
Cards 6.1.0
### **What's New**
* Android
* Moving the native dependencies to the bill-of-materials (BOM) for better version management.
* Initial supported MoEngage BOM version ***1.1.1***
* iOS
* Updated MoEngage-iOS-SDK to ***10.08.0***
Geofence 7.1.0
### **What's New**
* Android
* Moving the native dependencies to the bill-of-materials (BOM) for better version management.
* Initial supported MoEngage BOM version ***1.1.1***
* iOS
* Updated MoEngage-iOS-SDK to ***10.08.0***
Inbox 6.1.0
### **What's New**
* Android
* Moving the native dependencies to the bill-of-materials (BOM) for better version management.
* Initial supported MoEngage BOM version ***1.1.1***
* iOS
* Updated MoEngage-iOS-SDK to ***10.08.0***
# 17th October 2025
| **Plugins** | **Dependencies** |
| ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| core: 12.3.0 cards: 6.0.5 geofence: 7.0.4 inbox: 6.0.4 | \* **Android** + AGP: 8.7.3 + Kotlin: 1.9.23 + Compile SDK Version: 35 + Gradle Version: 8.9 \* **iOS** + iOS deployment target: 13 + tvOS deployment target: 13 |
Core 12.3.0
### **What's New**
* iOS
* **MoEngage-iOS-SDK** version updated to ***10.07.2***
* Android
* ***moe-android-sdk*** version updated to ***14.03.05***
Cards 6.0.5
### **What's New**
* iOS
* **MoEngageCards** version updated to ***5.01.5***
* Android
* ***cards-core*** version updated to ***3.1.3***
Geofence 7.0.4
### **What's New**
* iOS
* **MoEngageGeofence** version updated to ***6.00.3***
* Android
* ***geofence*** version updated to ***5.0.3***
Inbox 6.0.4
### **What's New**
* iOS
* **MoEngageInbox** version updated to ***3.01.2***
* Android
* Internal improvements in inbox plugin base
# 11th September 2025
| **Plugins** | **Dependencies** |
| ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| core: 12.2.0 cards: 6.0.4 geofence: 7.0.3 inbox: 6.0.3 | \* **Android** + AGP: 8.7.3 + Kotlin: 1.9.23 + Compile SDK Version: 35 + Gradle Version: 8.9 \* **iOS** + iOS deployment target: 13 + tvOS deployment target: 13 |
Core 12.2.0
### **What's New**
* iOS
* **MoEngage-iOS-SDK** version updated to **10.05.0**
* Android
* ***moe-android-sdk*** version updated to ***14.03.03***
Cards 6.0.4
### **What's New**
* iOS
* **MoEngageCards** version updated to **5.01.4**
* Android
* ***cards-core*** version updated to ***3.1.2***
Geofence 7.0.3
### **What's New**
* iOS
* **MoEngageGeofence** version updated to **6.00.2**
* Android
* ***geofence*** version updated to ***5.0.1***
Inbox 6.0.3
### **What's New**
* iOS
* **MoEngageInbox** version updated to **3.01.1**
* Android
* ***inbox-core*** version updated to ***5.0.1***
# 6th August 2025
| **Plugins** | **Dependencies** |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| cards: 6.0.3 | \* **Android** + AGP: 8.7.3 + Kotlin: 1.9.23 + Compile SDK Version: 35 + Gradle Version: 8.9 \* **iOS** + iOS deployment target: 13 + tvOS deployment target: 13 |
Cards 6.0.3
### **Fixes**
* Android
* Card data is returned in the SDK disabled state.
# 29th July 2025
| **Plugins** | **Dependencies** |
| ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| core: 12.1.0 cards: 6.0.2 geofence: 7.0.2 inbox: 6.0.2 | \* **Android** + AGP: 8.7.3 + Kotlin: 1.9.23 + Compile SDK Version: 35 + Gradle Version: 8.9 \* **iOS** + iOS deployment target: 13 + tvOS deployment target: 13 |
Core 12.1.0
### **What's New**
* iOS
* **MoEngage-iOS-SDK** version updated to **10.03.2**
* **MoEngageInApps** version updated to **7.01.2**
### **Fixes**
* iOS
* Fixed an issue with impression tracking when signature validation is enabled on server
Cards 6.0.2
### **What's New**
* iOS
* ***MoEngagePluginCards*** version updated to ***3.3.2***
Geofence 7.0.2
### **What's New**
* iOS
* ***MoEngagePluginGeofence*** version updated to **4*.2.2*\*\*
Inbox 6.0.2
### **What's New**
* iOS
* ***MoEngagePluginInbox*** version updated to **4*.2.2*\*\*
# 16th July 2025
| **Plugins** | **Dependencies** |
| ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| core: 12.0.0 cards: 6.0.0 geofence: 7.0.0 inbox: 6.0.0 | \* **Android** + AGP: 8.7.3 + Kotlin: 1.9.23 + Compile SDK Version: 35 + Gradle Version: 8.9 \* **iOS** + iOS deployment target: 13 + tvOS deployment target: 13 |
Core 12.0.0
### **What's New**
* Added support for simplified InApp triggers
* Android
* Added support for XML based initialisation configuration
* ***moe-android-sdk*** version updated to ***14.03.00***
* ***inapp***version updated to ***9.2.0***
* iOS
* Added support for Info.plist based initialisation configuration
### **BREAKING CHANGES**
* Android
* Min SDK version updated to 23
* Compiled SDK version updated to 35
* Removed deprecated APIs
| **Then** | **Now** |
| --------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| MoEInitializer#initialize(Context, MoEngage.Builder) MoEInitializer#initialize(Context, MoEngage.Builder, SdkState) | MoEInitializer#initializeDefaultInstance(Context, MoEngage.Builder) MoEInitializer#initializeDefaultInstance(Context, MoEngage.Builder, SdkState) |
* iOS
* Minimum iOS and tvOS deployment target updated to 13
* MoEngage-iOS-SDK version updated to 10.03.1
Cards 6.0.1
### **What's New**
* Added Accessibility support in cards
* Android
* ***cards-core*** version updated to ***3.1.0***
### **BREAKING CHANGES**
* Android
* Min SDK Version updated to 23
* Compiled SDK Version updated to 35
* iOS
* Minimum iOS deployment target updated to 13
Geofence 7.0.1
### **BREAKING CHANGES**
* Android
* Min SDK Version updated to 23
* Compiled SDK Version updated to 35
* ***geofence*** version updated to ***5.0.1***
* iOS
* Minimum iOS deployment target updated to 13
Inbox 6.0.1
### **BREAKING CHANGES**
* Android
* Min SDK Version updated to 23
* Compiled SDK Version updated to 35
* ***inbox-core*** version updated to ***4.1.0***
* iOS
* Minimum iOS deployment target updated to 13
# 24th April 2025
| **Plugins** | **Android Dependencies** |
| ------------ | --------------------------------------------------------------------------- |
| core: 11.2.2 | AGP: 8.7.3 Kotlin: 1.9.23 Compile SDK Version: 34 Gradle Version: 8.9 |
Core 11.2.2
### **What's New**
* Android
* ***inapp***version updated to ***8.8.1***
#
# 16th April 2025
| **Plugins** | **Android Dependencies** |
| --------------------------------------------------------- | --------------------------------------------------------------------------- |
| core: 11.2.1 cards:5.1.1 geofence:6.1.1 inbox:5.1.1 | AGP: 8.7.3 Kotlin: 1.9.23 Compile SDK Version: 34 Gradle Version: 8.9 |
Core 11.2.1
### **What's New**
* iOS
* Added back Swift AppDelegate support
* ***MoEngage-iOS-SDK*** version updated to ***9.23.4***
Cards 5.1.1
### **What's New**
* iOS
* ***MoEngagePluginCards*** version updated to ***2.3.2***
Geofence 6.1.1
### **What's New**
* iOS
* ***MoEngagePluginGeofence*** version updated to ***3.3.2***
Inbox 5.1.1
### **What's New**
* iOS
* ***MoEngagePluginInbox*** version updated to ***3.3.2***
# 24th March 2025
| **Plugins** | **Android Dependencies** |
| --------------------------------------------------------- | --------------------------------------------------------------------------- |
| core: 11.2.0 cards:5.1.0 geofence:6.1.0 inbox:5.1.0 | AGP: 8.7.3 Kotlin: 1.9.23 Compile SDK Version: 34 Gradle Version: 8.9 |
Core 11.2.0
### **What's New**
* Added support for Multi-User Identities. Refer to the [developer docs](/developer-guide/android-sdk/data-tracking/basic/track-user-attributes#multiple-Identifiers) on how to migrate from existing APIs to the new APIs. Refer to the [user guide](https://help.moengage.com/hc/en-us/articles/24050999467284-User-Identity-Management) to learn more about the feature.
* Android
* Added support for AGP 8.7.3 and above
* ***moe-android-sdk*** version updated to ***13.06.00***
* ***inapp***version updated to ***8.8.0***
* iOS
* ***MoEngage-iOS-SDK*** version updated to ***9.23.1***
Cards 5.1.0
### **What's New**
* Android
* Added support for AGP 8.7.3 and above
* ***cards-core*** version updated to ***2.4.0***
Geofence 6.1.0
### **What's New**
* Android
* Added support for AGP 8.7.3 and above
* ***geofence*** version updated to ***4.3.0***
Inbox 5.1.0
### **What's New**
* Android
* Added support for AGP 8.7.3 and above
* ***inbox-core*** version updated to ***3.3.0***
# 11th March 2025
| **Plugins** | **Android Dependencies** |
| --------------------------------------------------------- | --------------------------------------------------------------------------- |
| core: 11.1.4 cards:5.0.3 geofence:6.0.4 inbox:5.0.4 | AGP: 8.4.0 Kotlin: 1.9.23 Compile SDK Version: 34 Gradle Version: 8.6 |
Core 11.1.4
### **Fixes**
* Android
* Fixed Multiple Self-Handled InApp API not working when the application is using the React-Native Old Architecture
* iOS
* Fixed build issues when *use\_frameworks* is enabled in the *Podfile*
Cards 5.0.3
### **Fixes**
* iOS
* Fixed build issues when *use\_frameworks* is enabled in the *Podfile*
Geofence 6.0.4
### **Fixes**
* iOS
* Fixed build issues when *use\_frameworks* is enabled in the *Podfile*
Inbox 5.0.4
### **Fixes**
* iOS
* Fixed build issues when *use\_frameworks* is enabled in the *Podfile*
# 29th January 2025
| **Plugins** | **Android Dependencies** |
| --------------------------------------------------------- | --------------------------------------------------------------------------- |
| core: 11.1.3 cards:5.0.2 geofence:6.0.3 inbox:5.0.3 | AGP: 8.4.0 Kotlin: 1.9.23 Compile SDK Version: 34 Gradle Version: 8.6 |
Core 11.1.3
### **What's New**
* Android
* ***moe-android-sdk*** version updated to ***13.05.02***
* ***inapp***version updated to ***8.7.1***
* iOS
* ***MoEngage-iOS-SDK*** version updated to ***9.22.1***
Cards 5.0.2
### **What's New**
* Android
* ***cards-core*** version updated to ***2.3.2***
* iOS
* Internal dependency version update.
Geofence 6.0.3
### **What's New**
* Android
* Added support for MoEngage Android version ***13.05.02***and above
* iOS
* Internal dependency version update.
Inbox 5.0.3
### **What's New**
* Android
* Added support for MoEngage Android version ***13.05.02***and above
* iOS
* Internal dependency version update.
# 08th January 2025
| **Plugins** | **Android Dependencies** |
| --------------------------------------------------------- | --------------------------------------------------------------------------- |
| core: 11.1.2 cards:5.0.1 geofence:6.0.2 inbox:5.0.2 | AGP: 8.4.0 Kotlin: 1.9.23 Compile SDK Version: 34 Gradle Version: 8.6 |
Core 11.1.2
### **What's New**
* Added support for React version 0.76.
# 25th November 2024
| **Plugins** | **Android Dependencies** |
| --------------------------------------------------------- | --------------------------------------------------------------------------- |
| core: 11.1.1 cards:5.0.1 geofence:6.0.2 inbox:5.0.2 | AGP: 8.4.0 Kotlin: 1.9.23 Compile SDK Version: 34 Gradle Version: 8.6 |
Core 11.1.1
### **What's New**
* Android
* ***moe-android-sdk*** version updated to ***13.05.01***
* ***inapp***version updated to ***8.7.0***
* iOS
* Fixed the compiler error in Apple TV
### **Improvements**
* Fixed the lint issue for `**getMoEInAppRules**` with `noImplicitAny` as false in **tsconfig** file
#
# 30th September 2024
| **Plugins** | **Android Dependencies** |
| --------------------------------------------------------- | --------------------------------------------------------------------------- |
| core: 11.1.0 cards:5.0.0 geofence:6.0.1 inbox:5.0.1 | AGP: 8.4.0 Kotlin: 1.9.23 Compile SDK Version: 34 Gradle Version: 8.6 |
Core 11.1.0
### **What's New**
* Android
* ***moe-android-sdk*** version updated to ***13.05.01***
* ***inapp***version updated to ***8.7.0***
* iOS
* Internal dependency version update.
### **Improvements**
* Fixed the lint issue for `**getMoEInAppRules**` with `noImplicitAny` as false in **tsconfig** file
Cards 5.0.1
### **What's New**
* Android
* ***cards-core*** version updated to ***2.3.1***
* iOS
* Internal dependency version update.
Inbox 5.0.2
### **What's New**
* Android
* ***inbox-core*** version updated to ***3.2.1***
* iOS
* Internal dependency version update.
Geofence 6.0.1
### **What's New**
* Android
* ***geofence*** version updated to 4.2.1
* iOS
* Internal dependency version update.
# 07-08-2024
## Core 11.0.0
* iOS
* Added support for tracking custom boolean attributes in two formats: ***0/1*** and ***TRUE/FALSE*** Refer to the [documentation](/developer-guide/react-native-sdk/data-tracking/Tracking-User-Attributes#Custom-Boolean-User-Attribute) for more information.
**Custom Boolean Attribute Tracking in iOS.**
Updating to this version of the SDK will cause MoEngage to start tracking custom user attributes in Boolean syntax as TRUE/FALSE instead of the current 1/0 for iOS devices. This may affect your segmentation and trigger conditions.
In this version, you now have the flexibility to choose how to track custom user attributes with boolean data types. By default, iOS will align with the Android tracking method using TRUE/FALSE. However, you still have the option to continue using the existing 1/0 tracking method if it better suits your campaign requirements.
We recommend migrating to the new TRUE/FALSE method for consistency across platforms. However, we understand that you may have specific use cases where the 1/0 tracking method is preferred. To set your preference, please refer to the [custom attribute tracking section](/developer-guide/react-native-sdk/data-tracking/Tracking-User-Attributes#Custom-Boolean-User-Attribute) in our developer documentation.
* ***MoEngage-iOS-SDK*** version updated to ***9.18.1***
## Inbox 5.0.0
* iOS
* ***MoEngageInbox version updated to \~>2.17.0***
## Cards 4.0.0
* iOS
* ***MoEngageCards*** version updated to ***4.17.1***
## Geofence 6.0.0
* iOS
* ***MoEngageGeofence*** SDK version updated to ***\~>5.17.0***
# 31-07-2024
## Core 10.3.0
Updating to this version of the SDK will cause MoEngage to start tracking custom user attributes in Boolean syntax as TRUE/FALSE instead of the current 1/0 for iOS devices. This may have an effect to your segmentation and trigger conditions. If you wish to continue with the current 1/0 system, we recommend to skip upgrading this version, this will be configurable from 11.0.0 onwards.
* Typescript configuration issue fixes.
* Android
* Added support for AGP ***8.4.0*** and above
* Kotlin version updated to ***1.9.23***
* Compile SDK version updated to ***34***
* ***moe-android-sdk*** version updated to ***13.04.00***
* ***inapp*** version updated to ***8.5.0***
* iOS
* ***MoEngage-iOS-SDK version updated to \~>9.18.0***
## Inbox 4.1.0
* Typescript configuration issue fixes.
* Android
* Added support for AGP ***8.4.0*** and above
* Kotlin version updated to ***1.9.23***
* Compile SDK version updated to ***34***
* ***inbox-core*** version updated to ***3.1.0***
* iOS
* ***MoEngageInbox version updated to \~>2.17.0***
## Cards 3.1.0
* Typescript configuration issue fixes.
* Android
* Added support for AGP ***8.4.0*** and above
* Kotlin version updated to ***1.9.23***
* Compile SDK version updated to ***34***
* ***cards-core*** version updated to ***2.2.0***
* iOS
* ***MoEngageCards*** version updated to ***\~>4.17.0***
## Geofence 5.1.0
* Typescript configuration issue fixes.
* Android
* Added support for AGP ***8.4.0*** and above
* Kotlin version updated to ***1.9.23***
* Compile SDK version updated to ***34***
* ***geofence*** version updated to ***4.2.0***
* iOS
* ***MoEngageGeofence SDK version updated to \~>5.17.0***
# 03-07-2024
## Core 10.2.0
Updating to this version of the SDK will cause MoEngage to start tracking custom user attributes in Boolean syntax as TRUE/FALSE instead of the current 1/0 for iOS devices. This may have an effect to your segmentation and trigger conditions. If you wish to continue with the current 1/0 system, we recommend to skip upgrading this version, this will be configurable from 11.0.0 onwards.
* JSON Object and JSON Array tracking support in user attributes.
* Support for forcing SDK to a specific MoEngage Environment
* Android
* ***moe-android-sdk*** version updated to ***13.02.00***
* ***inapp***version updated to ***8.3.1***
## Inbox 4.0.2
* Android
* ***inbox-core*** version updated to ***3.0.2***
* iOS
* ***MoEngageInbox*** version updated to ***\~>2.16.0***
## Cards 3.0.2
* Android
* ***cards-core*** version updated to ***2.0.2***
* iOS
* ***MoEngageCards*** version updated to ***\~>4.16.0***
## Geofence 5.0.2
* Android
* ***geofence*** version updated to ***4.0.2***
* iOS
* ***MoEngageGeofence*** version updated to ***\~>5.16.0***
# 16-05-2024
# Core 10.1.0
Updating to this version of the SDK will cause MoEngage to start tracking custom user attributes in Boolean syntax as TRUE/FALSE instead of the current 1/0 for iOS devices. This may have an effect to your segmentation and trigger conditions. If you wish to continue with the current 1/0 system, we recommend to skip upgrading this version, this will be configurable from 11.0.0 onwards.
* Adding support for Data Center 6
* Android
* ***moe-android-sdk*** version updated to `13.01.00`
* ***inapp***version updated to `8.3.0`
# 14-05-2024
# Core 10.0.1
Updating to this version of the SDK will cause MoEngage to start tracking custom user attributes in Boolean syntax as TRUE/FALSE instead of the current 1/0 for iOS devices. This may have an effect to your segmentation and trigger conditions. If you wish to continue with the current 1/0 system, we recommend to skip upgrading this version, this will be configurable from 11.0.0 onwards.
* Bugfix
* Adding backward compatibility support for react-native version with react-native-moengage ***10.x.x***
# Inbox 4.0.1
* Bugfix
* Adding backward compatibility support for react-native version with react-native-moengage-inbox ***4.x.x***
# Cards 3.0.1
* Bugfix
* Adding backward compatibility support for react-native version with react-native-moengage-cards ***3.x.x***
# Geofence 5.0.1
* Bugfix
* Adding backward compatibility support for react-native version with react-native-moengage-geofence ***5.x.x***
# 07-05-2024
Release of react-native-moengage version 10.0.0
## 10.0.0 Compatible packages
androidx.lifecycle:lifecycle-process:2.7.0 (2.6.2 also can be used, but please test in apps and push)
com.moengage:rich-notification:5.0.1
react-native-moengage-cards - 3.0.0
react-native-moengage-inbox - 4.0.0
com.moengage:moe-android-sdk: - No need to add this dependency anymore, MoEngage automatically manages the compatibility between android core and react-native-moengage SDKs.
com.moengage:inapp: - No need to add this dependency anymore, MoEngage automatically manages InApp dependency.
com.moengage:cards-core - No need to add this dependency anymore, MoEngage automatically manages cards dependency.
com.moengage:inbox-core - No need to add this dependency anymore, MoEngage automatically manages inbox dependency.
# Core 10.0.0
Updating to this version of the SDK will cause MoEngage to start tracking custom user attributes in Boolean syntax as TRUE/FALSE instead of the current 1/0 for iOS devices. This may have an effect to your segmentation and trigger conditions. If you wish to continue with the current 1/0 system, we recommend to skip upgrading this version, this will be configurable from 11.0.0 onwards.
* Added support for Turbo Architecture
* If you are using Turbo Architecture, you need to use React version 0.73. otherwise, you will face build issues.
* Breaking APIs in Javascript
| Then | Now |
| ------------------------- | --------------------- |
| optOutDataTracking(false) | enableDataTracking() |
| optOutDataTracking(true) | disableDataTracking() |
* iOS
* Removed support for SDK initialization from Info.plist.
* Removed APIs
| List of removed APIs |
| ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| - (void)initializeDefaultInstance:(NSDictionary\**)launchOptions;* |
| *- (void)initializeDefaultInstanceWithState:(MoEngageSDKState)sdkState andLaunchOptions:(NSDictionary*\*)launchOptions; |
| - (void)initializeDefaultInstance:(BOOL)isSdkEnabled andLaunchOptions:(NSDictionary\**)launchOptions;* |
| *- (void)initializeDefaultSDKConfig:(MoEngageSDKConfig*\*)sdkConfig withSDKState:(BOOL)isSdkEnabled andLaunchOptions:(NSDictionary\**)launchOptions* |
* Android
* Making ***moe-android-sdk*** and ***inapp*** artifact as a part of ***react-native-moengage*** plugin.
# Inbox 4.0.0
* Added support for Turbo Architecture
* Android
* Making ***inbox-core*** artifact as a part of ***react-native-moengage-inbox*** plugin.
# Cards 3.0.0
* Added support for Turbo Architecture
* Android
* Making ***cards-core*** artifact as a part of ***react-native-moengage-cards*** plugin.
# Geofence 5.0.0
* Added support for Turbo Architecture
* Android
* Making ***geofence*** artifact as a part of ***react-native-moengage-geofence*** plugin.
# 08-04-2024
Release of react-native-moengage version 9.1.0
# 9.1.0 compatible packages
com.moengage:moe-android-sdk:13.00.03
androidx.lifecycle:lifecycle-process:2.7.0 (2.6.2 also can be used, but please test inapp and push)
com.moengage:cards-core:2.0.2 //self handled cards
com.moengage:inapp:8.2.0
com.moengage:rich-notification:5.0.1
### Requirements
1. AGP >= 7.4
2. If you are upgrading to AGP 8 -> AGP upgrade breaking changes - [https://developer.android.com/build/releases/past-releases/agp-8-0-0-release-notes](https://developer.android.com/build/releases/past-releases/agp-8-0-0-release-notes)
# Core 9.1.0
Updating to this version of the SDK will cause MoEngage to start tracking custom user attributes in Boolean syntax as TRUE/FALSE instead of the current 1/0 for iOS devices. This may have an effect to your segmentation and trigger conditions. If you wish to continue with the current 1/0 system, we recommend to skip upgrading this version, this will be configurable from 11.0.0 onwards.
* Support for Intrusive InApp in TV Platform.
* iOS
* Updated the dependency to MoEngage-iOS-SDK ***9.17.0,*** refer to [release notes](/developer-guide/release-notes/ios-sdk/2024/#8th-April-2024) for more details.
# Inbox 3.1.0
* iOS
* MoEngageInbox SDK version updated to ***2.16.0***.
# Cards 2.1.0
* iOS
* MoEngageCards dependency updated to ***4.16.0*** and above.
# Geofence 4.1.0
* iOS
* MoEngageGeofence SDK version updated to ***5.16.0***.
# 18-03-2024
# Core 9.0.0
* Added support for displaying non-intrusive nudge campaigns
* Removed support for MI Push
* Bugfix
* Exception thrown `***MoEInAppSelfHandledCampaign*** is an invalid object` while logging
* Android
* Support for Native Android SDK version ***13.00.00** and above*, refer to the [release notes](/developer-guide/release-notes/android-sdk/2024/#27th-February-2024) for more details.
* iOS
* Updated the dependency to MoEngage-iOS-SDK ***9.16.1,*** refer to [release notes](/developer-guide/release-notes/ios-sdk/2024/07th-March-2024) for more details.
# Inbox 3.0.1
* Android
* Support for Native Android SDK version ***13.00.00** and above*, refer to the [release notes](/developer-guide/release-notes/android-sdk/2024/#27th-February-2024) for more details.
* iOS
* MoEngageInbox SDK version updated to ***2.15.0***.
# Cards 2.0.1
* Android
* Support for Native Android SDK version ***13.00.00** and above*, refer to the [release notes](/developer-guide/release-notes/android-sdk/2024/#27th-February-2024) for more details.
* iOS
* MoEngageCards dependency updated to ***4.15.1*** and above.
# Geofence 4.0.1
* Android
* Support for Native Android SDK version ***13.00.00** and above*, refer to the [release notes](/developer-guide/release-notes/android-sdk/2024/#27th-February-2024) for more details.
* iOS
* MoEngageGeofence SDK version updated to ***5.15.0***.
# 24-02-2024
# Core 8.7.1
* Android
* Fixed the compile issue due to Java 17 in react-native **0.73.0**
# Inbox 2.6.1
* Android
* Fixed the compile issue due to Java 17 in react-native **0.73.0**
# Cards 1.2.1
* Android
* Fixed the compile issue due to Java 17 in react-native **0.73.0**
# Geofence 3.6.1
* Android
* Fixed the compile issue due to Java 17 in react-native **0.73.0**
# 29-01-2024
# Core 8.7.0
* Added TV OS support
* iOS
* Updated the dependency to MoEngage-iOS-SDK \*\*\*9.15.0,\*\*\*refer to [release notes](/developer-guide/release-notes/ios-sdk/2024/23rd-January-2024) for more details.
# Inbox 2.6.0
* iOS
* MoEngageInbox SDK version updated to ***2.14.0***.
# Cards 1.2.0
* iOS
* MoEngageCards dependency updated to ***4.14.0*** and above.
# Geofence 3.6.0
* iOS
* MoEngageGeofence SDK version updated to ***5.14.0***.
# 29-11-2023
# Core 8.6.0
* Support for tracking an array of numbers and strings in user attributes
* Android
* Support for Native Android SDK version ***12.10.00***, refer to the [release notes](/developer-guide/release-notes/android-sdk/2023-and-older#25-10-2023) for more details.
* Google Policy - API to delete User details.
* Android 14 policy updates.
* iOS
* Updated the dependency to MoEngage-iOS-SDK ***9.13.0***
# Inbox 2.5.0
* Android
* Support for Native Android SDK version ***12.10.00***, refer to the [release notes](/developer-guide/release-notes/android-sdk/2023-and-older#25-10-2023) for more details.
* iOS
* MoEngageInbox SDK version updated to ***2.12.0***.
# Cards 1.1.0
* Android
* Support for Native Android SDK version ***12.10.00***, refer to the [release notes](/developer-guide/release-notes/android-sdk/2023-and-older#25-10-2023) for more details.
* iOS
* MoEngageCards dependency updated to ***4.12.0*** and above.
# Geofence 3.5.0
* Android
* Support for Native Android SDK version ***12.10.00***, refer to the [release notes](/developer-guide/release-notes/android-sdk/2023-and-older#25-10-2023) for more details.
* iOS
* MoEngageGeofence SDK version updated to ***5.12.0***.
# 30-10-2023
## Core 8.5.4
* Android
* Bugfix
* MoEngage SDK throwing incompatible version error on app open
# 31-08-2023
## Inbox 2.4.3
* Bugfix
* PeerDependency version mismatch for ***react-native-moengage***
## Geofence 3.4.3
* Bugfix
* PeerDependency version mismatch for ***react-native-moengage***
## Cards 1.0.1
* Bugfix
* PeerDependency version mismatch for ***react-native-moengage***
# 31-08-2023
## Core 8.5.3
* iOS
* Updated the dependency to MoEngage-iOS-SDK **9.11.0**
## Inbox 2.4.2
* iOS
* Updated the dependency to MoEngageInbox **2.11.0**
## Geofence 3.4.2
* iOS
* Updated the dependency to MoEngageGeofence **5.11.0**
## Cards 1.0.0
* Added support for Self-Handled cards
# 17-08-2023
## Core 8.5.2
* Android
* Bugfix
* Self-handled InApp delivery controls not working.
* Import error for ***MoEngageLogLevel.INFO*** in ***MoEConstant.ts.***
# 18-07-2023
## Core 8.5.1
* Android
* Adding type check config for TypeScript files
* Support for configuring the plugin console logs
## Inbox 2.4.1
* Android
* Adding type check config for TypeScript files
* Support for configuring the plugin console logs
* Adding the **core** moduleas a peer dependency
## Geofence 3.4.1
* Android
* Adding type check config for TypeScript files
* Support for configuring the React-Native Plugin console logs
* Adding the **core** moduleas a peer dependency
# 25-05-2023
## Core 8.5.0
* Android
* Target & Compile SDK Version Updated to 33.
* Support For SelfHandled Push Notification Clicks In Foreground State.
* Bugfix
* Self-handled callback not working for test InApp and event-triggered InApp.
* iOS
* MoEngage-iOS-SDK version updated to **9.8.0**.
## Inbox 2.4.0
* Android
* Target & Compile SDK Version Updated to 33.
* iOS
* MoEngageInbox SDK version updated to **2.8.0.**
## Geofence 3.4.0
* Android
* Target & Compile SDK Version Updated to 33.
* iOS
* MoEngageGeofence SDK version updated to **5.8.0**.
# 16-02-2023
## Core 8.4.0
* iOS
* MoEngage-iOS-SDK version updated to **9.4.0**
## Inbox 2.3.0
* iOS
* MoEngageInbox SDK version updated to **2.4.0**
## Geofence 3.3.0
* Android
* \*\*\*configureGeofence()\*\*\*is deprecated. Use ***startGeofenceMonitoring()*** and \*\*\*stopGeofenceMonitoring()\*\*\*in the Geofence module.
* iOS
* MoEngageGeofence SDK version updated to **5.4.0**.
* Support for ***stopGeofenceMonitoring()*** API.
# 09-02-2023
## Core 8.3.0
* Android
* Android 13 push notification Opt-in with rationale via In-Apps.
* Support for enabling/disabling Device Id tracking.
* Bugfix
* The push-click callback is delivered only after the activity is resumed.
# 17-01-2023
## Core 8.2.0
* iOS
* MoEngage-iOS-SDK version updated to **9.2.0**
* Updated APIs
| Then | Now |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| - (void)initializeDefaultSDKConfig:(MOSDKConfig\**)sdkConfig andLaunchOptions:(NSDictionary*\*)launchOptions; | -(void)initializeDefaultSDKConfig:(MoEngageSDKConfig\**)sdkConfig andLaunchOptions:(NSDictionary*\*)launchOptions; |
| - (void)initializeDefaultSDKConfigWithState:(MOSDKConfig\**)sdkConfig withSDKState:(MoEngageSDKState)sdkState andLaunchOptions:(NSDictionary*\*)launchOptions; | - (void)initializeDefaultSDKConfigWithState:(MoEngageSDKConfig\**)sdkConfig withSDKState:(MoEngageSDKState)sdkState andLaunchOptions:(NSDictionary*\*)launchOptions; |
## Inbox 2.2.0
* iOS
* MoEngageInbox SDK version updated to **2.2.0**.
## Geofence 3.2.0
* iOS
* MoEngageGeofence SDK version updated to **5.2.0**.
# 21-11-2022
## Core 8.1.2
* Bugfix
* Updated the import statement to make the plugin compatible with C++ codebase.
# 09-11-2022
## Core 8.1.1
* Bugfix
* Added missing **MoEngageRichNotification** dependency to the plugin.
## Inbox 2.1.1
* Bugfix
* The payload of ***fetchAllMessages()*** is not in sync with the defined model.
* ***trackMessageClicked()*** and ***deleteMessage()*** not working on Android if the campaign has an image.
# 28-10-2022
## Core 8.1.0
* Android
* Support for Android 13 notification permission
* Support for Android Gradle Plugin version **7.3.1**
* Build Configuration Update
* Compile SDK version - 31
* Target SDK version - 31
* Support for Android SDK version **12.4.00** and above
* iOS
* Initialization APIs are updated to initialize SDK with the state.
| Then | Now |
| -------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| initializeDefaultInstance(\_ config: MOSDKConfig, sdkState: Bool = true, launchOptions: \[UIApplication.LaunchOptionsKey: Any]? = nil) | initializeDefaultInstance(config: MOSDKConfig, sdkState: MoEngageSDKState = .enabled, launchOptions: \[UIApplication.LaunchOptionsKey: Any]? = nil) |
## Inbox 2.1.0
* Android
* Android Gradle Plugin version updated to **7.3.1**
* Gradle version updated to **7.4**
* Compile SDK Version - 31
* Target SDK version - 31
* Support for Android SDK version **12.4.00**
* Inbox Core **2.2.0**
## Geofence 3.1.0
* iOS
* MoEngageGeofence SDK version updated to **\~>4.4.0**.
# 27-09-2022
## Core 8.0.0
* Support for Android SDK version **12.3.02** and above.
* Support for iOS SDK version **8.3.1** and above.
* TS Lint warnings resolved.
* Breaking Changes
* InApp Model MoEInAppCampaign broken down from a single object to multiple objects
* MoEInAppData
* MoEClickData
* MoESelfHandledCampaignData
* Push Model
* MoEPushCampaign --> MoEPushPayload
* Breaking APIs in Javascript
| Then | Now |
| ------------ | ----------------- |
| initialize() | initialize(appId) |
* Removed APIs
| List of removed APIs |
| --------------------------- |
| selfHandledPrimaryClicked() |
| enableSDKLogs() |
| optOutInAppNotification() |
| optOutPushNotification() |
* Android
* Build Configuration Updates
* Minimum SDK Version - 21
* Target SDK Version - 30
* Compile SDK Version - 30
* Mi SDK update to Version 5.x.x, refer to the [Configuring Xiaomi Push](https://developers.moengage.com/hc/en-us/articles/4403466194708) and update the integration
* Deprecated APIs
| Then | Now |
| -------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| MoEInitializer.initialize(Context, MoEngage.Builder) | MoEInitializer.initializeDefaultInstance(Context, MoEngage.Builder) |
| MoEInitializer.initialize(Context, MoEngage.Builder, SdkState) | MoEInitializer.initializeDefaultInstance(Context, MoEngage.Builder, SdkState) |
* iOS
* ***MOReactInitializer*** renamed to ***MoEngageInitializer***
* Deprecated APIs
| Then | Now |
| --------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| - (void)intializeSDKWithLaunchOptions:(NSDictionary\*)launchOptions; | - (void)initializeDefaultInstance:(NSDictionary\*)launchOptions; |
| - (void)intializeSDKWithState:(BOOL)isSdkEnabled andLaunchOptions:(NSDictionary\*)launchOptions; | - (void)initializeDefaultInstance:(BOOL)isSdkEnabled andLaunchOptions:(NSDictionary\*)launchOptions; |
| - (void)intializeSDKWithConfig:(MOSDKConfig\*)sdkConfig andLaunchOptions:(NSDictionary\*)launchOptions; | - (void)initializeDefaultSDKConfig:(MOSDKConfig\*)sdkConfig andLaunchOptions:(NSDictionary\*)launchOptions; |
| - (void)intializeSDKWithConfig:(MOSDKConfig\*)sdkConfig withSDKState:(BOOL)isSdkEnabled andLaunchOptions:(NSDictionary\*)launchOptions; | - (void)initializeDefaultSDKConfig:(MOSDKConfig\*)sdkConfig withSDKState:(BOOL)isSdkEnabled andLaunchOptions:(NSDictionary\*)launchOptions; |
## Inbox 2.0.0
* Support for Android SDK version **12.3.02** and above.
* Support for iOS SDK version **8.3.1** and above.
* TS Lint warnings resolved.
* Breaking Changes
* ***MoEReactInbox.initialize("YOUR\_APP\_ID");*** should be called before calling any other method.
* Android
* Build Configuration Updates
* Minimum SDK Version - 21
* Target SDK Version - 30
* Compile SDK Version - 30
## Geofence 3.0.0
* Support for iOS SDK version **8.3.1** and above, Geofence version **4.3.0** and above.
# Core v7.4.1
Release Date: 15th July 2022
* Device identifier tracking update as per Google's User Data policy. Advertising Id is only tracked after user consent. Along with the plugin update the Native Android dependency to **11.6.02**.
# Core v7.4.0
Release Date: 12th May 2022
* Bugfix iOS:
* Fixed the PushClick callback issue in terminated state, which appeared when the react-native version was above 0.65.
# Inbox v1.2.0
Release Date: 12th May 2022
* iOS
* Native SDK version updated to `~> 7.2.0`.
* Base plugin version dependency updated to `~> 2.3.0`.
# Geofence v2.2.0
Release Date: 16th May 2022
* iOS
* Native SDK version updated to `~> 7.2.0`.
* Base plugin version dependency updated to `~> 2.3.0`.
# Core v7.3.0
Release Date: 16th September 2021
* HTML InApp Support Added.
* Bugfix:
* Handled `trackEvent()` with null properties.
* iOS:
* Native SDK version updated to `~> 7.1.0`.
* Base plugin version dependency updated to `~> 2.1.0`.
* Android:
* Native SDK updated to support version `11.4.00` and above.
* Bugfix:
* `enableSDKLogs()` was not working
# Inbox v1.1.0
Release Date: 16th September 2021
* iOS
* Native SDK version updated to `~> 7.1.0`.
* Base plugin version dependency updated to `~> 2.1.0`.
* Android
* Base plugin version dependency updated to `2.2.0`.
# Inbox v1.0.0
Release Date: 31st August
* Initial Release
* APIs
* Fetch All Messages
* Get unclicked count
* Track message clicked
* Delete message
# Core v7.2.0
Release Date: 11th May 2021
* Android SDK updated to support `11.2.00` and above.
# Core v7.1.0
**Release Date:** 17th March 2021
* Added support to pass Array(String/Number) as event attributes in `addAttribute` method of MoEProperties.
# Core v7.0.0
**Release Date:** 25th February 2021
* Plugin now supports iOS 10.0 and above
* iOS Native Dependencies updated to support MoEngage-iOS-SDK `7.*` and above
* Android Native SDK updated to support `11.0.04` and above. Refer to the [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#11-4-00-31-08-2021) for behaviour changes.
* API to pass PushKit Token JS
* Added APIs to enable and disable MoEngage SDK.
* Added API to register a callback for push token-generated event.
# Core v6.1.7
**Release Date:** 15th February 2021
* Android dependencies updated to use versions published on Maven Central.
# Core v6.1.6
**Release Date:** 21st January 2021
* BugFix iOS: Token registered event produced an error as it's currently not supported in React Native.
# Core v6.1.5
**Release Date:** 18th January 2021
* Updated iOS MoEPluginBase dependency to support version 1.2 and above.
# Core v6.1.4
Release Date: 8th December 2020
* Support for extending Native Android Callbacks if required.
* iOS Base Plugin Updated to version 1.1.1 to ensure SDK sets the UNUserNotification Center delegate only in cases where it's nil.
# Core v6.1.3
Release Date: 25th November 2020
* APIs exposed customizing the Push notification in Android.
# Core v6.1.1
Release Date: 22nd October 2020
* Bugfix
* Events not being marked as non-interactive on Android
# Core v6.1.0
Release Date: 23rd September 2020
* Support for Push Templates
* Android moved to `androidx` namespace.
# Core v6.0.0
Release Date: 7th August 2020
* Breaking change in Initialization of iOS platform, refer to the [developer docs](/developer-guide/ios-sdk/sdk-integration/basic/sdk-initialization) to know more about the changes.
* Support for Self-Handled In-App
* Support for In-App V3
* Event listeners now return a model Object instead of JSON
* `setUserBirthday()` only accepts ISO-8601 String
* Breaking changes in APIs
* Android Native SDK dependency changed to support versions greater than `10.2.02` and above.
* iOS Native SDK dependency changed to support versions greater than `6.0.0`.
| Then | Now |
| --------------------------------------------------------- | --------------------------------------------------------- |
| ReactMoE.isExistingUser(boolean) | ReactMoE.setAppStatus(MoEAppStatus) |
| ReactMoE.trackEvent(string, JSONObject) | ReactMoE.trackEvent(string, MoEProperties |
| ReactMoE.setUserLocation(number, number) | ReactMoE.setUserLocation(MoEGeoLocation) |
| ReactMoE.setUserAttributeLocation(string, number, number) | ReactMoE.setUserAttributeLocation(string, MoEGeoLocation) |
| ReactMoE.setLogLevel(number) | ReactMoE.enableSDKLogs() |
* Android Specific Changes
* APIs to pass push token and payload has changed
| Then | Now |
| ------------------------------------ | --------------------------------------- |
| ReactMoE.passPushToken(string) | ReactMoE.passFcmPushToken(string) |
| ReactMoE.passPushPayload(JSONObject) | ReactMoE.passFcmPushPayload(JSONObject) |
# Core v5.0.0
Release Date: 18th Feb 2020
* New Event Listeners added for both iOS and Android platforms i.e, `pushClicked`, `inAppCampaignShown` and `inAppCampaignShown`.
* Earlier iOS Push and InApp Events deprecated to have it common for both Android and iOS platfroms. (`notificationClicked`, `inAppShown` and `inAppClicked`)
* APIs to pass push token and payload from React-Native Component/Javascript (Android Only API)
# Core v4.1.0
Release Date: 23rd Dec 2019
* Android SDK version updated to 9.8.01
# Android Kotlin SDK Changelog
Source: https://moengage.com/docs/developer-guide/release-notes/segment-integration/android-kotlin-sdk-changelog
View the changelog for the MoEngage Segment Android Kotlin SDK integration.
# 29-01-2026
## 3.5.0
* MoEngage SDK Version updated to **14.06.00**, [Release Notes](/developer-guide/release-notes/android-sdk/2026#4th-February-2026)
# 20-01-2026
## 3.4.1
* MoEngage SDK Version updated to **14.05.01**, [Release Notes](/developer-guide/release-notes/android-sdk/2026#20th-January-2026)
# 19-01-2026
## 3.4.0
* MoEngage SDK Version updated to **14.05.00**, [Release Notes](/developer-guide/release-notes/android-sdk/2026#19th-January-2026)
# 11-12-2025
## 3.3.2
* MoEngage SDK Version updated to **14.04.03,** [Release Notes](/developer-guide/release-notes/android-sdk/2025#11th-December-2025)
# 18-11-2025
## 3.3.1
* MoEngage SDK Version updated to **14.04.01,** [Release Notes](/developer-guide/release-notes/android-sdk/2025#18th-November-2025)
# 29-10-2025
## 3.3.0
* MoEngage SDK Version updated to **14.04.00,** [Release Notes](/developer-guide/release-notes/android-sdk/2025#29th-October-2025)
# 25-09-2025
## 3.2.5
* MoEngage SDK Version updated to **14.03.05,** [Release Notes](/developer-guide/release-notes/android-sdk/2025#25th-September-2025)
# 24-09-2025
## 3.2.4
* MoEngage SDK Version updated to **14.03.04,** [Release Notes](/developer-guide/release-notes/android-sdk/2025#24th-September-2025)
# 08-09-2025
## 3.2.3
* MoEngage SDK Version updated to **14.03.03,** [Release Notes](/developer-guide/release-notes/android-sdk/2025#8th-September-2025)
# 12-08-2025
## 3.2.2
* MoEngage SDK Version updated to **14.03.02,** [Release Notes](/developer-guide/release-notes/android-sdk/2025#12th-August-2025)
# 04-08-2025
## 3.2.1
* MoEngage SDK Version updated to **14.03.01,** [Release Notes](/developer-guide/release-notes/android-sdk/2025#4th-August-2025)
# 15-07-2025
## 3.2.0
* MoEngage SDK Version updated to **14.03.00,** [Release Notes](/developer-guide/release-notes/android-sdk/2025#15th-July-2025)
# 30-06-2025
## 3.1.4
* MoEngage SDK Version updated to **14.02.02,** [Release Notes](/developer-guide/release-notes/android-sdk/2025#27th-June-2025)
# 26-06-2025
## 3.1.3
* MoEngage SDK Version updated to **14.02.01,** [Release Notes](/developer-guide/release-notes/android-sdk/2025#26th-June-2025)
# 19-06-2025
## 3.1.2
* BugFix
* The update callback is not being processed when the update type is 'refresh'.
# 16-06-2025
## 3.1.1
* MoEngage SDK Version updated to **14.02.00,** [Release Notes](/developer-guide/release-notes/android-sdk/2025#16th-June-2025)
# 05-06-2025
## 3.1.0
* MoEngage SDK Version updated to **14.01.00,** [Release Notes](/developer-guide/release-notes/android-sdk/2025#5th-June-2025)
# 26-05-2025
## 3.0.3
* MoEngage SDK Version updated to **14.00.01,** [Release Notes](/developer-guide/release-notes/android-sdk/2025#26th-May-2025)
# 30-04-2025
## 3.0.0
* MoEngage SDK Version updated to **14.00.00,** [Release Notes](/developer-guide/release-notes/android-sdk/2025#30th-April-2025)
* Min supported SDK version updated to 23
* Compile SDK version updated to 35
# 11-03-2025
## 2.5.0
* MoEngage SDK Version updated to **13.06.00,** [Release Notes](/developer-guide/release-notes/android-sdk/2025#11th-March-2025)
* Android Gradle Plugin version updated from **8.4.0** to **8.7.3**
# 22-01-2025
## 2.4.2
* MoEngage SDK Version updated to **13.05.02,** [Release Notes](/developer-guide/release-notes/android-sdk/2025#22nd-January-2025)
# 22-11-2024
## 2.4.1
* MoEngage SDK Version updated to **13.05.01,** [Release Notes](/developer-guide/release-notes/android-sdk/2024#22nd-November-2024)
# 10-09-2024
## 2.4.0
* MoEngage SDK Version updated to **13.05.00,** [Release Notes](/developer-guide/release-notes/android-sdk/2024#10th-September-2024)
# 31-07-2024
## 2.3.0
* MoEngage SDK Version updated to **13.04.00,** [Release Notes](/developer-guide/release-notes/android-sdk/2024#31st-July-2024)
# 03-07-2024
## 2.2.0
* MoEngage SDK Version updated to **13.03.00,** [Release Notes](/developer-guide/release-notes/android-sdk/2024#3rd-July-2024)
* Support for Android Gradle Plugin **8.4.0**
* Updated Kotlin Version to **1.9.23**
* Updated Compile SDK Version to **34**
# 10-06-2024
## 2.1.1
* MoEngage SDK Version updated to **13.02.00,** [Release Notes](/developer-guide/release-notes/android-sdk/2024#10th-June-2024)
# 16-05-2024
## 2.1.0
* MoEngage SDK Version updated to **13.01.00,** [Release Notes](/developer-guide/release-notes/android-sdk/2024#16th-May-2024)
# 29-04-2024
## 2.0.3
* MoEngage SDK Version updated to **13.00.03,** [Release Notes](/developer-guide/release-notes/android-sdk/2024#29th-April-2024)
# 19-03-2024
## 2.0.2
* MoEngage SDK Version updated to **13.00.02,** [Release Notes](/developer-guide/release-notes/android-sdk/2024#19th-March-2024)
# 27-02-2024
## 2.0.0
* MoEngage SDK Version updated to **13.00.00,** [Release Notes](/developer-guide/release-notes/android-sdk/2024#27th-February-2024)
* Support for Android Gradle Plugin **8.2.2**
# 23-01-2024
## 1.5.1
* MoEngage SDK Version updated to **12.10.03,** [Release Notes](/developer-guide/release-notes/android-sdk/2024#23rd-January-2024)
# 29-11-2023
## 1.5.0
* MoEngage SDK Version updated to **12.10.02,** [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#29-11-2023)
* Updated Kotlin Version to **1.7.10**
# 15-11-2023
## 1.4.1
* MoEngage SDK Version updated to **12.10.01,** [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#15-11-2023)
# 25-10-2023
## 1.4.0
* MoEngage SDK Version updated to **12.10.00,** [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#07-09-2023)
# 07-09-2023
## 1.3.3
* MoEngage SDK Version updated to **12.9.03,** [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#07-09-2023)
# 31-08-2023
## 1.3.2
* MoEngage SDK Version updated to **12.9.02,** [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#31-08-2023)
# 09-08-2023
## 1.3.1
* MoEngage SDK Version updated to **12.9.01,** [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#09-08-2023)
# 18-07-2023
## 1.3.0
* MoEngage SDK Version updated to **12.9.00,** [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#18-07-2023)
* Support for Android Gradle Plugin **8.0.2**
# 08-06-2023
## 1.2.1
* MoEngage SDK Version updated to **12.8.01,** [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#08-06-2023)
* Bugfix
* Segment UserId not getting mapped to MoEngage Unique Id while passed through **identify(userId, traits)** call.
# 16-05-2023
## 1.2.0
* MoEngage SDK Version updated to **12.8.00,** [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#16-05-2023)
* Target & Compile SDK Version Update to 33
# 20-04-2023
## 1.1.2
* MoEngage SDK Version updated to **12.7.02,** [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#20-04-2023)
# 10-04-2023
## 1.1.1
* MoEngage SDK Version updated to **12.7.01,** [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#10-04-2023)
# 04-04-2023
## 1.1.0
* MoEngage SDK Version updated to **12.7.00,** [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#04-04-2023)
# 30-03-2023
## 1.0.2
* MoEngage SDK Version updated to **12.6.03,** [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#30-03-2023)
# 16-03-2023
## 1.0.1
* MoEngage SDK Version updated to **12.6.02,** [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#16-03-2023)
# 28-02-2023
## 1.0.0
* MoEngage SDK Version updated to **12.6.01,** [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#14-02-2023)
# Android SDK Changelog
Source: https://moengage.com/docs/developer-guide/release-notes/segment-integration/android-sdk-changelog
View the changelog for the MoEngage Segment Android SDK integration.
# 14-02-2023
## 6.5.8
* MoEngage SDK Version updated to **12.6.01,** [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#14-02-2023)
# 07-02-2023
## 6.5.7
* MoEngage SDK Version updated to **12.6.00,** [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#07-02-2023)
# 31-01-2023
## 6.5.6
* MoEngage SDK Version updated to **12.5.06,** [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#31-01-2023)
# 19-01-2023
## 6.5.5
* MoEngage SDK Version updated to **12.5.05,** [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#19-01-2023)
# 19-12-2022
## 6.5.4
* MoEngage SDK Version updated to **12.5.04,** [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#19-12-2022)
# 07-12-2022
## 6.5.3
* MoEngage SDK Version updated to **12.5.03,** [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#07-12-2022)
# 01-12-2022
## 6.5.2
* MoEngage SDK Version updated to **12.5.02,** [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#01-12-2022)
# 14-11-2022
## 6.5.1
* MoEngage SDK Version updated to **12.5.01,** [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#14-11-2022)
# 04-11-2022
## 6.5.0
* MoEngage SDK Version updated to **12.5.00,** [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#04-11-2022)
# 26-10-2022
## 6.4.0
* MoEngage SDK Version updated to **12.4.00,** [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#26-10-2022)
* Android Gradle Plugin version updated to **7.3.1**
* Build Configuration updated to the following
* compileSdk 31
* minSdk 21
* targetSdk 31
# 20-09-2022
## 6.3.1
* MoEngage SDK Version updated to **12.3.02,** [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#20-09-2022)
# 12-09-2022
## 6.3.0
* MoEngage SDK Version updated to **12.3.01,** [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#12-09-2022)
# 02-09-2022
## 6.2.5
* MoEngage SDK Version updated to **12.2.05,** [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#02-09-2022)
# 6.2.4(13-08-2022)
* MoEngage SDK Version updated to **12.2.03,** [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#12-08-2022)
# 6.2.3(05-07-2022)
* MoEngage SDK Version updated to **12.2.03,** [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#05-07-2022)
# 6.2.2(19-05-2022)
* MoEngage SDK Version updated to **12.2.02**, [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#19-05-2022)
# 6.2.1(11-05-2022)
* MoEngage SDK Version updated to **12.2.01**, [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#11-05-2022)
# 6.2.0(09-05-2022)
* MoEngage SDK version updated to **12.2.00**, [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#12-2-00-09-05-2022)
# 6.1.0(29-04-2022)
* MoEngage SDK version updated to **12.1.00**, [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#12-1-00-29-04-2022)
# 6.0.0(30-03-2022)
## Behavioral Changes
* Build Configuration updated to the following
* compileSdk 30
* minSdk 21
* targetSdk 30
* Starting from SDK version 12.0.00 following features are not integrated by default when adding moe-android-sdk as a dependency. If you are using these features refer to their respective integration document and make update the dependencies.
* [In-App](/developer-guide/ios-sdk/in-app-messages/in-app-nativ)
* [Push Amplification](/developer-guide/android-sdk/push/optional/push-amplification)
* [Device Trigger](/developer-guide/android-sdk/push/optional/device-triggered)
* APIs to initialize the SDK now throws *[IllegalStateException](https://developer.android.com/reference/java/lang/IllegalStateException)* in case App-id is null or empty.
## External Library Version updates
* androidx.core:core 1.3.1 --> 1.6.0
* androidx.appcompat:appcompat 1.2.0 --> 1.3.1
* androidx.lifecycle:lifecycle-process 2.2.0 --> 2.4.0
* com.google.firebase:firebase-messaging 22.0.0 --> 23.0.0
* Kotlin Standard Library 1.4.20 --> 1.6.0
MoEngage SDK version to **12.0.00**. Refer to the [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#12-0-00-16-03-2022) of **12.0.00** for more details.
# 5.6.00(08-03-2022)
* MoEngage SDK version to `11.5.00`, [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#11-5-00-08-03-2022)
# 5.5.04(22-02-2022)
* MoEngage SDK version updated to `11.4.04`, [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#11-4-04-22-02-2022)
# 5.5.03 (31-01-2022)
* MoEngage SDK version updated to `11.4.03`, [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#11-4-03-27-01-2022)
# 5.5.02 (09-11-2021)
* MoEngage SDK version updated to `11.4.02`, [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#11-4-02-09-11-2021)
# 5.5.01(29-09-2021)
* MoEngage SDK version updated to `11.4.01` [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#11-4-01-29-09-2021)
# 5.5.00(30-08-2021)
* MoEngage SDK version updated to `11.4.00`, [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#11-4-00-31-08-2021)
# 5.4.01 (19-07-2021)
* MoEngage SDK version updated to `11.3.01`, [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#11-3-01-19-07-2021)
# 5.4.00 (02-07-2021)
* MoEngage SDK version updated to `11.3.00`, [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#11-3-00-02-07-2021)
# 5.3.01 (13-05-2021)
* MoEngage SDK version updated to `11.2.01`,[Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#11-2-01-13-05-2021)
# 5.3.00 (10-05-2021)
* MoEngage SDK version updated to `11.2.00`, [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#11-2-00-10-05-2021)
# 5.2.00 (14-04-2021)
* MoEngage SDK version updated to `11.1.00`, [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#11-1-00-14-04-2021)
# 5.1.01 (08-04-2021)
* MoEngage SDK version updated to `11.0.05`, [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#11-0-05-08-04-2021)
# 5.1.00 (01-03-2021)
* MoEngage SDK version pinned to a specific version. `11.0.04` in this release.
# 5.0.01 (24-02-2021)
* Updating minimum dependency of MoEngage SDK to the version published on maven central
* Publishing moved to Maven Central. All future updates would be published on Maven Central only.
# 5.0.00 (28-01-2021)
* MoEngage SDK version updated to support `11.0.03` and above. Refer to the[Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#11-0-03-28-01-2021) for more details.
# 4.3.00 (19-11-2020)
* MoEngage SDK version is no longer pinned to a specific version. The latest version within the defined range would be picked. In the defined range major version of the SDK is maintained.
# 4.2.03(05-11-2020)
* Updated MoEngage SDK version to `10.4.04`
# 4.2.02(16-10-2020)
* Updated MoEngage SDK version to `10.4.03`
# 4.2.01(25-09-2020)
* Updated MoEngage SDK version to `10.4.01`
# 4.2.00(17-09-2020)
* Updated MoEngage SDK version to `10.4.00`. Refer to the [Release Notes](/developer-guide/release-notes/android-sdk/2023-and-older#10-4-00-17-09-2021) for more details.
* Moved to `androidx` namespace.
# v4.1.01(07-07-2020)
* Updated MoEngage SDK version to 10.1.01
# v4.1.00(02-07-2020)
* Updated MoEngage SDK version to 10.1.00
* Cards support
# v4.0.03(05-04-2020)
* Updated MoEngage SDK version to 10.0.03
* Migrated integration-verification module to Kotlin
# v4.0.02(18-03-2020)
* Updated MoEngage SDK version to 10.0.02
* Support added for India Cluster
# v4.0.01 (04-03-2020)
* Updated MoEngage SDK version to 10.0.01
# v4.0.00 (21-02-2020)
* Removed Support for manifest based integration
* Removed support for MoEngage's GCM library. If you are still using the GCM dependency move to FCM dependency.
* Removed support for Fresco, use Glide instead if you are using Gifs for In-Apps.
* If sender id is provided while initializing the SDK it will be used for token registration instead of the default sender id in the google-services.json file.
* InApp Callbacks - InApp Callbacks listener is now a concrete class rather than an interface. Refer to the API documentation for more details.
* Self-Handled in-app delivered on the Main thread\
Refer to [Migration Guide](/developer-guide/android-sdk/migration/migration-to-10xxx) documentation for more details.
# iOS SDK Changelog
Source: https://moengage.com/docs/developer-guide/release-notes/segment-integration/i-os-sdk-changelog
View the changelog for the MoEngage Segment iOS SDK integration.
# v8.2.0
**Release Date**: 22nd February 2023
* Updated MoEngage SDK Dependency to 9.5.0
# v8.1.0
**Release Date**: 6th February 2023
* Updated MoEngage SDK Dependency to 9.4.\*
# v7.6.0
**Release Date**: 9th January 2023
* Updated MoEngage SDK Dependency to 8.7.\* *.*
# v8.0.0
**Release Date**: 4th January 2023
* Updated MoEngage SDK Dependency to 9.2.\*
# v7.5.0
**Release Date**: 14th December 2022
* Updated MoEngage SDK Dependency to 8.6.\* *.*
# v7.4.0
**Release Date**: 14th December 2022
* Updated MoEngage SDK Dependency to 8.5.\* *.*
# v7.3.0
**Release Date**: 19th October 2022
* Updated MoEngage SDK Dependency to 8.4.\* *.*
# v7.2.0
**Release Date**:20th July 2022
* Updated MoEngage SDK Dependency to 8.3.\* *.*
# v7.1.0
**Release Date**:7th June 2022
* Updated MoEngage SDK Dependency to 8.2.\* *.*
* Introduced `SEGMoEngageInitializer.h` class to initialize MoEngage-iOS-SDK.
* Added support for Swift Package Manager.
# v6.2.0
**Release Date**: 09th August 2022
* Updated MoEngage SDK Dependency to 7.2.\* *.*
# v6.1.0
**Release Date**: 31st August 2021
* Updated MoEngage SDK Dependency to `~> 7.1.0`.
# v6.0.1
**Release Date**: 10th May 2021
* Fixed import errors for Analytics SDK, as there were 2 different import statements based on the way Analytics SDK was integrated into the project, added support for both.
# v6.0.0
**Release Date**: 23rd February 2021
* Updated pod dependency to support `MoEngage-IOS-SDK` 7.0 and above
# v5.1.0
**Release Date**: 14th December 2020
* Updated pod dependency to support `Analytics` 4.0 and above
# v5.0.0
**Release Date**: 28th July 2020
* Updated pod dependencies to support `MoEngage-iOS-SDK` 6.1.0 and above
# iOS Swift Changelog
Source: https://moengage.com/docs/developer-guide/release-notes/segment-integration/i-os-swift-changelog
View the changelog for the MoEngage Segment iOS Swift SDK integration.
# 29-01-2026
## 2.9.0
* Updated MoEngage-iOS-SDK to 10.10.0
# 19-01-2026
## 2.8.0
* Updated MoEngage-iOS-SDK to 10.09.0
# 29-10-2025
## 2.7.0
* Updated MoEngage-iOS-SDK to 10.08.0
# 24-09-2025
## 2.6.0
* Updated MoEngage-iOS-SDK to 10.07.0
# 08-09-2025
## 2.5.0
* Updated MoEngage-iOS-SDK to 10.05.0
# 05-08-2025
## 2.4.0
* Updated MoEngage-iOS-SDK to 10.04.0
* Added fallback for Segment SDK lifecycle callback misses
# 15-07-2025
## 2.3.0
* Updated MoEngage-iOS-SDK to 10.03.0
* Added support for initializing default SDK instance with configuration data in Application's Info.plist
# 30-06-2025
## 2.2.1
* Updated MoEngage-iOS-SDK to 10.02.2
# 27-06-2025
## 2.2.0
* Updated MoEngage-iOS-SDK to 10.02.1
# 19-06-2025
## 2.1.0
* Updated MoEngage-iOS-SDK to 10.01.0
* Use internal flag to update the SDK instead of segment ***UpdateType***
# 28-05-2025
## 2.0.0
* Updated MoEngage-iOS-SDK to 10.00.0
# 11-03-2025
## 1.5.0
* Updated MoEngage-iOS-SDK to 9.23.0
# 07-01-2025
## 1.4.0
* Added manual integration support.
* Updated MoEngage-iOS-SDK to 9.21.0
# 01-08-2024
## 1.3.0
* Updated MoEngage-iOS-SDK to 9.18.1
# 08-04-2024
## 1.2.0
* Updated MoEngage-iOS-SDK to 9.17.0
# 13-03-2024
## 1.1.0
* Updated MoEngage-iOS-SDK to 9.16.0
# 21-11-2023
## 1.0.1
* Migrated to https URL for SPM dependencies.
# 28-02-2023
## 1.0.0
* An initial release that supports Segment Swift API integrations.
* Supports MoEngage SDK version **9.5.0** and above.
# React-Native Plugin Changelog
Source: https://moengage.com/docs/developer-guide/release-notes/segment-integration/react-native-plugin-changelog
View the changelog for the MoEngage Segment React Native plugin integration.
# 13-06-2023
## 1.0.1
* Removed the Test & Mock files from the plugin npm package
# 31-05-2023
## 1.0.0
* Support for Segment Integration With MoEngage React-Native SDK
# Subscribe to MoEngage SDK Releases
Source: https://moengage.com/docs/developer-guide/release-notes/subscribe-to-moengage-sdk-releases/subscribe-to-mo-engage-sdk-releases
Subscribe to GitHub release notifications to get updates when MoEngage publishes new SDK versions.
You can now receive a notification whenever MoEngage releases a new version of native and hybrid SDKs, by subscribing to the Github release.
You must be logged in to Github.
Perform the following steps to subscribe to an SDK release notification:
1. Go to the required GitHub repository.
We will add support for other SDKs soon.
* Android: [https://github.com/moengage/android-dependency-catalog](https://github.com/moengage/android-dependency-catalog)
* iOS: [https://github.com/moengage/apple-sdk](https://github.com/moengage/apple-sdk)
* React Native: [https://github.com/moengage/React-Native](https://github.com/moengage/React-Native)
* Flutter: [https://github.com/moengage/Flutter-SDK/](https://github.com/moengage/Flutter-SDK/)
* Unity: [https://github.com/moengage/MoEngage-Unity-SDK](https://github.com/moengage/MoEngage-Unity-SDK)
2. Click **Watch**. The Notifications pop-up window is displayed.\\
3. Click **Custom**. The Custom pop-up window is displayed.\\
4. Select **Releases** and click **Apply**.
Whenever MoEngage releases a new version of an SDK, you will receive a notification through an email stating a new version is available.
# Changelog
Source: https://moengage.com/docs/developer-guide/release-notes/unity-sdk/changelog-3
View the changelog and release notes for the MoEngage Unity SDK plugins.
* You can now get notified whenever MoEngage releases a new version of the Unity SDK. For more information, refer to [Subscribe to MoEngage SDK Releases](developer-guide/release-notes/subscribe-to-mo-engage-sdk-releases/subscribe-to-mo-engage-sdk-releases).
* For privacy manifest support on iOS, please make sure that you are on Unity SDK Version 3.2.0 or above and iOS SDK Version 9.17.0 or above. Want to know more about privacy manifest? Refer this [link](https://help.moengage.com/hc/en-us/articles/23893067070996-Apple-Privacy-Manifest-Update).
# 09-09-2025
## Core 5.0.0
* Added support for Unity 6.1
# 07-08-2024
## Core 4.0.0
* iOS
* Added support for tracking custom boolean attributes in two formats: ***0/1*** and ***TRUE/FALSE*** Refer to the [documentation](/developer-guide/react-native-sdk/data-tracking/Tracking-User-Attributes#Custom-Boolean-User-Attribute) for more information.
**Custom Boolean Attribute Tracking in iOS.**
Updating to this version of the SDK will cause MoEngage to start tracking custom user attributes in Boolean syntax as TRUE/FALSE instead of the current 1/0 for iOS devices. This may affect your segmentation and trigger conditions.
In this version, you now have the flexibility to choose how to track custom user attributes with boolean data types. By default, iOS will align with the Android tracking method using TRUE/FALSE. However, you still have the option to continue using the existing 1/0 tracking method if it better suits your campaign requirements.
We recommend migrating to the new TRUE/FALSE method for consistency across platforms. However, we understand that you may have specific use cases where the 1/0 tracking method is preferred. To set your preference, please refer to the [custom attribute tracking section](/developer-guide/react-native-sdk/data-tracking/Tracking-User-Attributes#Custom-Boolean-User-Attribute) in our developer documentation.
* Updated MoEngage-iOS-SDK to dependency to ***9.18.1 .***
* Added DC-06 support
## Geofence 2.0.0
* iOS
* Updated the MoEngageGeofence dependency to ***5.17.1*** .
# 26-04-2024
## Core 3.2.0
Updating to this version of the SDK will cause MoEngage to start tracking custom user attributes in Boolean syntax as TRUE/FALSE instead of the current 1/0 for iOS devices. This may have an effect to your segmentation and trigger conditions. If you wish to continue with the current 1/0 system, we recommend to skip upgrading this version, this will be configurable from 4.0.0 onwards.
* Internal improvements.
* iOS
* Updated the MoEngage-iOS-SDK dependency to **9.17.0** and above. Refer [here](/developer-guide/release-notes/ios-sdk/2024#26-04-2024) for more information.
## Geofence 1.2.0
* iOS
* Updated the MoEngageGeofence dependency to **5.16.0** and above.
# 20-12-2023
## Core 3.1.0
* Android
* Support for SDK version **12.10.02**and above.
* Google Policy Compliance: API to **DeleteUser()** to delete User details.
* iOS
* Updated the MoEngage-iOS-SDK dependency to `9.14.0` and above.
## Geofence 1.1.0
* Android
* Support for native Geofence SDK version **3.4.0** and above.
* iOS
* Updated the MoEngageGeofence dependency to **5.13.0** and above.
# 11-09-2023
* Android
* Bugfix
* New [release assets](https://github.com/moengage/MoEngage-Unity-SDK/releases/tag/rich-notification-v4.5.1) with RichNotification native SDK version update to `4.5.1`.
# 3.0.0 (17-08-2023)
* Support for Android SDK version **12.8.02**.
* Support for iOS SDK version **9.10.0**.
* The MoEngage unity package requires the application to use Unity Version 2023.1.7f1. Version 2023.1.7f1 is required for the target SDK and Gradle version compatibility.
* Breaking Changes
| Then | Now |
| ------------------------- | --------------------- |
| InvalidateInAppContexts() | ResetInAppContexts() |
| OptOutDataTracking(true) | EnableDataTracking() |
| OptOutDataTracking(false) | DisableDataTracking() |
* Removed API
* EnableSDKLogs()
* OptOutPushTracking()
* OptOutInAppTracking()
* SelfHandledPrimaryClicked()
* StartGeofenceMonitoring()
* Android
* Support for Android 13 notification permission.
* Android Gradle Plugin version updated to 7.3.1
* Gradle version updated to 7.4
* Build Configuration Updates
* Compile SDK Version 33
* Target SDK version 33
* Support for Android SDK version **12.8.02**
* InApp **6.7.2**
* Removed and Updated APIs
| Then | Now |
| --------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
| initialize(Context context, MoEngage.Builder builder) | initialiseDefaultInstance(Context context, MoEngage.Builder builder) |
| initialize(Context context, MoEngage.Builder builder, boolean isSdkEnabled) | initialiseDefaultInstance(Context context, MoEngage.Builder builder, SdkState sdkState) |
* iOS
* Removed and Updated APIs
| Then | Now |
| ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| - (void)intializeSDKWithLaunchOptions:(NSDictionary\**)launchOptions andSDKState:(BOOL)isSDKEnabled;* | - (void)initializeSDKWithLaunchOptions:(NSDictionary\*)launchOptions withSDKState:(MoEngageSDKState)sdkState; |
# Geofence 1.0.0(17-08-2023)
* Support for Android Geofence SDK version **3.3.0**
* Support for iOS MoEngageGeofence SDK version **5.10.0** and above.
* Added support for ***StopGeofenceMonitoring*** API.
* iOS
* Removed and Updated APIs
| Then | Now |
| ----------------------------------------- | ------------------------------------------------- |
| MoEngageClient.StartGeofenceMonitoring(); | MoEngageGeofenceClient.StartGeofenceMonitoring(); |
# 2.3.0(25-07-2022)
* Android
* Device identifier tracking update as per Google's User Data policy. Advertising Id is only tracked after user consent. Along with the plugin update the Native Android dependency to `11.6.02`.
* iOS
* Native dependencies updated to support `MoEngage-iOS-SDK` version `7.2.0`.
# 2.2.0(02-09-2021)
* Android
* Native SDK updated to support `11.4.00` and above. Refer to [Release Notes](/developer-guide/release-notes/ios-sdk/2023-and-older#11-4-00-31-08-2021--0-5) for more details.
* iOS
* Native dependencies updated to support `MoEngage-iOS-SDK` version `7.1.0` and above.
# 2.1.0 (11-05-2021)
* Android SDK updated to `11.2.00`
# 2.0.0 (01-03-2021)
* iOS
* Dropped support for iOS 9.\*, plugin now supports iOS version `10.0` and above.
* Native dependencies updated to support `MoEngage-iOS-SDK` version `7.0.0` and above.
* Android
* Android Native SDK updated to support version `11.0.04`.
* Removed APIs
| Then | Now |
| ---------------------------------------------- | ------------------------------------------------- |
| MoEngageClient#Pass PushPayload(IDictionary) | MoEngageClient#PassFcm PushPayload(IDictionary) |
| MoEngageClient#PassPushToken(string) | MoEngageClient#PassFcmPushToken(string) |
# 1.3.1 (16-02-2021)
* Android artifacts use maven central instead of Jcenter.
# 1.3.0 (11-01-2021)
* iOS: UnityAppController Swizzling implementation added since UnityAppController subclass Implementation was not working in case of multiple subclasses.
# 1.2.1 (29-12-2020)
* iOS: Weak linked AppTrackingTransparency framework.
# 1.2.0 (18-12-2020)
* Disable/Enable Methods added to block/unblock the SDK features.
* Push Token Callback added
# 1.1.1 (23-10-2020)
* Bugfix: Events were not marked as non-interactive in iOS in `version 1.1.0`.
# 1.1.0 (30-09-2020)
* Added support for Push Templates
* Provided GDPR OptOut APIs
* iOS Native SDK Dependency set to MoEPluginBase 1.0.0
* Android SDK moved to `androidx` namespace
# 1.0.1 (07-07-2020)
* Android SDK Version update
# 1.0.0 (05-07-2020)
* Initial Release
# Changelog
Source: https://moengage.com/docs/developer-guide/release-notes/web-sdk/changelog-1
View the changelog and release notes for the MoEngage Web SDK.
## v2.68.03
**Release Date:** 12th February 2026
* OSM: Hotfix regarding handle\_page\_change() function in TV device integration.
***
## v2.68.02
**Release Date:** 12th February 2026
* Shopify: Fix regarding saving cart\_token in storage.
* OSM: Fix regarding delivery funnel stats for self-handled OSM.
* Cards: Fix regarding multiple lines of content in Cards message body.
***
## v2.68.01
**Release Date:** 5th February 2026
* GTM: Add Method sequencing for MoEngage public APIs.
* SDK: Fix an infinite user-resolution infinite loop in device attribute tracking.
* NPM: Fixed the disable\_onsite mismatched key name issue.
***
## v2.68.00
**Release Date:** 29th January 2026
* OSM: Array object support for trigger filters.
***
## v2.67.00
**Release Date:** 22nd January 2026
* SDK: Added support for Adblocker Handling.
***
## v2.66.02
**Release Date:** 20th January 2026
* SDK: Fix regarding an IndexedDB transaction.
***
## v2.66.01
**Release Date:** 14th January 2026
* OSM: Fix regarding multiple template calls.
* OSM: Additional error handling in exit intent campaigns.
* Cards: Fix regarding cards button aria label.
***
## v2.66.00
**Release Date:** 8th January 2026
* SDK: Decoupling environment and logs from debug logs.
* SDK: Disable data tracking.
* Cards: Code refactoring.
* OSM: Segment revaluation.
* NPM: Null check for swScope.
***
## v2.65.03
**Release Date:** 6th January 2026
* SDK: Fixed an issue with DC\_101.
***
## v2.65.02
**Release Date:** 19th December 2025
* SDK: Fixed an issue with identifyUser.
* Web Personalisation: Subdomain sharing fetch experiences issue fixed.
***
## v2.65.01
**Release Date:** 4th December 2025
* Web Personalisation: Added cache support for self-handle experiences.
***
## v2.65.00
**Release Date:** 4th December 2025
* OSM: Brizy v3.
* Web Push: Fixed an issue where push subscription details were not removed after unsubscribing.
* Web Push: Fixed an issue where the soft ask did not reappear after logging out.
***
## v2.64.00
**Release Date:** 20th November 2025
* OSM: Added support for Channel-level frequency capping
* Analytics: Updated `destroy_session()` method to handle parallel user logouts
* Analytics: Added support to store third-level domain cookies
* Analytics: Added expiry date to `moe_uuid` cookie
***
## v2.63.02
**Release Date:** 19th November 2025
* Analytics: Removed async from `identifyUser()`, `enableSdk()`, `disableSdk()` methods to make them compatible with new GTM changes
***
## v2.63.01
**Release Date:** 13th November 2025
* WebP: webp reset reapply operations for SPA pages.
***
## v2.63.00
**Release Date:** 06th November 2025
* SDK: SDK-Platform Bug fixes regarding subdomain sharing.
* SDK: Universal Link Tracking - Email
* OSM: Improved test case coverage of the OSM module
***
## v2.62.00
**Release Date:** 30th October 2025
* SDK: Upgraded Node Version to 22.11.0 (LTS)
* Analytics: Refactored subscriber-based billing module
***
## v2.61.02
**Release Date:** 28th October 2025
* OSM: Fix regarding restoring styles when no campaigns exist
***
## v2.61.01
**Release Date:** 23rd October 2025
* OSM: Fix regarding the application of styles on the body tag
***
## v2.61.00
**Release Date:** 16th October 2025
* SDK: Added Multi-App and Portfolio Attributes-Tracking Support
***
## v2.60.01
**Release Date:** 6th October 2025
* Analytics: User logout issue issue
***
## v2.60.00
**Release Date:** 26th September 2025
* SDK: Cookie Storage Reduction
***
## v2.59.00
**Release Date:** 18th September 2025
* Landing Pages: Bypass subscriber billing in landing pages
* Web personalisation: device ID handling issue fix
***
## v2.58.02
**Release Date:** 4th September 2025
* Cards: Bug fix related to `disableSDK`
* Web Personalisation: Removed caching for self-handled personalisation
***
## v2.58.01
**Release Date:** 3rd September 2025
* Push: Hard ask for impression tracking in case of self-handled push
***
## v2.58.0
**Release Date:** 21st August 2025
* OSM: Campaign Priority Management
***
## v2.57.0
**Release Date:** 14th August 2025
* Cards: Cards module size optimised
* Web-Push: Self-handled web push opt-in shown event tracking
* SDK: CI/CD Optimisations
***
## v2.56.2
**Release Date:** 1st August 2025
* Data Tracking: Bugfix related to fetching user before SDK initialisation
***
## v2.56.0
**Release Date:** 17th July 2025
* Landing Pages: added tracking support for subscriber-based billing apps
***
## v2.55.1
**Release Date:** 10th July 2025
* OSM: Added Self Handled OSM support. Follow the integration doc [here](/developer-guide/web-sdk/onsite-messaging/Self-Handled-On-Site-Messaging)
***
## v2.55.0
**Release Date:** 9th July 2025
* WebP: Validate offering context function updated for tracking offering experiences.
***
## v2.54.12
**Release Date:** 3rd July 2025
* WebP: Self-handling experience rendering support
* WebP: Added offering click and shown experience tracking
* Web Push: Fixed issue related to fetching SDK Settings
* Data Tracking: Fixed issues related to subscriber-based billing and cross-subdomain tracking
***
## v2.54.10
**Release Date:** 1st July 2025
* WebP: Self-handling experience rendering support
* WebP: Added offering click and shown experience tracking
***
## v2.54.9
**Release Date:** 1st July 2025
* Web Push: Fixed issue related to fetching SDK Settings
***
## v2.54.8
**Release Date:** 1st July 2025
* Data Tracking: Fixed issues related to subscriber-based billing and cross-subdomain tracking
***
## v2.54.7
**Release Date:** 26th June 2025
* Web SDK Accessibility support in Cards
***
## v2.54.6
**Release Date:** 23rd June 2025
* Web SDK Opt-out: Initialise Lifecycle event emitted even if SDK is disabled
***
## v2.54.4
**Release Date:** 19th June 2025
* Web Push: Refactored and removed unused codes
* Web Personalisation: Updated prefix name for self-handle function
* Web Personalisation: Added support for multiple `moe-data-id`
***
## v2.54.3
**Release Date:** 9th June 2025
* Web SDK Accessibility support in Web Push and On-site messaging
* Shopify: Fixed order of cart items in data tracking payload
* Web SDK Opt-out: Initialising store manager when enabling SDK
***
## v2.54.2
**Release Date:** 27th May 2025
* Web SDK Opt-out
***
## v2.53.5
**Release Date:** 24th April 2025
* Data Tracking: Tracking `moe_aid` in all report calls if present
***
## v2.53.4
**Release Date:** 21st April 2025
* Web Personalisation: Removed JavaScript type attribute from the script tag.
***
## v2.53.3
**Release Date:** 9th April 2025
* Cards: Delete API failure fixed.
* Cards: Content CSS fixed.
***
## v2.53.2
**Release Date:** 8th April 2025
* Cards: Un-clicked count function updated.
* WebP: widget id attribute removed from script tags.
***
## v2.52.2
**Release Date:** 12th March 2025
* Data Tracking: Added support for Multi-ID
***
## v2.52.0
**Release Date:** 4th March 2025
* WebP: Updated default variation method for impression tracking
***
## v2.51.3
**Release Date:** 25th February 2025
* WebP: Hash url support in Web Personalized editor
* Cards: API cards context data updated
***
## v2.51.1
**Release Date:** 13th February 2025
* NPM Package: Added compatibility for server-side rendering
* OSM: Bug-fix for a corner case
***
## v2.51.0
**Release Date:** 30th January 2025
* Web Push: bugfix for push support in Chrome extension
* NPM Package: Added support for CommonJS Module
* Landing Pages: Tracking widget id in `trackClick` function
* Tech: Refactor SPA handler
***
## v2.50.1
**Release Date:** 23rd January 2025
* Segment: Data Center casing related bugfix
***
## v2.50.0
**Release Date:** 20th January 2025
* OSM: Added support of tracking failure stats in Offline mode
* Web Personalisation: Added support for Tabbed Recommendation
* Web Personalisation: Split URL related bugfix
* Web Push: Added support for Push notification in Chrome Extension
***
## v2.49.0
**Release Date:** 9th January 2025
* Web Push: Removed the push permission check while tracking device attribute if the web push module is disabled.
* Web Push: Fixed tracking of push device attribute in an edge-case of subscriber-based billing.
* Web Personalisation: Added public method `renderPageTypeExperience` for Page-Type experience rendering.
* NPM Package: Added support to provide custom SDK-version during initialisation.
* OSM: Fixed fetching meta-data of OSM campaigns on user login.
***
## v2.48.1
**Release Date:** 5th December 2024
* OSM: GCG campaign rendering fix.
* WebP: Split Url Rendering.
* Landing Page Released
***
## v2.48.0
**Release Date:** 21st November 2024
* NPM Package: Added `window.Moengage` null check in integration script
* OSM: Added multiple URL filtering support in a single operation
***
## v2.47.2
**Release Date:** 11th November 2024
* NPM Package: handled cards `on_load` callback in case when cards initialisation takes time
***
## v2.47.1
**Release Date:** 29th October 2024
* Web Push: notification error handling fixed
***
## v2.47.0
**Release Date:** 23rd October 2024
* Cards: Cards Sync and Code improvement.
* Web Push: Code revert for notification error handling
***
## v2.46.3
**Release Date:** 17th October 2024
* OSM: Removed cookies dependency from test campaigns
* Cards: Removed cards frame on user logout
* Data Tracking: Size of offline batches made same as that of online batches
* NPM Package: InitData TypeScript declaration fixed
***
## v2.46.0
**Release Date:** 7th October 2024
* SDK: Added versioning in Web SDK, Cards, Web Personalisation, serviceworker (Web Push)
* NPM package: Added versioning of Web SDK in sync to version in package.json file of the NPM package
* NPM package: Added TypeScript declaration file to assist usage of Web SDK in IDEs
***
## v2.45.1 - All Cluster
**Release Date:** 20th September 2024
* Patch Fixes
* Web-Push: Null check for the 'Notification' window object.
***
## v2.45.0 - All Cluster
**Release Date:** 19th September 2024
* Patch Fixes
* Web-Push: Null check for the 'Notification' window object.
* OSM: Added campaign context in OSM template call
***
## v2.44.0
**Release Date:** 17th September 2024
* Patch Fixes
* Web-Push: Null check for the 'Notification' window object.
* OSM: Added campaign context in OSM template call
***
## v2.43.0 - All Cluster
**Release Date:** 12th September 2024
* SDK: Adding new events and device attributes for Push Subscription events.
* SDK: JSON object support for trigger evaluator.
* Web Personalisation: Remove the default cluster target to dc\_1.
***
## v2.43.1
**Release Date:** 11th September 2024
* SDK (Patch): handled cross-sub-domain push opted
***
## v2.43.0 - Alpha
**Release Date:** 10th September 2024
* SDK: Adding new events and device attributes for Push Subscription events.
* SDK: JSON object support for trigger evaluator.
* Web Personalisation: Remove default cluster target to dc\_1.
***
## v2.42.0 - Alpha
**Release Date:** 3rd September 2024
* OSM: Added support for delay in custom event trigger campaign
* Web Personalisation: Show personalized experiences in preview mode
***
## v2.41.1 - All Cluster
**Release Date:** 29th August 2024
* Web Personalisation: Trigger Personalize based on `pageContext`
* Web Personalisation: Added Page Type filter support
* Data Tracking: Fixed Push Subscriber Billing post-logout issue
* Cards: Added support to handle notification icon on a non-SPA element in a SPA website
* Cards: Removed hidden cards from self-handled APIs
***
## v2.41.0 - Alpha
**Release Date:** 27th August 2024
* Web Personalisation: Trigger Personalize based on `pageContext`
***
## v2.40.2 - All Cluster
**Release Date:** 22nd August 2024
* Data Tracking: User Attribute caching of object-type attributes
* OSM: Passing User ID in API calls
* Web Personalisation: Editor rendering logic change
***
## v2.40.1
**Release Date:** 20th August 2024
* Data Tracking: User Attribute caching of object-type attributes
* OSM: Passing User ID in API calls
***
## v2.40.0
**Release Date:** 19th August 2024
* Web Personalisation: Editor rendering logic change
***
## v2.39.0
**Release Date:** 12th August 2024
* Data Tracking: Bug fixes - `setCurrentSource` error handling
***
## v2.39.0
**Release Date:** 6th August 2024
* Cards: Merged Cards TV features and global dc4 release
***
## v2.38.5
**Release Date:** 2nd August 2024
* Cards: Added support for Cards in TV for DC4
***
## v2.38.4
**Release Date:** 2nd August 2024
* WebP: SUP-22054 - Stats API Failing For hash urls
***
## v2.38.1
**Release Date:** 1st August 2024
* Cards: Added support for Cards in TV - All clusters except dc4
***
## v2.37.7
**Release Date:** 24th July 2024
* Data Tracking: Added condition to check date value in user attribute
***
## v2.37.3 - Alpha
**Release Date:** 2nd July 2024
* OSM: Delivery funnel cases for personalisation failure, delay campaign and API failures
* Web Personalisation: Test experince URL fix for hash URLs.
***
## v2.37.1 - Alpha
**Release Date:** 27th June 2024
* Shopify: Added `cart_token` request param in Shopify multi-ID enabled clients
* Core: Added flag for subscriber billing accepted attributes
* Cards: cards get call hit multiple times bugfix
***
## v2.37.0 - Alpha
**Release Date:** 27th June 2024
* Cards: cards get call hit multiple times bugfix
***
## v2.36.0 - DC4
**Release Date:** 24th June 2024
* OSM: Null check added on a function being called from TV devices
***
## v2.34.4 - DC4
**Release Date:** 20th June 2024
* OSM: New campaigns fetching on every 15min on TV devices fixed
***
## v2.34.3
**Release Date:** 14th June 2024
* Web Personalisation: Anti Flicker code updated
***
## v2.34.2
**Release Date:** 13th June 2024
* Web Push Notification: added check for 1-step without overlay
* Data Tracking: Updating the data tracking API format to support batching
* Core: All scripts caching time updated to 2 weeks
***
## v2.34.1 - Alpha
**Release Date:** 12th June 2024
* Web Push Notification: added check for 1-step without overlay
* Core: All scripts caching time updated to 2 weeks
***
## v2.34.0 - Alpha
**Release Date:** 11th June 2024
* Data Tracking: Updating the data tracking API format to support batching
***
## v2.33.1
**Release Date:** 11th June 2024
* OSM: Replaced dot-space unicode in osm event and attribute names
***
## v2.33.0
**Release Date:** 6th June 2024
* Web Personalisation: Anti-flicker on element basis
***
## v2.30.6
**Release Date:** 19th Apr 2024
* Web personalisation: Server side personalisation feature added
* OSM: AND trigger support added
***
## v2.25.0 - alpha
**Release Date:** 13th Mar 2024
* Web personalisation: Insert operation handling when body is not available
* OSM: Campaign context tracking in OSM lead gen for submitted event
***
## v2.23.1 - alpha
**Release Date:** 12th Mar 2024
* Web personalisation: Real time recommendations support added
***
## v2.23.0 - alpha
**Release Date:** 4th Mar 2024
* Data tracking: Page change handler added
***
## v2.22.2 - alpha
**Release Date:** 4th Mar 2024
* Data tracking: Minor testing logs added
***
## v2.22.1
**Release Date:** 27th Feb 2024
* Data tracking: Page change handler added
***
## v2.22.0
**Release Date:** 22nd Feb 2024
* OSM: Injecting campaign ID in the template
***
## v2.21.1
**Release Date:** 15th Feb 2024
* Data tracking: Enabled beacon for all the clients
* Core: `DisableCookies` config added
***
## v2.20.6
**Release Date:** 29th Jan 2024
* Web personalisation: Minor bugfix
* OSM: OR support in event trigger
***
## v2.20.2
**Release Date:** 29th Jan 2024
* Core: Added remote logs support
***
## v2.20.0
**Release Date:** 23rd Jan 2024
* Web Personalisation: Added mobile specific personalisation support
***
## v2.19.24
**Release Date:** 17th Jan 2024
* Core: Minor bug fix relating to serviceworker in DC build
***
## v2.19.22
**Release Date:** 9th Jan 2024
* Cards: Minor bug fix relating to mobile back button when card is open
***
## v2.19.21 - alpha
**Release Date:** 8th Jan 2024
* Cards: Minor bug fix relating to mobile back button when card is open
***
## v2.19.20
**Release Date:** 3rd Jan 2024
* OSM: Minor bug fix
***
## v2.19.19 - alpha
**Release Date:** 3rd Jan 2024
* OSM: Minor bug fix
***
## v2.19.18
**Release Date:** 2nd Jan 2024
* npm: Added missing keys for initialisation
***
## v2.19.17 - alpha release
**Release Date:** 2nd Jan 2024
* npm: Added missing keys for initialisation
***
## v2.19.16
**Release Date:** 14th Dec 2023
* Core: Added data center support in npm and web personalisation
***
## v2.19.15
**Release Date:** 13th Dec 2023
* Cards: Bug fix relating to default Config being empty
* OSM: Bug fix for test campaigns
***
## v2.19.13
**Release Date:** 8th Dec 2023
* Shopify: Bug fix relating to using phone and email for user ID
***
## v2.19.11
**Release Date:** 6th Dec 2023
* Core: Minor bug fixes
***
## v2.19.9
**Release Date:** 28th Nov 2023
* Web Personalisation: Rendering experiences for specific URL separately
***
## v2.19.7
**Release Date:** 28th Nov 2023
* Core: Internal code refactor and unit test cases
***
## v2.19.2
**Release Date:** 27th Nov 2023
* OSM: Removed Cookies usage in Test campaign
***
## v2.18.7
**Release Date:** 7th Nov 2023
* CARDS: `prev_sync_card_id` added in get call
***
## v2.18.5
**Release Date:** 6th Nov 2023
* WebP: Performance Flicker overlay added.
* Chrome Extension: Added Batched events.
***
## v2.17.15
**Release Date:** 30th Oct 2023
* WebP: Integration error handling and Retry on lazy loading bug fix (SUP-17485)
***
## v2.17.14
**Release Date:** 25th Oct 2023
* Web Push: Fixed popping-up of web push hard-ask optin when `swScope` is configured
***
## v2.17.13
**Release Date:** 19th Oct 2023
* WebP (Bug Fix): Default Variation Impression Tracking
***
## v2.17.12
**Release Date:** 17th Oct 2023
* WebP DPM Phase 2
***
## v2.17.11
**Release Date:** 10th Oct 2023
* WebP and Cards: Bug Fixes
***
## v2.17.10
**Release Date:** 5th Oct 2023
* WebP: DPM Released
***
## v2.17.9
**Release Date:** 26th Sep 2023
* Shopify: Fixed Cart token tracking issue in Firefox - Add To Cart case
***
## v2.17.8
**Release Date:** 8th Sep 2023
* Push: Reverted serviceworker changes which were released on 29th Aug 2023
***
## v2.17.7
**Release Date:** 8th Sep 2023
* Shopify: Cart token tracking issue fixed
***
## v2.17.6
**Release Date:** 5th Sep 2023
* Shopify: Cart token tracking issue testing
***
## v2.17.5
**Release Date:** 5th Sep 2023
* Push: Service worker issue of tracking impression and click fixed
***
## v2.17.4
**Release Date:** 31st Aug 2023
* Shopify: Option for phone to use as user identifier
* Cards: Minor bugfix for self handled cards
***
## v2.17.3
**Release Date:** 29th Aug 2023
* Push: Minor bugfix for `indexedDB` in serviceworker
***
## v2.17.2
**Release Date:** 29th Aug 2023
* Push: Minor bugfix for `indexedDB` in serviceworker
***
## v2.17.1
**Release Date:** 29th Aug 2023
* Push: Minor bugfix for serviceworker
***
## v2.17.0
**Release Date:** 29th Aug 2023
* OSM: Minor bugfix for OSM Pro
* Few Unit test cases added for existing modules
* Push: Merged multiple serviceworkers.
* Web Personalisation: Generating `unique_id` for first load
* Shopify: tracking `cart_token` even if web push is disabled.
***
## v2.16.1
**Release Date:** 8th Aug 2023
* OSM: Minor bugfix for OSM Pro
***
## v2.16.0
**Release Date:** 31st Jul 2023
* Core: New Data centers DC\_5 and DC\_100 added
***
## v2.15.9
**Release Date:** 27th Jul 2023
* OSM: Minor change related to delivery funnel and OSM Pro
***
## v2.15.8
**Release Date:** 24th Jul 2023
* Web personalisation: Minor bug fix related to Same Session personalisation.
***
## v2.15.7
**Release Date:** 18th Jul 2023
* Web personalisation: Same Session personalisation.
***
## v2.15.2
**Release Date:** 4th Jul 2023
* Web personalisation: Added support to add custom HTML and JS in the experience
***
## v2.14.0
**Release Date:** 4th Jul 2023
* OSM Rebranding Banner Template - Iframe to Div.
***
## v2.13.9
**Release Date:** 4th July 2023
* Shopify: minor bug fix on tracking cart token
***
## v2.13.8
**Release Date:** 3rd July 2023
* Shopify: Tracking cart token on add to cart
***
## v2.13.7
**Release Date:** 26th Jun 2023
* Web personalisation: Small bugfix in loading editor
***
## v2.13.6
**Release Date:** 22nd Jun 2023
* Web personalisation: Small bugfix in permalink
***
## v2.13.5
**Release Date:** 21st Jun 2023
* Web personalisation: Added support to render multiple experiences
***
## v2.13.4
**Release Date:** 13th Jun 2023
* Added batching support on Android Chrome and Opera browsers.
***
## v2.13.3
**Release Date:** 12th Jun 2023
* OSM-Rebranding: Anchor Tag Click Tracking and Same Page Redirection.
***
## v2.13.0
**Release Date:** 22nd May 2023
* Core: SDK will stop running if the userAgent is a bot.
***
## v2.12.2
**Release Date:** 17th May 2023
* Core: If DB is blocked or archived then SDK will stop
***
## v2.12.1
**Release Date:** 16th May 2023
* Data Tracking: minor bug fix related to user unique ID tracking
***
## v2.12.0
**Release Date:** 9th May 2023
* Onsite Messaging: Implemented Delivery Funnel to track delivery failure stats
* Web personalisation: Added Multiple URL support
***
## v2.11.1
**Release Date:** 8th May 2023
* Onsite Messaging: GCG campaign fix
* Onsite Messaging: `copyToClipboard` function added in OSM new editor.
***
## v2.11.0
**Release Date:** 2nd May 2023
* Web personalisation: Lazy loading websites handled
***
## v2.10.4
**Release Date:** 26th Apr 2023
* Fixed Mobile Devices Scrolling issue and Exit intent issue
***
## v2.10.3
**Release Date:** 24th Apr 2023
* Web Personalisation: WebP default URL Param's immutable
***
## v2.10.1
**Release Date:** 17th Apr 2023
* Web Push: New config to disable web push module on demand
***
## v2.10.0
**Release Date:** 13th Apr 2023
* Web Personalisation: Added support for default variation
***
## v2.9.1
**Release Date:** 10th Apr 2023
* Integration: Updated integration script of Web SDK to restrict multiple initialisation
***
## v2.8.59
**Release Date:** 3rd Apr 2023
* Push: Support for Web Push Notification in iOS
***
## v2.8.58
**Release Date:** 29th Mar 2023
* Shopify: Minor Bug fix
***
## v2.8.57
**Release Date:** 27th Mar 2023
* Web Personalisation: Minor Bug fix relating to opening editor without referrer
***
## v2.8.56
**Release Date:** 23rd Mar 2023
* Data Tracking: Minor bug fix relating to beacon
***
## v2.8.55
**Release Date:** 16th Mar 2023
* Data Tracking: Started tracking data using beacon instead of xhr.
***
## v2.8.54
**Release Date:** 2nd Mar 2023
* OSM: Minor bug fix related to template rendering
* Shopify: Tracking cart token via serviceworker
***
## v2.8.52
**Release Date:** 22nd Feb 2023
* Web Personalisation: Added support for pre-fetch
***
## v2.8.51
**Release Date:** 22nd Feb 2023
* Data Tracking: Added Chrome iOS browser as a browser name
***
## v2.8.50
**Release Date:** 9th Feb 2023
* Data Tracking: Bug fix related to Batching if events where it is getting cleared
***
## v2.8.49
**Release Date:** 8th Feb 2023
* Web Push: Added Support for Safari MacOS and Edge Web Push Notification
***
## v2.8.48
**Release Date:** 20th Jan 2023
* Shopify: Tracking cart token
***
## v2.8.47
**Release Date:** 19th Jan 2023
* Web Personalisation: Minor bug fix - null pointer check
***
## v2.8.46
**Release Date:** 19th Jan 2023
* Web Personalisation: Preprod testing scope added
***
## v2.8.45
**Release Date:** 12th Jan 2023
* Web Personalisation: Remote logging of all the logs
***
## v2.8.40
**Release Date:** 14th Dec 2022
* OSM: Passing uid in OSM APIs for enabled DBs
***
## v2.8.38
**Release Date:** 28th Nov 2022
* OSM: Re-sync the list of campaigns on login
***
## v2.8.37
**Release Date:** 22nd Nov 2022
* Cards: Added font family support in cards
***
## v2.8.36
**Release Date:** 14th Nov 2022
* Cards: Minor bugfix
***
## v2.8.18
**Release Date:** 20th July 2022
* OSM: Audio / Video support in template added
***
## v2.8.17
**Release Date:** 6th July 2022
* OSM: Resetting overflow style of body on template close
***
## v2.8.16
**Release Date:** 30th June 2022
* amp iframe cross domain sharing fix
* tracking `migrated_user` for push migration case in subscribe event
* in batching, logout first and then create new device and user
* removed `raw` key from cookies to reduce its size
***
## v2.8.15
**Release Date:** 28th June 2022
* OSM: added dynamic event listeners for Lead Gen template
***
## v2.8.14
**Release Date:** 20th June 2022
* Data Tracking: adding event in `indexedDB` for batching case
***
## v2.8.13
**Release Date:** 16th June 2022
* Reverted: OSM meta call performance fixes
***
## v2.8.12
**Release Date:** 13th June 2022
* Updated Readme file to remove environment and inapp host
***
## v2.8.11
**Release Date:** 27th May 2022
* Error logging in console in serviceworker in case of push notification failure
***
## v2.8.8
**Release Date:** 23rd May 2022
* OSM: Improved performance of OSM template call on page load.
***
## v2.8.7
**Release Date:** 17th May 2022
* OSM: Fixed Exit Intent Campaign caching issue
***
## v2.8.6
**Release Date:** 27th Apr 2022
* OSM: Scroll campaigns performance improved. Changed the implementation from continuous probing to throttling.
***
## v2.8.4
**Release Date:** 20th Apr 2022
* Push: Added support for non-inline click event listener for "Don't Allow" Soft Ask
***
## v2.8.2
**Release Date:** 12th Apr 2022
* OSM: Added dismiss on dynamically added elements
***
## v2.8.1
**Release Date:** 4th Apr 2022
* Data Tracking: Support array data type in user attribute tracking
* events broadcast on automated events which are generate by SDK
***
## v2.8.0
**Release Date:** 2nd Mar 2022
* Push: supporting absolute url in serviceworker path
***
## v2.7.30
**Release Date:** 25th Feb 2022
* OSM: Fixed the delay type campaigns in case SPA
* Data Tracking: Removed extra data being stored in Cookies in case of sub domain shared tracking
***
## v2.7.28
**Release Date:** 18th Feb 2022
* Push: Opt-In appearing automatically after resetting permission
***
## v2.7.27
**Release Date:** 31st Jan 2022
* OSM: multiple scroll campaign rendering fix
***
## v2.7.25
**Release Date:** 10th Jan 2022
* Using `device_uuid` from cookies in case of AMP
***
## v2.7.24
**Release Date:** 20th Dec 2021
* Prefetching exit intent type campaigns - checking on every page reload.
***
## v2.7.23
**Release Date:** 16th Dec 2021
* Prefetching exit intent type campaigns - filtering before prefetching
***
## v2.7.21
**Release Date:** 13th Dec 2021
* Prefetching exit intent type campaigns and caching it in browser for faster deliverability
***
## v2.7.20
**Release Date:** 10th Dec 2021
* fix for web push in AMP.
***
## v2.7.19
**Release Date:** 30th Nov 2021
* Support for A/B testing of OSM added.
* Using `campaign_context` for OSM calls.
***
## v2.7.18
**Release Date:** 2nd Nov 2021
* Considering Mobile Number also as a criteria for a user to be considered as subscribed user.
***
## v2.7.12
**Release Date:** 14th July 2021
* Use the API `https://websdk.moengage.com/v2/sdk/report/` to send batch events using Web SDK. The new API replaces the existing API `https://websdk.moengage.com/v2/report/add?`.
* **Release Date (Minor):** 18th June 2021
* Applied the reappear time in Soft Ask
***
## v2.7.11
**Release Date:** 4th June 2021
* fix: passing data to indexed for serviceworker in case of shopify
***
## v2.7.3
**Release Date:** 3rd May 2021
* using `content` instead of `campaign_type` in source params
* added `unique_id` check in OSM API calls
***
## v2.7.0
**Release Date:** 13th January 2021
* Data: Updated the Hosts in different clusters.
* Web Push: Removed pull mechanism code which was redundant
* OSM: Side Banner templates dimension issue fixed
***
## v2.6.4
**Release Date:** 7th December 2020
* Web Push: updated firefox endpoints
* OSM: added margin to side banner template
***
## v2.6.0
**Release Date:** 19th October 2020
* Web Push - Added dedupe check
***
## v2.5.4
**Release Date:** 14th August 2020
* OSM - max times to show a campaign fix
***
## v2.5.3
**Release Date:** 4th August 2020
* `moe_user_id` made as string
***
## v2.5.2
**Release Date:** 20th July 2020
* OSM: passing campaign id in test campaign
* fixed Edge browser detection
***
## v2.5.0
**Release Date:** 13th July 2020
* OSM: introduced `disable_onsite: true`, which can disable the onsite on a particular page.
***
## v2.4.6
**Release Date:** 2nd July 2020
* OSM: exposed the `dismissInapp` method, which can be called to close the OSM campaign without tracking anything
***
## v2.4.5
**Release Date:** 1st July 2020
* OSM: Display over other campaign issue fix
***
## v2.4.4
**Release Date:** 30th June 2020
* OSM validation check fix for Web Personalization
***
## v2.4.3
**Release Date:** 29th June 2020
* OSM validation check fix
***
## v2.4.2
**Release Date:** 19th June 2020
* Passing `new_uid` in `MOE_LOGOUT` event in case of force logout
***
## v2.4.1
**Release Date:** 17th June 2020
* Fix for wrongly showing OSM to unintended user.
***
## v2.4.0
**Release Date:** 10th June 2020
* Added support for AMP analytics
***
## v2.3.0
**Release Date:** 6th June 2020
* Improvement: refactor serviceworker code
* long session duration bug fix
***
## v2.2.0
**Release Date:** 5th May 2020
* Added support for India cluster.
***
## v2.1.0
**Release Date:** 8th April 2020
* Feature: Tracking Additional event attributes for all events
* Tracking `moe_logged_in_status` (boolean) for all events
* Tracking `moe_first_visit` (boolean) for all events
***
## v2.0.6
**Release Date:** 7th April 2020
* Bug fix: browser inactive issue fix on page load
***
## v2.0.5
**Release Date:** 4th April 2020
* Bug fix: browser inactive issue fix
***
## v2.0.4
**Release Date:** 3rd April 2020
* Bug fix: session expiry logic fix for page refresh
***
## v2.0.3
**Release Date:** 30th March 2020
* Bug fix: Increased Local reports Queue size to 50.
***
## v2.0.2
**Release Date:** 23rd March 2020
* Bug fix: Test campaign cookie expiration time and updated sameSite cookie state.
***
## v2.0.1
**Release Date:** 20th March 2020
* Fixed bug related to `pushPage` of Onsite Messaging campaign
***
## v2.0.0
**Release Date:** 18th March 2020
* Stable version released
* Added semantic versioning
# TV and OTT Integrations
Source: https://moengage.com/docs/developer-guide/tv-and-ott-integrations/getting-started/tv-and-ott-integrations
Integrate MoEngage with TV and OTT platforms to track user behavior and send personalized messages.
MoEngage empowers marketers and product managers to understand the behavior of their users and employ multiple communication channels to engage with those users on various TV Operating Systems.
You can capture customers' activities, show personalized, timely messages using communication channels like In-App, On-Site Messages, Cards, Web Personalization (in the case of Web-based platforms), and Push, and also capture customers' interactions with these messages.
Self-handled In-apps / Cards tend to be a predominant use-case in the case of TV Operating Systems so that you can custom handle the JSON payload (or content) delivered by MoEngage and show the content based on your TV app user experience.
# Supported Platforms and Features
| Platform or Channels and Features | Description | Framework |
| --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Data Tracking | Data tracking is available for all TV OS types. The data will be tracked with the *Platform* being set to "TV" and the \_OS Type\_being set to the OS version of the TV device, such as, "Android TV", "Fire TV", etc. | [Android Native](/developer-guide/android-sdk/sdk-integration/basic-integration/Install-Using-BOM), [iOS Native](/developer-guide/ios-sdk/sdk-integration/basic/sdk-integration), [React Native](/developer-guide/react-native-sdk/overview/getting-started-with-react-native-sdk) |
| Push | Android TV currently supports Push notifications, and this feature will be released soon for Amazon Fire TV. However, it is not supported by any other TV platform. **Note**: By default, Push notifications aren't supported on Android TV unless the app is system-whitelisted. | Releasing soon |
| In-App or OSM | Depending on the OS, overlay campaigns are supported on TV devices via In-apps or OSM for TV. [TV In-app campaigns](https://help.moengage.com/hc/en-us/articles/25719907293844-Create-In-App-Campaign-for-TV) are supported for Android TV, Apple TV, Roku TV and Amazon Fire TV. [TV OSM Campaigns](https://help.moengage.com/hc/en-us/articles/25289365657620-Create-OSM-Pro-Campaign-for-TV) are supported by LG webOS, Samsung Tizen OS, VizioTV, and Xbox. | [Android Native](/developer-guide/android-sdk/sdk-integration/basic-integration/Install-Using-BOM), [iOS Native](/developer-guide/ios-sdk/sdk-integration/basic/sdk-integration), [React Native](/developer-guide/react-native-sdk/overview/getting-started-with-react-native-sdk) |
| Cards | Cards are supported in LG webOS, Samsung Tizen OS, VizioTV, and Xbox. To learn more, see [Create a Card Campaign](https://help.moengage.com/hc/en-us/articles/360045074752-Create-a-Card-Campaign). **Note**: Only [Self Handled Cards](/developer-guide/react-native-sdk/cards/self-handled-cards#get-cards-info) are supported for TV. | |
| Web Personalization | This is being released soon for all TV OS types. | Releasing soon |
| | | |
For any help with TV and OTT integrations, please contact your MoEngage Customer Success Manager (CSM) or the Support team.
# Compliance
Source: https://moengage.com/docs/developer-guide/unity-sdk/compliance/compliance
Opt out of data tracking or enable and disable the MoEngage SDK in your Unity application.
# Opt-Out Of Data Tracking
To opt-out of data tracking by the SDK use the **optOutDataTracking( )** method as shown below. Once you have opted out of data tracking you need to explicitly opt-in to start tracking any event OR attributes for the user.
```c# c# theme={null}
// shouldOptOut: Bool indicating opt-out status, set true if you want to opt-out
MoEngageClient.optOutDataTracking(shouldOptOut);
```
# Enable/Disable SDK
If you don't want the MoEngage SDK to track any user information or send any data to the MoEngage System use the **DisableSdk()** method as shown below:
```c# c# theme={null}
MoEngageClient.DisableSdk();
```
Once this API is called all the SDK APIs will be non-operational. SDK will be disabled until **EnableSdk()** is called.\
Once you have the user's consent use the below API to enable the SDK.
```c# c# theme={null}
MoEngageClient.EnableSdk();
```
The above methods are available from the Unity Plugin version 1.2.0.
# Native SDK Initialisation
Based on the compliance policy you can optionally choose to initialize the SDK in a disabled state. To do so you can pass in a boolean value stating the SDK state as disabled while initializing the SDK.
## ANDROID:
```Kotlin Kotlin theme={null}
import com.moengage.unity.wrapper.MoEInitializer
import com.moengage.core.MoEngageimport com.moengage.core.DataCenterimport com.moengage.core.model.SdkState
// this is the instance of the application class and "YOUR_Workspace_ID" is the Workspace ID from the dashboard.
val moEngage = MoEngage.Builder(this, "YOUR_WORKSPACE_ID",[YOUR_DATA_CENTER])
MoEInitializer.initialize(getApplicationContext(), moEngage, sdkState)
```
```Java Java theme={null}
import com.moengage.unity.wrapper.MoEInitializer;
import com.moengage.core.MoEngage;import com.moengage.core.DataCenter;import com.moengage.core.model.SdkState;
// this is the instance of the application class and "YOUR_Workspace_ID" is the Workspace ID from the dashboard.
MoEngage.Builder moEngage =
new MoEngage.Builder(this, "YOUR_WORKSPACE_ID",[YOUR_DATA_CENTER]);
MoEInitializer.initialiseDefaultInstance(applicationContext, moEngage, sdkState)
```
## iOS:
In the case of iOS, SDK is initialized in the `MoEUnityAppController` class. Here update the initialization method to include the disabled SDK parameter as shown below:
```Objective-C Objective-C theme={null}
@implementation MoEUnityAppController
- (instancetype)init
{
self = [super init];
if (self) {
UnityRegisterAppDelegateListener(self);
}
return self;
}
# pragma mark - UIApplicationDelegate methods
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[super application:application didFinishLaunchingWithOptions:launchOptions];
// SDK Initialization, with SDK State(isSdkEnabled) as MoEngageSDKStateDisabled for disabling the SDK
[[MoEUnityInitializer sharedInstance] initializeSDKWithLaunchOptions:launchOptions withSDKState:MoEngageSDKStateDisabled];
return YES;
}
@end
```
# Delete User From MoEngage Server
Source: https://moengage.com/docs/developer-guide/unity-sdk/data-tracking/delete-user-from-moengage-server
Delete the current user from the MoEngage server using the Unity SDK on Android.
This API is supported in **MoEngage Unity Package** starting **3.1.0** and is only available for the Android platform. Download the assets from [here](https://github.com/moengage/MoEngage-Unity-SDK/releases/tag/moengage-v3.1.0).
To delete the current user from the MoEngage server use the **DeleteUser(UserDeletionResponseDelegate)** method as shown below, **UserDeletionResponseDelegate**is a delegate function with **UserDeletionData**parameter, which is triggered when the user deletion is completed.
```javascript c# theme={null}
using MoEngage;
public void DeleteUser() {
Debug.Log("DeleteUser() : ");
MoEngageClient.DeleteUser(MyUserDeletionResponseDelegate);
}
//Delegate function
public void MyUserDeletionResponseDelegate(UserDeletionData data) {
Debug.Log("MyUserDeletionResponseDelegate() : isSuccess: " + data.isSuccess);
}
```
# Enable Advertising Identifier Tracking
Source: https://moengage.com/docs/developer-guide/unity-sdk/data-tracking/enable-advertising-identifier-tracking
Enable advertising identifier tracking in your Unity app using the MoEngage SDK for analytics.
For accurate analytics around devices and tracking Re-installs, it is essential to track the Advertising Identifier.
## Add Ad Identifier Library
Add the below dependency in the application level ***build.gradle*** file.
```groovy Groovy theme={null}
implementation("com.google.android.gms:play-services-ads-identifier:18.0.1")
```
To enable Advertising Identifier tracking use the *enableAdIdTracking()* method as shown below.
```javascript c# theme={null}
using MoEngage;
MoEngageClient.EnableAdIdTracking();
```
Before you enable Advertising Id tracking please ensure the application is complying with the [Google Play Policy](https://support.google.com/googleplay/android-developer/answer/10144311) regarding Advertising Id tracking. Refer to our [help document](https://help.moengage.com/hc/en-us/articles/7457641031828) for more information on the policy.
In case, you need to disable advertising-id after enabling tracking use the following method.
```javascript c# theme={null}
using MoEngage;
MoEngageClient.DisableAdIdTracking();
```
The above APIs are available only starting plugin version 2.3.0. In the older versions, Advertising Identifier tracking is enabled by default.
# Install/Update Differentiation
Source: https://moengage.com/docs/developer-guide/unity-sdk/data-tracking/install-update-differentiation
Differentiate between app installs and updates in your Unity app using the MoEngage setAppStatus API.
SDK needs support to enable the update by the user application or install the application. You need to have logic on the app side to distinguish between app *INSTALL* and *UPDATE*.
If the user was already using your application and has just updated to a new version that has MoEngage SDK, it is an update. Call the below API
```c# c# theme={null}
using MoEngage;
MoEngageClient.SetAppStatus(MoEAppStatus.UPDATE);
```
In case it is a fresh install call the below API
```c# c# theme={null}
using MoEngage;
MoEngageClient.SetAppStatus(MoEAppStatus.INSTALL);
```
# Tracking Events
Source: https://moengage.com/docs/developer-guide/unity-sdk/data-tracking/tracking-events
Track custom user events and their properties in your Unity app using the MoEngage TrackEvent API.
SDK adheres to the MoEngage FUP policies. For more information, refer to the [Fair Usage Policy](https://help.moengage.com/hc/en-us/articles/24151864954644-Fair-Usage-Policy-FUP#h_01HQSMZVQWT2KYP0PY1P8GQMRM).
Tracking events is how you record any actions your users perform, along with any properties that describe the action. Every trackEvent call records a single user action. We recommend that you make your event names human-readable so that everyone on your team can know what they mean instantly.
Every **TrackEvent()** call expects 2 parameters, event name and **Properties** instance which represent additional event attributes about the event. Add all the additional information which you think would be useful for segmentation while creating campaigns. For eg: the following example shows an example of tracking an event with all the possible data types.
```c# c# theme={null}
// Create Properties instance with all the event attributes info
Properties properties = new Properties()
.AddBoolean("booleanAttr", true)
.AddDouble("doubleAttr", 12.34)
.AddInteger("intAttr", 123)
.AddLocation("locationAttr", new GeoLocation(12.21, 13.42))
.AddISODateTime("dateAttr", "2019-01-02T08:26:21.170Z")
.AddString("stringAttr", "test String");
// Track Event to track the Event
MoEngageClient.TrackEvent("UnityEvent", properties);
```
Event names should not contain any special characters other than "\_". It can contain just spaces and an underscore.
# Analytics
MoEngage SDK has started tracking user sessions and application traffic sources. Refer to the [Sessions in MoEngage Analytics](https://help.moengage.com/hc/en-us/articles/360031402891-Understanding-Sessions-in-MoEngage-Analytics) and [Source Analysis in MoEngage Analytics](https://help.moengage.com/hc/en-us/articles/360031146052-Source-Analysis-in-MoEngage-Analytics)to learn more about how user session and application traffic source tracking works.
With user session tracking we have introduced the flexibility to selectively mark events as non-interactive.
## What is a non-interactive event?
Events that do not affect the session calculation in anyways are called non-interactive events. Non-interactive events have the below properties
* Do not start a new session.
* Do not extend the session.
* Do not have information related to a user session.
## How to mark an event as non-interactive?
To mark an event as a non-interactive call **SetNonInteractiveEvent()** for **Properties** instance as shown below:
```c# c# theme={null}
// Create Properties instance with SetNonInteractive()
Properties properties = new Properties()
.AddBoolean("booleanAttr", true)
.AddString("stringAttr", "test String")
.SetNonInteractive();
// Track Event to track the Event
MoEngageClient.TrackEvent("NonInteractive Event", properties);
```
# Tracking User Attributes
Source: https://moengage.com/docs/developer-guide/unity-sdk/data-tracking/tracking-user-attributes
Track user attributes and manage login and logout states using the MoEngage Unity SDK.
User Attributes are pieces of information you know about a user which could be demographics like age or gender, account-specific like plan, or even things like whether a user has seen a particular A/B test variation. It's up to you! It is basically a customer identity that you can reference across the customer’s whole lifetime.
# Implementing Login/Logout
* It's important to set the User Attribute Unique ID when a user logs into your app.
* This is to merge the new user with the existing user, if any exists, and will help prevent creation of unnecessary/stale users.
* Setting the Unique ID is a critical piece to tie a user across devices and installs/uninstalls as well across all platforms (i.e. iOS, Android, Windows, The Web). Set the **USER\_ATTRIBUTE\_UNIQUE\_ID** attribute as soon as the user is **logged in**. Unique ID can be something like an email ID, a username (unique), or a database ID or any Backend generated ID.
* Do not set this for the user who not logged in.
## Login
```c# c# theme={null}
using MoEngage;
MoEngageClient.SetUniqueId("UNIQUE ID");
```
**Note:** The following values are not allowed in the UniqueID field: "unknown", "guest", "null", "0", "1", "true", "false", "user\_attribute\_unique\_id", "(empty)", "na", "n/a", "", "dummy\_seller\_code", "user\_id", "id", "customer\_id", "uid", "userid", "none", "-2", "-1", "2"
## Logout
The application needs to notify the MoEngage SDK whenever the user is logged out of the application. To notify the SDK, call the API whenever the user is logged out of the application.
```c# c# theme={null}
using MoEngage;
MoEngageClient.Logout();
```
In case the application is registering for push token it should pass the new push token to MoEngage SDK after user logout. For more information about passing push tokens, refer to [Push Configuration for Android SDK](/developer-guide/android-sdk/push/basic/push-configuration).
## Updating User Attribute Unique Id
Use the method *setAlias()* to update the user attribute unique id instead of *setUniqueId()* with a different value. Using the method *setUniqueId()* with a new value creates unintended users in MoEngage.
```c# c# theme={null}
using MoEngage;
MoEngageClient.SetAlias("Updated Unique Id");
```
Please make sure that you use **SetAlias()** for updating the Unique Identifier and not **SetUniqueId()** as calling **SetUniqueId()** with a new value will reset the current user and lead to the creation of unintended users in our system.
# Tracking User Attributes
The SDK provides APIs to track commonly tracked user attributes like First Name, Last Name, Email-Id, etc. Please use the provided methods for tracking these attributes.
```c# c# theme={null}
using MoEngage;
MoEngageClient.SetFirstName("First Name");
MoEngageClient.SetLastName("Last Name");
MoEngageClient.SetEmail("Email");
MoEngageClient.SetPhoneNumber("Phone number");
MoEngageClient.SetGender(MoEUserGender.MALE); // MoEUserGender.FEMALE
MoEngageClient.SetUserLocation(new GeoLocation(23, 44));
MoEngageClient.SetBirthdate("2020-01-02T08:26:21.170Z"); // ISO Format : yyyy-MM-dd'T'HH:mm:ss.fff'Z'
```
For setting other User Attributes you can use the generic method **SetUserAttribute(key, value)**
```c# c# theme={null}
using MoEngage;
MoEngageClient.SetUserAttribute(key, value);
```
## Tracking Date as user attributes
To track any date as user attributes use the ***SetUserAttributeISODate()***. This API takes the attribute name and ISO Date as input.\
Date Format - ***yyyy-MM-dd'T'HH:mm:ss.fff'Z'***
Example:
```c# c# theme={null}
using MoEngage;
MoEngageClient.SetUserAttributeISODate("userAttrDate", "2019-01-02T08:26:21.170Z");
```
## Tracking Location as user attributes
To track any location as user attributes use the ***SetUserAttributeLocation()***. This API takes the attribute name and an instance of ***GeoLocation*** for coordinates as input.\
Example:
```c# c# theme={null}
using MoEngage;
MoEngageClient.SetUserAttributeLocation("bangalore", new GeoLocation(23, 44));
```
## Custom Boolean User Attribute
### iOS(optional)
Starting from version 4.x.x of MoEngage.unityPackage, the default tracking for the custom boolean attribute will be changed to ***bool(true/false***) from ***double(0/1)***. To configure this, enable ***should Track Boolean As Number*** variable of MoGameObject script as shown below to track the boolean as double . By default it is ***disabled*** to track boolean as true/false.
Refer to the example code below for tracking the boolean user attribute.
```c# c# theme={null}
using MoEngage;
// If `should Track Boolean As Number` is passed as true then `boolean attribute True` will tracked with value 1 else true
MoEngageClient.SetUserAttribute("boolean attribute true",true);
// If `should Track Boolean As Number` is passed as true then `boolean attribute false` will tracked with value 0 else false
MoEngageClient.SetUserAttribute("boolean attribute false",false);
```
## Reserved keywords for User Attributes
Below is the list of keys that should not be used when tracking user attributes.
* USER\_ATTRIBUTE\_UNIQUE\_ID
* USER\_ATTRIBUTE\_USER\_EMAIL
* USER\_ATTRIBUTE\_USER\_MOBILE
* USER\_ATTRIBUTE\_USER\_NAME
* USER\_ATTRIBUTE\_USER\_GENDER
* USER\_ATTRIBUTE\_USER\_FIRST\_NAME
* USER\_ATTRIBUTE\_USER\_LAST\_NAME
* USER\_ATTRIBUTE\_USER\_BDAY
* USER\_ATTRIBUTE\_NOTIFICATION\_PREF
* USER\_ATTRIBUTE\_OLD\_ID
* MOE\_TIME\_FORMAT
* MOE\_TIME\_TIMEZONE
* USER\_ATTRIBUTE\_DND\_START\_TIME
* USER\_ATTRIBUTE\_DND\_END\_TIME
* MOE\_GAID
* INSTALL
* UPDATE
* MOE\_ISLAT
* status
* user\_id
# InApp NATIV
Source: https://moengage.com/docs/developer-guide/unity-sdk/in-app-messages/inapp-nativ
Display contextual in-app NATIV campaigns in your Unity app using the MoEngage SDK.
In-App NATIV Campaigns target your users by showing a message while the user is using your app. They are very effective in providing contextual information and help to cross-sell/up-sell on desired screens of your app or/and on desired actions performed by the user in your app.
## Installing Android Dependency
Add the following dependency to the **mainTemplate.gradle** file.
```gradle Groovy theme={null}
dependencies {
...
implementation("com.moengage:inapp:$sdkVersion")}
```
replace **\$sdkVersion** with the appropriate SDK version
### **Requirements for displaying images and GIFs in InApp**
Starting InApp version **7.0.0,** SDK requires [Glide](https://bumptech.github.io/glide/) to show images and GIFs in the in-apps. You need to add the below dependency in your **mainTemplate.gradle** file.
```gradle Groovy theme={null}
dependencies {
...
implementation("com.github.bumptech.glide:glide:4.9.0")
annotationProcessor("com.github.bumptech.glide:compiler:4.9.0")
}
```
# Display In-App
Call the below API to show an in-app message on a screen.
```c# c# theme={null}
using MoEngage;
MoEngageClient.ShowInApp();
```
# Self Handled In-Apps
Self Handled In-Apps are messages that are delivered by the SDK but showing has to be done by the App.\
To show In-Apps call the below method.
```c# c# theme={null}
using MoEngage;
MoEngageClient.GetSelfHandledInApp();
```
The payload for self-handled in-app is returned via a callback. Register a callback as shown below.
```c# c# theme={null}
using MoEngage;
// register a callback
MoEGameObject.InAppSelfHandled += InAppSelfHandledCallback;
public void InAppSelfHandledCallback(object sender, InAppSelfHandledCampaignData inAppData) {
/// process the selfhandled payload here
string selfHandledPayload = inAppData.selfHandled.payload;
}
```
## Tracking Statistics
Since display, click, and dismiss for Self-Handled InApp is controlled by the application we need you to notify the SDK whenever the In-App is **Shown**, **Clicked**, or **Dismissed**. Below are the methods you need to call to notify the SDK. The **InAppSelfHandledCampaignData** object provided to the application in the callback for self-handled in-app should be passed in as a parameter to the below APIs.
```c# c# theme={null}
// call whenever in-app is shown
MoEngageClient.SelfHandledShown(campaign);
// call whenever in-app is clicked
MoEngageClient.SelfHandledClicked(campaign);
// call whenever in-app is dismissed
MoEngageClient.SelfHandledDismissed(campaign);
```
# InApp Callbacks
SDK provides callbacks to the client application whenever is shown, dismissed or clicked(only if there is a navigation action or custom action associated with the widget).\
Use the below callbacks to get notified for the above cases
## InApp Shown
```c# c# theme={null}
using MoEngage;
// register a callback
MoEGameObject.InAppShown += InAppShownCallback;
public void InAppShownCallback(object sender, InAppData inappData){
Debug.Log(TAG + " InAppShownCallback() : ");
}
```
## InApp Clicked
```c# c# theme={null}
using MoEngage;
// register a callback
MoEGameObject.InAppClicked += InAppClickedCallback;
public void InAppClickedCallback(object sender, InAppClickData inAppData)
{ Debug.Log(TAG + " InAppClickedCallback() : ");
}
```
## InApp Custom Action
```c# c# theme={null}
using MoEngage;
// register a callback
MoEGameObject.InAppCustomAction += InAppCustomActionCallback;
public void InAppCustomActionCallback(object sender, InAppClickData inAppData)
{
// key value pairs for custom aciton.
IDictionary keyValuePairs = ((CustomAction) inAppData.action).keyValuePairs; Debug.Log(TAG + " InAppCustomActionCallback() : keyValuePairs: " + keyValuePairs.ToString());
}
```
## InApp Dismissed
```c# c# theme={null}
using MoEngage;
// register a callback
MoEGameObject.InAppDismissed += InAppDismissedCallback;
public void InAppDismissedCallback(object sender, InAppData inAppData)
{ Debug.Log(TAG + " InAppDismissedCallback() : ");
}
```
## InApp Payload
```c# c# theme={null}
/// InApp Campaign model
public class InAppData {
/// Account info
public AccountMeta accountMeta;
/// InApp campaign info
public InAppCampaign campaignData;
/// Native platform from which the callback was triggered.
public Platform platform;
}
/// Meta-data related to your MoEngage account.
public class AccountMeta {
/// Account Identifier
public string appId;
}
/// InApp Campaign Details
public class InAppCampaign {
/// Unique identifier for each campaign.
public string campaignId;
/// Campaign Name
public string campaignName;
/// Additional meta data of campaign
public InAppCampaignContext campaignContext;
}
/// Additonal meta of InAppCampaign
public class InAppCampaignContext {
/// Formatted campaign id
public string formattedCampaignId;
}
/// InApp model when click action is performed.
public class InAppClickData {
/// Account info
public AccountMeta accountMeta;
/// InApp campaign info
public InAppCampaign campaignData;
/// Native platform from which the callback was triggered.
public Platform platform;
/// Action info
public InAppClickAction action;
}
/// InApp Navigation action model.Available only in InAppClickedCallback()
public class NavigationAction: InAppClickAction {
/// Navigation action type
public ActionType actionType;
/// Type of Navigation action.Possible value deep_linking or screen
public NavigationType navigationType;
/// Deeplink Url or the Screen Name used for the action.
public string url;
/// Additional Key-Value pairs entered on the MoEngage Platform for navigation action of the campaign
public IDictionary < string, object > keyValuePairs;
}
/// Custom action performed on inapp.Available only in InAppCustomActionCallback()
public class CustomAction: InAppClickAction {
/// Custom Action type
public ActionType actionType;
/// Key-Value Pair entered on the MoEngage Platform during campaign creation.
public IDictionary < string, object > keyValuePairs;
} /// InApp SelfHandled model. Available on InAppSelfHandledCallback() callback
public class InAppSelfHandledCampaignData {
/// Account info
public AccountMeta accountMeta;
/// InApp campaign info
public InAppCampaign campaignData;
/// Native platform from which the callback was triggered.
public Platform platform;
/// SelfHandled payload info
public SelfHandled selfHandled;
}
/// SelfHandled Payload information
public class SelfHandled {
/// Self handled campaign payload.
public string payload;
/// Interval after which in-app should be dismissed, unit - Seconds
public long dismissInterval;
/// Should the campaign be dismissed by pressing the back button or using the back gesture. if the value is true campaign should be dismissed on back press.
public bool isCancellable;
}
```
# Handling Orientation Change
This is only for the Android platform
Starting Unity Plugin version 2.2.0 in-apps are supported in both portrait and landscape modes.\
SDK has to be notified when the device orientation changes for SDK to handle in-app displays.
There are two ways to do it:
1. Add the API call in the Android native part of your app
2. Call MoEngage plugin's **onOrientationChanged()**
3. Add the API call in the Android native part of your app
Notify the SDK when **onConfigurationChanged()** API callback is received in your UnityPlayerActivity class.
```java Java theme={null}
public class SampleUnityPlayerActivity extends UnityPlayerActivity {
...
@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
super.onConfigurationChanged(newConfig);
//API to notify MoEngage SDK
MoEUnityHelper.getInstance().onConfigurationChanged();
...
}
...
}
```
If you don't want to create a custom **UnityPlayerActivity**, MoEngage SDK on Android comes bundled with **MoEUnityPlayerActivity** which internally handles the device configuration changes.\
This activity needs to be added as an entry point to your app, to do so replace your current entry point with the below code in your **AndroidManifest.xml**.
```xml XML theme={null}
...
...
```
## Call the MoEngage plugin's orientation change API
Call the below API to notify SDK of the orientation change.
```objectivec c# theme={null}
MoEngageClient.OnOrientationChanged();
```
# Android Notification Runtime Permissions
Source: https://moengage.com/docs/developer-guide/unity-sdk/push/basic/android-notification-runtime-permissions
Handle Android 13 notification runtime permissions in your Unity app using the MoEngage SDK.
This is supported from Plugin version **3.0.0**.
Android 13 (API level 33) and higher supports [runtime permission](https://developer.android.com/guide/topics/permissions/overview#runtime) for sending [non-exempt](https://developer.android.com/develop/ui/views/notifications/notification-permission#exemptions)(including Foreground Services (FGS)) notifications from an app [POST\_NOTIFICATIONS](https://developer.android.com/reference/android/Manifest.permission#POST_NOTIFICATIONS). This change helps users focus on the notifications that are most important to them.
Refer to the [official documentation](https://developer.android.com/develop/ui/views/notifications/notification-permission) for more details.
When the application is running on Android 13 to show notifications to the user, applications would need to request the user for notification permission.
For applications integrating the MoEngage SDK, would need to
* Notify the SDK of the permission request's response from the user.
* If the application has already requested push permission(before MoEngage integration) help MoEngage set up notification channels for notification display.
## Notify SDK of permission result
Once the application requests the user for notification permission notify the SDK of the user response using the below API. *If you are letting MoEngage SDK handle the notification permissions, you should ignore this step.*
```c# c# theme={null}
using MoEngage;
MoEngageClient.PushPermissionResponseAndroid(isGranted)
```
## Setup Notification Channels
If the application has already taken notification permission from the user call the below API to set up Notification Channels for showing push notifications.
```c# c# theme={null}
using MoEngage;
MoEngageClient.SetupNotificationChannelsAndroid()
```
## Let MoEngage SDK handle Notification permission
MoEngage SDK provides helper APIs to show the permission request to the end-user or navigate the user to the settings screen for enabling notifications.
Use the below API to show the permission request dialog to the user.
When using the below API SDK automatically tracks the response, sets up the required notification channel, etc, mentioned above.
```c# c# theme={null}
using MoEngage;
MoEngageClient.RequestPushPermissionAndroid()
```
## Navigate to Notification Settings (situational/optional)
Use the below API to show navigate the user to the Notification Settings for the application on the device.
*Note*: Below Android 8(API level 26) the user is directed to the Application Info screen of your application.
```c# c# theme={null}
using MoEngage;
MoEngageClient.NavigateToSettingsAndroid()
```
## Update the Permission request count
Once the application requests the user for notification permission, update the SDK of the request attempts.
### Why does the SDK require permission attempt count?
SDK requires the attempt count to accurately track the number of times the permission request was attempted. If the user denies the permission request twice the application/SDK cannot request permission further i.e. if we request permission it would be automatically denied without the user seeing the request dialog. As an SDK we cannot be sure of the number of times the user has denied the permission we try to optimize the calls to request permission based on the attempt count.
```c# c# theme={null}
using MoEngage;
MoEngageClient.UpdatePushPermissionRequestCountAndroid(count)
```
# Android Push Configuration
Source: https://moengage.com/docs/developer-guide/unity-sdk/push/basic/android-push-configuration
Configure Android push notifications in your Unity app including Firebase and push token setup.
## Basic Configuration
To use Push Notification in your Unity application, you need to configure Firebase into your application; refer to the following documentation to configure Push Notification in your application.
* [Push Notification](/developer-guide/android-sdk/push/basic/push-configuration)
* [Configuring FCM](/developer-guide/android-sdk/push/basic/push-token-registration-and-display)
In case your application is handling the push token registration and push payload, we highly recommend you use the native Android methods(mentioned in the documentation above) for passing the token and the payload to the SDK. If, for whatever reason, you wish to handle the token registration and handle incoming messages by yourself, pass the push token and payload to the SDK by using the below APIs
Also, make sure you have set up [Firebase for Unity](https://firebase.google.com/docs/cloud-messaging/unity/client).
NotificationConfig requires assets for small icon and large icon, depending your Unity version you will have to include these in either in **Assets/res** folder or include the raw assets in an Android Library Project or AAR. For more information on AAR, refer [here](https://docs.unity3d.com/2023.1/Documentation/Manual/android-library-project-and-aar-plugins-introducing.html).
## Passing Push Token
```c# c# theme={null}
using MoEngage;
MoEngageClient.PassFcmPushToken()
```
## Passing Push Payload
```c# c# theme={null}
using MoEngage;
MoEngageClient.PassFcmPushPayload()
```
We highly recommend you use the Android native APIs for passing the push payload to the MoEngage SDK instead of the Unity/C# APIs. Unity Engine might not get initialized if the application is in the killed state which will lead to poor push reachability or delivery.
## Customizing Push notification
If required the application can customize the behavior of notifications by using Native Android code (Java/Kotlin). To learn more about the customization refer to the [Advanced Push Configuration](/developer-guide/android-sdk/push/advanced/callbacks-and-customisation) documentation.Instead of extending ***PushMessageListener*** as mentioned in the above document extend ***PluginPushCallback.***
Refer to the below documentation for Push Amp+, Push Templates, and Geofence.
* [Push Templates](/developer-guide/android-sdk/push/optional/push-templates)
* [GeoFence Push](/developer-guide/android-sdk/push/optional/location-triggered)
# iOS Push Configuration
Source: https://moengage.com/docs/developer-guide/unity-sdk/push/basic/ios-push-configuration
Configure iOS push notifications in your Unity app including APNS certificates and push registration.
# Configuring Push in iOS
## APNS Certificate
First, you will have to create an APNS certificate and upload to the dashboard to be able to send push notifications in iOS. Follow the steps below to do that :
* [Create an APNS certificate](/developer-guide/ios-sdk/integration-with-older-version-of-sdk/push/basic/apns-certificate-pem-file)
* [Convert the resultant certificate to .pem format](/developer-guide/ios-sdk/integration-with-older-version-of-sdk/push/basic/apns-certificate-pem-file-7xx)
* [Upload .pem file to MoEngage Dashboard](/developer-guide/ios-sdk/integration-with-older-version-of-sdk/push/basic/apns-certificate-pem-file-7xx)
\*Follow the links on each step to complete it.
## Push Registration
After this you will have to register for push notification in the App by using **RegisterForPush** method of the plugin as shown below:
```c# c# theme={null}
using MoEngage;
MoEngageClient.RegisterForPush();
```
## App Target Settings
MoEngage plugin takes care of setting up the project while building it for the first time. But verify the Capability section has `Push Notifications` enabled along with `AppGroups` and `Background Mode` Settings as shown below:
MoEngage plugin creates an app group for the app with format: `group..moengage`. Make sure the same is resolved with the Apple developer account here.
## Extensions
MoEngage plugin takes care of setting up the Extension target too. Make sure the same App Group Id is set for MoENotificationServiceExtension and MoEPushTemplateExtension.
# Push Callback
Source: https://moengage.com/docs/developer-guide/unity-sdk/push/basic/push-callback
Set up push notification click observers to handle notification interactions in the MoEngage Unity SDK.
# Notification Click Observers
MoEngage plugin triggers the **PushNotifCallback** event whenever a notification is clicked. This event is a common trigger for both iOS and Android platforms. Refer to the below code to set the observer to the same:
```auto c# theme={null}
using MoEngage;
// Add Push Callback for MoEGameObject
MoEGameObject.PushNotifCallback += PushCallback;
//Implement the calback
public void OnPushClicked(object sender, PushCampaignData campaignData)
{
Debug.Log(" OnPushClicked() : Event handler callback: " + campaignData.platform +
" \n clickedAction: " + campaignData.data.clickedAction + " \n payload:" + campaignData.data.payload);
}
```
## PushCampaignData structure
PushCampaignData instance will have the below properties:
```auto c# theme={null}
public class PushCampaignData {
/// Account info
public AccountMeta accountMeta;
/// PushCampaign data object
public PushCampaign data;
/// Native platform from which the callback was triggered.
public Platform platform;
}
/// Meta-data related to your MoEngage account.
public class AccountMeta {
/// Account Identifier
public string appId;
}
/// Push Payload information
public class PushCampaign {
/// This key is present only for the Android Platform. It's a boolean value indicating if the user clicked on the default content or not. true if the user clicks on the default content else false.
public bool isDefaultAction;
/// Action to be performed on notification click.
public IDictionary < string, object > clickedAction;
/// Complete campaign payload.
public IDictionary < string, object > payload;
}
/// Platform on which Push Campaign belongs
public enum Platform {
iOS,
Android
}
```
Payload Structure for **clickedAction** Dictionary
```json JSON theme={null}
{
"clickedAction": {
"type": "navigation/customAction",
"payload": {
"type": "screenName/deepLink/richLanding",
"value": "",
"kvPair": {
"key1": "value1",
"key2": "value2",
...
}
}
}
}
```
**clickedAction**- Action to be performed on notification click.
**clickedAction.type**- Type of click action. Possible values **navigation** and **customAction**. Currently, **customAction** is supported only on Android.
**clickAction.payload** - Action payload for the clicked action.\
**clickedAction.payload.type** - Type of navigation action defined. Possible values **screenName**, **deepLink**, and **richLanding.**
Currently, in the case of iOS, rich landing and deep-link URLs are processed internally by the SDK and not passed in this callback; therefore possible value in the case of iOS is only **screenName**.\
**clickAction.value** - value entered for navigation action or custom payload.\
**clickAction.kvPair** - Custom key-value pair entered on the MoEngage Platform.\
**payload** - Complete campaign payload.
## Android Payload
If the user clicks on the default content of the notification, the key-value pair and campaign payload can be found inside the **payload** key. If the user clicks on the action button or a push template action, the action payload would be found inside **clickedAction**.\
You can use the **isDefaultAction** key to check whether the user clicked on the default content and then parse the payload accordingly.
## iOS Payload
In the case of iOS, you would always receive the key-value pairs with respect to clicked action in **clickedAction** property. Refer to this [link](/developer-guide/android-sdk/push/basic/ios-push-integration-tutorial) for knowing the iOS notification payload structure.
# Configuring Push Templates
Source: https://moengage.com/docs/developer-guide/unity-sdk/push/optional/configuring-push-templates
Import the RichNotifications package to add push notification templates in your Unity app.
To integrate Push Template, Go to Unity Editor, navigate to **Assets > Import Package > Custom Package,** and import the **RichNotifications.unitypackage**\
The above package is part of the Android folder in the **.zip** file you downloaded during installation.
# Location Triggered
Source: https://moengage.com/docs/developer-guide/unity-sdk/push/optional/location-triggered
Import the Geofence package to enable location-triggered push notifications in your Unity app.
To integrate Geofence, Go to Unity Editor, navigating to `Assets > Import Package > Custom Package` and import the `Geofence.unitypackage`. The package is part of the `.zip` file you downloaded during installation.
# Initialization
Add ***MoEGeofenceGameObject.cs*** to the same object created in the [Unity Initialization](/developer-guide/unity-sdk/sdk-integration/sdk-initialization/sdk-initialization) step and set the ***App Id***
# Android Configuration
## Prerequisites for Geofence
To use geofencing, your app must request the following:
* ACCESS\_FINE\_LOCATION
* ACCESS\_BACKGROUND\_LOCATION if your app targets Android 10 (API level 29) or higher
For Geofence pushes to work your Application should have location permission and [Play Services' Location Library](https://developers.google.com/android/guides/setup#declare-dependencies) should be included.
Refer to the [documentation](https://developer.android.com/training/location/geofencing#RequestGeofences) for more details on Geofence.
# iOS Configuration
Post integration with the geofence package make sure to [Build and Replace](/developer-guide/unity-sdk/sdk-integration/sdk-initialization/ios-sdk-initialization) for iOS.
# Configuration
## Start Geofence Monitoring
After integrating the geofence package call ***StartGeofenceMonitoring()*** method to initiate the geofence module, this will fetch the geofences around the current location of the user. Please take a look at the [iOS doc](/developer-guide/ios-sdk/push/optional/location-triggered) and [Android doc](/developer-guide/android-sdk/push/optional/location-triggered) for more information on Geofence. By default, the geofence feature is not enabled. You need to call the ***S***\*\**tartGeofenceMonitoring*()\*\*to receive location-triggered
```c# c# theme={null}
using MoEngage;
MoEngageGeofenceClient.StartGeofenceMonitoring();
```
## Stop Geofence Monitoring
If you want to stop the geofence monitoring or feature use the ***StopGeofenceMonitoring()*** API. This API will remove the existing geofences.
```c# c# theme={null}
using MoEngage;
MoEngageGeofenceClient.StopGeofenceMonitoring();
```
# Limitations
Source: https://moengage.com/docs/developer-guide/unity-sdk/sdk-integration/limitations
Review unsupported features and native integration requirements when using the MoEngage Unity plugin.
Compared to the Native Android/iOS SDKs there are a certain set of features we either do not support or require native Android/iOS implementation when using our Unity plugin.
# Features not supported
* In-App Nudges
* Action Buttons in iOS Notifications
* Huawei Push Kit
* Xiaomi Push
# Features that are supported but require Native Integration
* Inbox Module
* Cards
# Android SDK Initialization
Source: https://moengage.com/docs/developer-guide/unity-sdk/sdk-integration/sdk-initialization/android-sdk-initialization
Initialize the MoEngage SDK in your Unity project's Android Application class and manifest.
# Enable Custom Manifest File
Navigate to Build Settings and switch the platform to Android. Then go to **Player Settings --> Player --> Android --> Publishing Settings**.\
Under the Build Heading check **Custom Main Manifest**.
# Adding Dependencies
MoEngage plugin depends on the following Jetpack libraries. In case you don't have them in your application already, please add them.\
You can choose to enable the custom gradle template in your Application's **Player Settings** and the below dependencies.
```Groovy Groovy theme={null}
implementation("androidx.core:core:1.9.0") implementation("androidx.appcompat:appcompat:1.4.2") implementation("androidx.lifecycle:lifecycle-process:2.5.1")
```
# Add Application Class
* Create a Java/Kotlin class and add it to the **Assets --> Plugins --> Android** folder. Extend the class with **android.app.Application** and override the onCreate().
* Declare the above-created class in the Manifest file inside the application tag.
```AndroidManifest.xml AndroidManifest.xml theme={null}
```
The Manifest file can be found in the **Assets--> Plugins --> Android** folder.
# SDK Initialization
Get the Workspace**ID** from the **Settings Page\*\*\*\*Dashboard --> Settings --> Workspace --> General** on the MoEngage dashboard and initialize the MoEngage SDK in the **Application class's onCreate()** method.
It is recommended that you initialize the SDK on the main thread inside **onCreate()** and not create a worker thread and initialize the SDK on that thread.
```Kotlin kotlin theme={null}
import com.moengage.unity.wrapper.MoEInitializer
import com.moengage.core.MoEngageimport com.moengage.core.DataCenter
// this is the instance of the application class and "YOUR_Workspace_ID" is the Workspace ID from the dashboard.
val moEngage = MoEngage.Builder(this, "YOUR_Workspace_ID", DataCenter.DATA_CENTER_X)
MoEInitializer.initialize(getApplicationContext(), moEngage)
```
```Java Java theme={null}
import com.moengage.unity.wrapper.MoEInitializer;
import com.moengage.core.MoEngage;import com.moengage.core.DataCenter;
// this is the instance of the application class and "YOUR_Workspace_ID" is the Workspace ID from the dashboard.
MoEngage.Builder moEngage = new MoEngage.Builder(this, "YOUR_Workspace_ID",[YOUR_DATA_CENTER]);
MoEInitializer.initialiseDefaultInstance(applicationContext, moEngage)
```
Following details of the different data centers you need to set based on the dashboard hosts
| Data Center | Dashboard host |
| -------------------------- | ------------------------- |
| DataCenter.DATA\_CENTER\_1 | dashboard-01.moengage.com |
| DataCenter.DATA\_CENTER\_2 | dashboard-02.moengage.com |
| DataCenter.DATA\_CENTER\_3 | dashboard-03.moengage.com |
| DataCenter.DATA\_CENTER\_4 | dashboard-04.moengage.com |
| DataCenter.DATA\_CENTER\_5 | dashboard-05.moengage.com |
For more information about the detailed list of possible configurations, refer to the [API reference](%20https://moengage.github.io/android-api-reference/core/com.moengage.core/\[android-jvm]-mo-engage/-builder/index.html).
All the configurations are added to the builder before initialization. If you are calling initialize at multiple places, ensure that all the required flags and configurations are set each time you initialize to maintain consistency in behavior.
# Exclude MoEngage Storage File from Auto-Backup
This is a mandatory integration step and is very essential to prevent your data from getting corrupted. Android's auto back-up service periodically backs up Shared Preference files, Database files, etc, more details [here](https://developer.android.com/guide/topics/data/autobackup). This backup results in MoEngage SDK's identifiers being backed up and restored after re-install.This restoration of the identifier results in your data being corrupted and users not being reachable via push notifications.
To ensure data is not corrupted after a backup is restored, opt out of MoEngage SDK's storage files. Refer to [Exclude MoEngage Storage File from the Auto-Backup](/developer-guide/android-sdk/sdk-integration/basic-integration/exclude-moengage-storage-file-from-auto-backup) section of the documentation to learn more about which files to exclude.
# iOS SDK Initialization
Source: https://moengage.com/docs/developer-guide/unity-sdk/sdk-integration/sdk-initialization/ios-sdk-initialization
Initialize the MoEngage SDK in your Unity project's iOS configuration file with your workspace ID.
# Include MoEngage Configuration
After the MoEngage package is imported, include ***MoEngageConfiguration.h*** file in your Asset folder\
(`Asset > Import New Asset`). Download this configuration file from [here](https://github.com/moengage/MoEngage-Unity-SDK/blob/master/iOS/MoEngageConfiguration.h).
In your configuration file, set MoEngage App ID and Region along with other constants as shown below:
```objectivec Objective-C theme={null}
// MoEngage Account Identifier
#define kMoEngageAppID @"YOUR WORKSPACE ID"
/// Set DataCenter
#define kMoEngageRegion NULL// DATA_CENTER_01/DATA_CENTER_02/DATA_CENTER_03/DATA_CENTER_04/DATA_CENTER_05
/// Set Xcode console logs for debugging purpose
#define kMoEngageLogsEnabled YES // YES/NO
/// Enable UnityController Swizzling.
#define kMoEngageUnityControllerSwizzlingEnabled YES // YES/NO
/// Interval at which data must be send to MoEngage
#define kMoEngageAnalyticsPeriodicFlushDuration 60 // Any value greater than 60
/// Bool to disable to periodic flush of events.
#define kMoEngageAnalyticsDisablePeriodicFlush NO // YES/NO
/// Inset value for nudge placement. Currently Nudge is not supported in Unity.
#define kMoEngageInAppSafeArea 0
/// Bool to enable Storage Encryption
#define kMoEngageStorageEncryption NO // YES/NO
/// Set the keychain group name to save the encryption key in keychain
#define KeyChainGroupName NULL
/// If true sdk will encrypt all data in the API Request.
#define kMoEngageNetworkEncryption NO // YES/NO
/// Encryption Key of type String which will be use to encrypt/decrypt data in Debug mode.
#define kMoEngageNetworkNetworkDebugKey NULL
/// Encryption Key of type String which will be use to encrypt/decrypt data in Release mode
#define kMoEngageNetworkNetworkReleaseKey NULL
/// Jwt Configuration, if true all Network Request will be authenticated with jwt token
#define kMoEngageDataSecurity NO // YES/NO
```
# Unity App Controller Swizzling
There are two approaches using which the SDK can be initialized:
1. **Unity App Controller Subclass:**\
SDK contains the `MoEUnityAppController` class which is the subclass of UnityAppController. Here we get a callback on AppLaunch to initialize MoEngage SDK.
2. **UnityAppController swizzling:**\
Define `kMoEngageUnityControllerSwizzlingEnabled` in the configuration file and set it to `YES` to enable UnityAppController swizzling. Here `application:didfinishLaunchinWithOptions:` method is swizzled to initialize MoEngage SDK.
UnityAppController swizzling (2nd approach) will be required if your project has multiple implementations of UnityAppController subclasses (1st approach), here the subclass defined in the plugin might not work reliably because here only one of the subclasses in the project will get the callbacks.
# Build and Replace
We make use of [CocoaPods](https://cocoapods.org/) for managing native dependencies, therefore make sure the same is installed in your system.
Once required packages are imported go to `File > Build Settings`, switch to iOS platform, and click on `Build`. Select `Replace` in the pop-up. It's necessary to select **Replace** on first-time integration, this is because we will be updating the build settings of the Xcode project for MoEngage SDK and also installing the native dependencies via CocoaPods.
After building the project in Unity Editor, open Unity-iPhone.xcworkspace in Xcode, and you are good to run the Unity-iPhone App.
# SDK Initialization
Source: https://moengage.com/docs/developer-guide/unity-sdk/sdk-integration/sdk-initialization/sdk-initialization
Attach the MoEGameObject script to your Unity scene and configure your MoEngage App ID.
# Unity Initialization
In your Unity project, add an empty game object to the first scene, attach the ***MoEGameObject.cs*** script, and set the ***App ID*** as shown below
\
Now head over to platform-specific docs to set up the project with MoEngage SDK:
* [Android Initialization](https://developers.moengage.com/hc/en-us/articles/4404432245268)
* [iOS Initialization](https://developers.moengage.com/hc/en-us/articles/4404432735636)
# SDK Installation
Source: https://moengage.com/docs/developer-guide/unity-sdk/sdk-integration/sdk-installation/sdk-installation
Download and import the MoEngage Unity package into your project using the Unity Editor.
The MoEngage Unity package requires the application to use Unity Version 2023.1.7f1. Version 2023.1.7f1 is required for the target SDK and Gradle version compatibility.
## External Dependency Manager
The plugin uses the [External Dependency Manager](https://github.com/googlesamples/unity-jar-resolver) by Google for Unity (EDM4U) (formerly Play Services Resolver / Jar Resolver). Make sure to include it in your project before proceeding with the SDK Integration.
## Add MoEngage Package
To integrate the MoEngage Unity SDK, first, download the Unity packages from [here](https://github.com/moengage/MoEngage-Unity-SDK/releases). Then go to Unity Editor, navigate to `Assets > Import Package > Custom Package` , and import the `MoEngage.unitypackage`. Select all the files as shown below and click `Import`:
Once the plugin is integrated, head over to the SDK Initialization doc for setting up the Unity Project.
# Cards
Source: https://moengage.com/docs/developer-guide/web-sdk/cards/cards
Set up MoEngage Cards to deliver targeted inbox and newsfeed messages on your website.
Cards can be used to create targeted or automated App Inbox/NewsFeed messages that can be grouped into various categories and target users with different updates/offers that can stay in the Inbox/Feed over a designated period. For more information, refer to [Cards](https://help.moengage.com/hc/en-us/articles/360045074752-Create-Cards-Campaign).
## SDK Installation
Pass the Cards config in the SDK [initialization](/developer-guide/web-sdk/web-sdk-integration/basic-integration/web-sdk-integration) script as shown below:
```javascript JavaScript lines wrap theme={null}
Moengage = moe({
app_id: moeAppID,
debug_logs: 0,
cards: {
enable: true,
placeholder: '#cardIcon' // CSS selector of inbox icon
}
});
```
`placeholder` is the icon on click of which the inbox will open. Make sure it is provided by you and it exist in the DOM.
## UI Customizations
SDK provides a set of UI customizations that can overwrite the default values. Refer to the code snippet below for the UI customizations.
```javascript JavaScript lines wrap theme={null}
Moengage = moe({
app_id: moeAppID,
debug_logs: 0,
cards: {
enable: true,
placeholder: "#cardIcon", // CSS selector of inbox icon
backgroundColor: "#F6FBFC", // any valid CSS color format
overLayColor: "rgba(0, 0, 0, 0.8)",
fontFaces: [{
family: "Sofia",
url: "https://fonts.gstatic.com/s/sofia/v14/8QIHdirahM3j_su5uI0Orbjl.woff2"
}, {
family: "Audiowide",
url: "https://fonts.gstatic.com/s/audiowide/v16/l7gdbjpo0cum0ckerWCdlg_OMRlABg.woff2"
}],
cardDismiss: {
color: "#db2828", // any valid CSS color format
enable: false // boolean value, which enable the dismiss option.
},
optionButtonColor: "#C4C4C4", // any valid CSS color format
dateTimeColor: "#8E8E8E", // any valid CSS color format
unclickedCardIndicatorColor: "blue", // any valid CSS color format
pinIcon: "https://app-cdn.moengage.com/sdk/pin-icon.svg", // absolute path to the icon image.
refreshIcon: "https://app-cdn.moengage.com/sdk/refresh-icon.svg", // absolute path to the icon image.
navigationBar: {
backgroundColor: "#00237C", // any valid CSS color format
text: "Notifications", // string. eg, Notifications
color: "#fff", // any valid CSS color format
fontSize: "16px", // any valid CSS size format
fontFamily: "", // any font family which is added to the website
},
closeButton: {
webIcon: "https://app-cdn.moengage.com/sdk/cross-icon.svg",
mWebIcon: "https://app-cdn.moengage.com/sdk/cross-icon.svg",
},
tab: {
active: {
color: "#06A6B7",
underlineColor: "#06A6B7",
backgroundColor: "transparent"
},
inactiveTabFontColor: "#7C7C7C",
fontSize: "14px", // any valid CSS size format
fontFamily: "", // any font family which is added to the website
backgroundColor: "#fff", // any valid CSS color format
},
webFloating: {
enable: false, // false by default
icon: "https://app-cdn.moengage.com/sdk/bell-icon.svg", // absolute path to the icon image. by default, our icon will be used.
postion: "0px 10px 40px 0", // need all 4 offset in proper CSS format in the order of top, right, bottom, left.
countBackgroundColor: "#FF5A5F",
countColor: "#fff",
iconBackgroundColor: "#D9DFED",
fontFamily: "Audiowide"
},
mWebFloating: {
enable: false, // false by default
icon: "https://app-cdn.moengage.com/sdk/bell-icon.svg", // absolute path to the icon image. by default, our icon will be used.
postion: "0px 10px 40px 0", // need all 4 offset in proper CSS format in the order of top, right, bottom, left.
countBackgroundColor: "#FF5A5F",
countColor: "#fff",
iconBackgroundColor: "#D9DFED",
fontFamily: "Audiowide"
},
card: {
headerFontSize: "16px",
descriptionFontSize: "14px",
ctaFontSize: "12px",
fontFamily: "inherit",
horizontalRowColor: "#D9DFED"
},
noDataContent: {
img: "https://app-cdn.moengage.com/sdk/cards-no-result.svg",
text: "No notifications to show, check again later.",
}
}
});
```
## APIs
### Unclicked Count
The SDK provides an API to fetch the number of cards that haven't been clicked by the users. To get the count, use the following API.
```javascript JavaScript lines wrap theme={null}
```
### New Card Count
The SDK provides an API to get the new cards for the user on the device. To get the count, use the following API.
```javascript JavaScript lines wrap theme={null}
```
## Callbacks
The SDK provides the following callbacks:
### Inbox Open Callback
To get a callback when the user clicks on the inbox icon and when the inbox is open, register the callback function to the setInboxOpenListener() method as shown below.
```javascript JavaScript lines wrap theme={null}
```
### Inbox Close Callback
To get a callback when the user closes the inbox, register the callback function to the setInboxCloseListener() method as shown below.
```javascript JavaScript lines wrap theme={null}
```
### Card Click Callback
To get a callback when the user clicks on a card, register the callback function to
setCardClickListener() method:
```javascript JavaScript lines wrap theme={null}
```
# Self Handled Cards
Source: https://moengage.com/docs/developer-guide/web-sdk/cards/self-handled-cards
Fetch card campaign data via the MoEngage SDK and build custom card UI on your website.
Self-handled cards allow you to create Card Campaigns on the MoEngage Platform and display the cards anywhere inside the website. SDK provides APIs to fetch campaign data, which you can use to create your view for cards.
## SDK Installation
Pass the Cards config in the SDK [initialization](/developer-guide/web-sdk/web-sdk-integration/basic-integration/web-sdk-integration) script, as shown below.
```javascript JavaScript lines wrap theme={null}
Moengage = moe({
app_id: moeAppID,
debug_logs: 0,
cards: {
enable: true
}
});
```
Cards is a separate module and it gets loaded asynchronously with core SDK module. So it may not be available immediately on the page load.
Please use this event listener and call the Cards API once it has been initialised:
```javascript JavaScript lines wrap theme={null}
window.addEventListener('MOE_LIFECYCLE', event => {
if (event.detail.name === 'CARDS_INITIALIZED') {
// call the cards APIs here
}
});
```
If you are using npm package, then use this helper function:
```javascript JavaScript lines wrap theme={null}
moengage.on_cards_loaded().then(function() {
// call the cards APIs here
})
```
### Notify on Inbox Open
Whenever you open the inbox, you can notify Moengage as shown below to sync the data and track the inbox open event.
```javascript JavaScript lines wrap theme={null}
```
### Fetch Categories
To fetch all the categories for which cards are configured, use the getCardCategories() API.
```javascript JavaScript lines wrap theme={null}
```
Additionally, you can have an **All** category which would be a superset of all the categories. Use the isAllCategoryEnabled() API.
```javascript JavaScript lines wrap theme={null}
```
### Fetch Cards for Categories
To fetch the cards eligible for display for a specific category, use the getCardsForCategory(categoryName) API.
```javascript JavaScript lines wrap theme={null}
```
To fetch all the cards eligible for display irrespective of the category, pass the category 'All' as shown below
```javascript JavaScript lines wrap theme={null}
```
### Fetch Card Info
Instead of using separate APIs to fetch Cards and categories, you can use the \*getCardsInfo(cardID)\*API to fetch all the information in one go.
```javascript JavaScript lines wrap theme={null}
```
### Refresh Cards from the Server
Use the fetchCards() API to refresh cards from the MoEngage server if required.
```javascript JavaScript lines wrap theme={null}
```
### Track Statistics for Cards
Since the UI/display of the cards is controlled by the application, to track the statistics on display and click, we need the application to notify the SDK.
#### Impressions
Call the \*cardShown(cardID)\*API when a specific card is visible on the screen.
```javascript JavaScript lines wrap theme={null}
```
#### Clicks
Whenever a user clicks on a card, call the *cardClicked(cardID, widgetID)* API and pass the card object widget identifier for the UI element clicked.
```javascript JavaScript lines wrap theme={null}
```
#### Delete Card
Call the *deleteCard(cardID)* API to delete a card.
```javascript JavaScript lines wrap theme={null}
```
# Configure Data opt-out in Web SDK
Source: https://moengage.com/docs/developer-guide/web-sdk/data-tracking/configure-data-opt-out-in-web-sdk
Disable user data tracking in the MoEngage Web SDK to comply with GDPR and CCPA regulations.
To comply with privacy regulations such as GDPR and CCPA, your application must provide users with the ability to opt out of data tracking. The MoEngage Web SDK provides APIs to disable user-specific data collection while maintaining core functionality and anonymous analytics.
* By default, data tracking is enabled.
* When a user opts out, the SDK stops collecting personally identifiable information (PII) and behavior-specific data.
## How Data Tracking Opt-out Works
When you disable data tracking, the SDK performs the following actions to ensure compliance and privacy:
* **Data Erasure (Local):** Deletes existing user attributes, events, session information, and batches from local storage.
* **State Persistence:** Maintains the opt-out preference across browser sessions and user logouts.
* **Anonymous Tracking:** Continues to track a limited set of "Permitted Events" (like Web Push subscriptions) without associating them with a specific user identity.
* **Cross-Subdomain Support:** Synchronizes the opt-out state across subdomains (if configured).
**Server Data Notice**
Data erasure occurs only locally within the browser's storage. Disabling data tracking does not retroactively delete historical data that has already been sent to and stored on MoEngage servers.
## Disable Data Tracking
Call the `disableDataTracking()` method when a user rejects tracking cookies or requests to opt out.
```javascript JavaScript lines wrap theme={null}
Moengage.disableDataTracking();
```
### What happens when disabled?
* New custom events and user attributes are not tracked.
* PII (Email, Mobile Number, Name, etc.) is blocked from being sent to the server.
* The SDK logs an error if you attempt to call `disableDataTracking()` when it is already disabled.
* If the SDK itself is disabled via `disableSdk()`, calling `disableDataTracking()` will have no effect.
## Enable Data Tracking
Call the `enableDataTracking()` method when a user provides consent to be tracked.
```javascript JavaScript lines wrap theme={null}
Moengage.enableDataTracking();
```
### Re-identifying Users after Consent
After enabling data tracking, you must call `identifyUser()` to associate the current session and any prior anonymous events with a specific user profile.
```javascript JavaScript lines wrap theme={null}
Moengage.enableDataTracking().then(() = {
// Re-identify user to link anonymous events to the profile
Moengage.identifyUser("USER_UNIQUE_ID");
})
```
## Supported Platforms
The Data Tracking Opt-out feature is currently supported on the following platforms and frameworks:
| Platform / Framework | Support Status |
| ------------------------ | --------------- |
| Native Web SDK | ✅ Supported |
| NPM Module | ✅ Supported |
| Google Tag Manager (GTM) | ✅ Supported |
| Shopify | ✅ Supported |
| Flutter | ✅ Supported |
| Segment / VTEX / AMP | ❌ Not Supported |
## Data Collection Behavior
### Permitted Events
When data tracking is disabled, the SDK tracks standard events anonymously to maintain core functionality. For a full list of these interactions, refer to the [Standard Events documentation](https://help.moengage.com/hc/en-us/articles/207836953-Derived-Events-Attributes#h_01HMRWM2FZRGSVMH3V3KKK6WRV). All standard events are tracked except for custom events and user attributes, which are restricted as listed below.
### Restricted Data (PII)
**Restricted Attributes**
* Personal Identifiers: First Name, Last Name, Full Name.
* Contact Info: Email ID, Mobile Number.
* Demographics: Gender, Birth Date.
* All custom user attributes.
* All custom events.
## Frequently Asked Questions
### Does the opt-out state persist after a user logs out?
Yes. The tracking preference is stored in the browser's storage and persists across app sessions and user logouts to ensure user privacy choices are respected.
### Will I still see page view counts for opted-out users?
Yes. **Viewed Web Page** is a permitted event. However, these views are recorded anonymously and are not linked to a specific user profile or historical data.
### Can I use this alongside disableSdk()?
`disableSdk()` takes precedence. If the SDK is disabled, SDK does not perform any operations. `disableDataTracking()` allows the SDK to remain active for anonymous features while stopping personalized data collection.
# Setting Unique Id for SDK versions below 2.52.2
Source: https://moengage.com/docs/developer-guide/web-sdk/data-tracking/setting-unique-id-for-sdk-versions-below-2-52-2
Set a unique user ID for login and logout in MoEngage Web SDK versions below 2.52.2.
## Implementing Login/Logout
* It's important to set the ID when a user logs into your app.
* This merges the new user with the existing user, if any exists, and will help prevent the creation of unnecessary/stale users.
* Setting the ID is a critical piece to tie a user across devices as well across all platforms (i.e. iOS, Android, Web). Call the login method as soon as the user is logged in. ID can be something like an email ID, a username (unique), or a database ID or any Backend generated ID.
* Do not set this for the user who not logged in.
## Log In
```javascript JavaScript lines wrap theme={null}
Moengage.add_unique_user_id(UNIQUE_ID); // UNIQUE_ID is used to uniquely identify a user.
```
**Warning**
If you do not use the MoEngage logout method and call `Moengage.add_unique_user_id(NEW_UNIQUE_ID)`, then the SDK will trigger MoEngage force-logout. A new user profile will get created with `NEW_UNIQUE_ID` as its ID and the first user profile will receive the logout event. This way of using `Moengage.add_unique_user_id` is NOT recommended as new user creation resets the current user and creates unintended users in our system. You should always explicitly call the MoEngage logout method before calling this method again.
**Critical - Very Important Integration Guideline**
Never use both the login methods - `identifyUser` (login method of SDK versions 2.52.2 onwards) and `add_unique_user_id` in your project. Use only either one of the methods. Using both the methods can lead to inconsistent user profile creation and merging in your MoEngage account.
## Log Out
Logs out the current user.
```javascript JavaScript lines wrap theme={null}
Moengage.destroy_session();
```
## Update User
```javascript JavaScript lines wrap theme={null}
Moengage.update_unique_user_id(NEW_UNIQUE_ID);
```
**Critical**
All the methods mentioned above- `add_unique_user_id`, `destroy_session` and `update_unique_user_id` should be called in proper order. So make sure, you track other attributes after these methods are executed completely. Since it returns a promise, you can use. For example:
```javascript JavaScript lines wrap theme={null}
Moengage.add_unique_user_id(UNIQUE_ID).then(() => {
Moengage.add_mobile('7777777777')
});
```
# Web SDK Data Tracking Introduction
Source: https://moengage.com/docs/developer-guide/web-sdk/data-tracking/web-sdk-data-tracking-introduction
Learn about user attribute and event tracking capabilities in the MoEngage Web SDK.
# Overview
MoEngage Web SDK, by default, tracks information for MoEngage default attributes and events. Use additional tracking for best personalization of the message and advance segmentation. Additional tracking is done either for:
# User Attributes
Persistent forever.
For example, email, first name, last name and so on. For more information, refer to [User Attributes](/developer-guide/web-sdk/data-tracking/web-sdk-user-attributes-tracking).
**Note**
You can not use "moe\_" as a prefix while naming events, event attributes, or user attributes. It is a system prefix and using it might result in periodic blacklisting without prior communication.
# Events
Persistent for 60 days unless otherwise defined in your contract.
For example, Order Successful, Started Application and so on.
For more information on MoEngage tracked attributes and events, refer to [Events and Attributes](https://help.moengage.com/hc/en-us/articles/207836953-Derived-Events-Attributes?_gl=1*1ttwmhc*_ga*MTU4NTM0MzI0NS4xNzI3MTcwMzYy*_ga_SEBHW7YTZ7*czE3NzE4MjEwNDEkbzE1NiRnMSR0MTc3MTgyOTQ1NiRqNCRsMCRoMA..) and [Events Tracking](/developer-guide/web-sdk/data-tracking/web-sdk-events-tracking).
For further assistance, please contact your MoEngage Customer Success Manager (CSM) or the Support team.
# Web SDK Events Tracking
Source: https://moengage.com/docs/developer-guide/web-sdk/data-tracking/web-sdk-events-tracking
Track user actions and event attributes on your website using the MoEngage Web SDK.
* MoEngage highly recommends using the optional step for MoEngage Web SDK integration.
* SDK adheres to the MoEngage FUP policies. For more information, refer to the [Fair Usage Policy](https://help.moengage.com/hc/en-us/articles/24151864954644-Fair-Usage-Policy-FUP#h_01HQSMZVQWT2KYP0PY1P8GQMRM).
## Track Event
Tracking events records the user actions and the action properties. A single user action is recorded with every track\_event call. MoEngage recommends that you make your event names human-readable so that everyone in your team can know what they mean instantly.
You can track an event using track\_event with the event name and the event characteristics such as attributes or properties.
```javascript JavaScript lines wrap theme={null}
Moengage.track_event("EVENT_NAME_1"); // This event has no attributes
// Track events with additional attributes
Moengage.track_event("EVENT_NAME_2", {
"attribute_1": "value_1", // string value
"attribute_2": 2, // numeric value
"attribute_3": 3.4, // numeric value
"attribute_4": new Date(2017, 0, 31), // datetime value. Example value represents 31 January, 2017.
});
```
Add all the additional information which you think would be useful for segmentation while creating campaigns. For example, the following code tracks a purchase event of a product. We are including attributes like amount, quantity, category, which describe the event we are tracking.
```javascript JavaScript lines wrap theme={null}
Moengage.track_event("Purchase", {
"quantity":2,
"product_name":"Ipad mini",
"price": 599.99,
"currency": "USD"
});
```
**Critical**
* Ensure that you are tracking event and user attributes without changing their data types. For instance, in the above purchase event, amount and quantity are tracked in numeric form. MoEngage detects the data type automatically unless you explicitly specify it as a string.
* Having unique timestamps for events is crucial to maintain accurate and reliable data. Please ensure that events do not share the same timestamp down to the millisecond level.
### Event tracking using Google Tag Manager (GTM)
Use the described code in the `Custom HTML Tag` inside GTM. This Tag should be fired once per event and triggered on the elements where you wish to track website events. The event attributes can be picked up from GTM Data Layer.
```JavaScript JavaScript lines wrap theme={null}
```
## Non-Interactive Event
Events that do not affect the session duration calculation in MoEngage Analytics are marked as Non-Interactive events.
The following are considered non-interactive events:
* Do not start a new session, even when the website is in the foreground
* Do not extend the session
* Do not have information on source and session
For example, events that are tracked when the website is in the background, are not initiated by users and hence are marked as non-interactive.
To mark an event as non-interactive send `moe_non_interactive: 1` while tracking the event as described:
```javascript JavaScript lines wrap theme={null}
Moengage.track_event("Content Refreshed", {"NewsCategory": "Politics", "moe_non_interactive": 1})
```
## Callbacks on events tracked by SDK
There are few events which are tracked by SDK automatically for you and if you want to get those, then you can listen to the events as follows:
```JavaScript JavaScript lines wrap theme={null}
window.addEventListener('MOE_AUTOMATED_EVENTS', function (event) {
switch (event.detail.name) {
case 'MOE_WEB_UNSUBSCRIBED':
console.log(event.detail.data); // it contains all the attributes of the event
break;
case 'EVENT_ACTION_WEB_SESSION_START':
console.log(event.detail.data); // it contains all the attributes of the event
break;
}
});
```
### List of events
1. MOE\_WEB\_UNSUBSCRIBED
2. EVENT\_ACTION\_WEB\_SESSION\_START
3. MOE\_PAGE\_VIEWED
4. MOE\_WEB\_OPTIN\_BANNER\_LOAD
5. MOE\_WEB\_OPTIN\_CLOSED
6. MOE\_WEB\_OPTIN\_ACCEPTED
7. MOE\_USER\_SUBSCRIBED
8. MOE\_OPT\_IN\_SHOWN
9. MOE\_OPT\_IN\_ALLOWED
10. MOE\_OPT\_IN\_DISMISSED
11. MOE\_OPT\_IN\_BLOCKED
12. MOE\_LOGOUT
13. MOE\_ONSITE\_MESSAGE\_CLICKED
14. MOE\_ONSITE\_MESSAGE\_SHOWN
15. MOE\_ONSITE\_MESSAGE\_DISMISSED
16. MOE\_ONSITE\_MESSAGE\_AUTO\_DISMISS
## Troubleshooting
### Event is not tracked on redirection when I am using window\.open(..)
In case you are redirecting to another page using `window.open` method and also tracking some event(s) on redirection then you need to wrap the `window.open` in a `setTimeout`. eg-
```javascript JavaScript lines wrap theme={null}
setTimeout(() => window.open(), 0);
```
### Events are not getting tracked when the page URL is very big
URL is tracked by default in all the events as an attribute. But the maximum length of the URL supported is 512 character. If the URL length exceeds that, then the whole events will be dropped.
So make sure the URL length does not exceed 512 characters
### Page Viewed event is not getting tracked on back/forward navigation
Your website might be eligible for bfcache. Back/forward cache (or bfcache) is a browser optimization that enables instant back and forward navigation. bfcache is an in-memory cache that stores a complete snapshot of a page (including the JavaScript heap) as the user is navigating away. Read more about bfcache [here](https://web.dev/articles/bfcache)
Thus the Moengage SDK does not re-initialises again and hence the page viewed events are not tracked.
To include bfcache restores in your pageview count, set listeners for the `pageshow` event and check the `persisted` property.
```javascript JavaScript lines wrap theme={null}
window.addEventListener('pageshow', (event) = {
// Send another pageview if the page is restored from bfcache.
if (event.persisted) {
Moengage.track_page_view();
}
});
```
For further assistance, please contact your MoEngage Customer Success Manager (CSM) or the Support team.
# Web SDK User Attributes Tracking
Source: https://moengage.com/docs/developer-guide/web-sdk/data-tracking/web-sdk-user-attributes-tracking
Track user attributes like email, name, and gender on your website using the MoEngage Web SDK.
MoEngage highly recommends using the optional step for MoEngage Web SDK integration.
User attributes are specific traits of a user such as an email, username, mobile, gender and so on. User Attributes helps target users based on these attributes across devices or installs or to personalize the messages.
## Pre-defined Attributes
Use the following MoEngage methods to make use of the standard user attributes.
```javascript JavaScript lines wrap theme={null}
Moengage.add_first_name("Dominick");
Moengage.add_last_name("Cobb");
Moengage.add_email("dom@level5.com");
Moengage.add_mobile("+12399999999");
Moengage.add_user_name("Dominick (Dom) Cobb"); // Full name for user
Moengage.add_gender("M");
Moengage.add_birthday(new Date(1980, 2, 31));
```
## Custom Attributes
```javascript JavaScript lines wrap theme={null}
// string
Moengage.add_user_attribute("ATTRIBUTE_NAME_1", "value");
// Integer - Numeric
Moengage.add_user_attribute("ATTRIBUTE_NAME_2", 1);
// Double - Numeric
Moengage.add_user_attribute("ATTRIBUTE_NAME_3", 5.99);
// Date
Moengage.add_user_attribute("ATTRIBUTE_NAME_4", new Date(2021, 2, 10));
// Boolean
Moengage.add_user_attribute("ATTRIBUTE_NAME_5", false);
// Arrays can be only in string or in number format.
// Array (all items should be of same data type)
Moengage.add_user_attribute('colors', ['blue', 'green', 'red']);
// Array (all items should be of same data type)
Moengage.add_user_attribute('ids', [77892, 1123, 3311]);
// Object (upto 2 levels and maximum payload size of 150 KB is supported)
// The value of the highest-level key has to be of primitive JavaScript type or Date
Moengage.add_user_attribute('someCustAttr', { 'key1': { 'subKey1': 'someVal1', 'subKey2': true, 'subKey3': 125676, 'subKey4': new Date() }, 'key2': [1, 4, 5, 3] });
```
## User Login and Logout
ID is used to uniquely identify a user within the MoEngage dashboard.
Ensure log in and log out of users are implemented correctly during the visit to your website and users are authenticated.
If the user [log in](#log-in) and [log out](#log-out) is not handled correctly, user data may get corrupted.
When you go live with MoEngage web SDK for the first time, ensure that you are setting the ID of your existing website users on page load.
As soon as the user is authenticated, ensure that the user id is passed on to the MoEngage SDK using the login method. After the user logs out of your app, ensure to call the logout method of MoEngage.
Use the following MoEngage methods on user login, user log out and user update:
### Log In
For SDK versions below 2.52.2 refer to [this document](/developer-guide/web-sdk/data-tracking/Setting-Unique-Id-for-SDK-versions-below-2-52-2).
Please ensure that you are using the latest [integration script](/developer-guide/web-sdk/web-sdk-integration/basic-integration/web-sdk-integration) before using the below MoEngage methods.
```javascript JavaScript lines wrap theme={null}
/** if a single argument is passed into identifyUser method, it will be treated as ID */
Moengage.identifyUser(UNIQUE_ID); // UNIQUE_ID is used to uniquely identify a user
/** if email has been chosen as identity */
Moengage.identifyUser({ u_em: 'emailValue@emailDomain.com' });
/** if mobile has been chosen as identity */
Moengage.identifyUser({ u_mb: '7777777777' });
/** you can set two or more identities at the same time */
Moengage.identifyUser({ u_em: 'emailValue@emailDomain.com', u_mb: '7777777777', uid: 'unique_id_value' });
```
**Information**
Updates are made to SDK functions to improve user identification and session management.
* **Forced Logout**: The MoEngage SDK no longer automatically logs out the previous user when a new user is detected on the device. Logout should now be explicitly called for workspaces enabled with Identity resolution to avoid data corruption.
* **SetUniqueID**: *IdentifyUser* function supports multiple identifiers, which replaces the need of using *SetUniqueID* function for user identification. Note that *SetUniqueID* is marked for removal in the future releases of SDK versions - it is important to use *identifyUser* instead especially if you are using Identity resolution in your workspace.
* **SetAlias**: For workspaces with the Identity resolution feature enabled, MoEngage SDK stores the previous identifier values. When *IdentifyUser* function is used to track the new identifier values, MoEngage SDK detects the change in identifier value and reports accordingly.
* If you call the *IdentifyUser* function without logging out, then the existing logged-in user's ID is updated.
Refer to our help [document](https://help.moengage.com/hc/en-us/articles/24050999467284-User-Identity-Management) to learn more about the feature.
Here, `u_em`, `u_mb`, `uid` are standard user attributes. Please refer to the below table to identify user with standard user attributes:
| User Attribute Name | Key name to be used in identifyUser method |
| :----------------------- | :----------------------------------------- |
| ID | uid |
| Email (Standard) | u\_em |
| Gender | u\_gd |
| Birthday | u\_bd |
| Name | u\_n |
| First Name | u\_fn |
| Last Name | u\_ln |
| Mobile Number (Standard) | u\_mb |
You can identify a user with custom user attributes as well if the same have been chosen as identities in your MoEngage dashboard.
```javascript JavaScript lines wrap theme={null}
/** replace custom_attribute_name with the actual name of your custom user attribute and attributeValue with the actual value you want to assign to the attribute */
Moengage.identifyUser({ custom_attribute_name: 'attributeValue' });
/** you can set two or more identities at the same time */
Moengage.identifyUser({ cust_attr_1: 'value1', cust_attr_2: 'value2' });
/** you can set custom user identity and standard user identity at the same time */
Moengage.identifyUser({ cust_attr_1: 'value1', cust_attr_2: 'value2', u_em: 'emailValue@emailDomain.com' });
```
If you want to retrieve the current state of identities set for the user, you can use the below method:
```javascript JavaScript lines wrap theme={null}
Moengage.getUserIdentities();
/**
returns an object with the user's current set identities and their values:
{ u_em: 'emailValue@emailDomain.com', u_mb: '7777777777', uid: 'valueOfID' }
*/
```
**Critical - Very Important Integration Guideline**
Never use both the login methods - `identifyUser` and `add_unique_user_id` (login method of SDK versions below 2.52.2) in your project. Use only either one of the methods. Using both the methods can lead to inconsistent user profile creation and merging in your MoEngage account.
In order the get the value of a tracked user attributes, you can use the below method:
```javascript JavaScript lines wrap theme={null}
Moengage.getUserAttribute(ATTRIBUTE_NAME);
/**
Pass the attribute name as the paramaeter and it will return the value of the attribute if present.
Note: This method only returns locally tracked user attributes. if the user logs out and then logs in, the previously tracked attributes will not be fetched using this method.
*/
```
### Log Out
Logs out the current user.
```javascript JavaScript lines wrap theme={null}
Moengage.destroy_session();
```
### Update User
```javascript JavaScript lines wrap theme={null}
/** Set the ID for the first time */
Moengage.identifyUser(UNIQUE_ID);
/** Update the ID */
Moengage.identifyUser(NEW_UNIQUE_ID);
/** Set the identities for the first time */
Moengage.identifyUser({ uid: UNIQUE_ID, u_em: 'emailValue@emailDomain.com', u_mb: '7777777777' });
/** Update the identities - you can update one or more identities. */
Moengage.identifyUser({ u_em: 'updatedValue@emailDomain.com', u_mb: '8888888888' });
```
**Critical**
`identifyUser` and `destroy_session` methods should be called in proper order. So make sure, you track other attributes after these methods are executed completely. Since these return promise, you can track data like this:
```javascript JavaScript lines wrap theme={null}
Moengage.identifyUser({ u_em: 'emailValue@emailDomain.com', uid: UNIQUE_ID }).then(() => {
Moengage.add_mobile('7777777777')
});
```
## Track User Attributes
Ensure that you are tracking user attributes in the following cases:
1. When a new attribute is set for a user. For example, set the Email Id or Mobile No. attribute for the user after a user logs in or signs up on the website.
2. When the value of an existing attribute is updated.
3. When you go live for the first time with MoEngage web SDK integration, ensure that you are passing the user attributes set for your existing website users after page load (if they are not already sent to MoEngage).
4. For more information on supported data types and data tracking policies, please refer to [Data Tracking Policies](https://help.moengage.com/hc/en-us/articles/360037314991#h_01H9QNZ61VNHSMFQC28MAZJXS9).
Make sure that you are not using a single unique id for all the users, this is possible only when the unique id value is hardcoded, instead of retrieving from your servers.
## Attribute tracking via Google Tag Manager (GTM)
You can follow the documentation at [Google Tag Manager(GTM)](https://partners.moengage.com/hc/en-us/articles/7191684558612) to track attribute via GTM.
## Tracking at the time of Redirection
In case of redirection to another page immediately after tracking attribute or events, make sure that the tracking is completed and then you redirect.
```javascript JavaScript lines wrap theme={null}
Moengage.identifyUser({ u_em: 'emailValue@emailDomain.com', uid: UNIQUE_ID }).then(() => {
window.open('[https://www.moengage.com](https://www.moengage.com)')
});
```
If you cannot wait for the tracking to complete and need to redirect immediately, then it is suggested to track the data on the next page after redirection.
## User Attribute Caching
Duplicate User Attributes won't be tracked for 6 hours.
For more information about the default attributes collected by MoEngage SDK, refer to [Web SDK Data Collection](https://help.moengage.com/hc/en-us/articles/360042954831-Default-Web-SDK-).
For further assistance, please contact your MoEngage Customer Success Manager (CSM) or the Support team.
# Web Push Notifications Integration Validation
Source: https://moengage.com/docs/developer-guide/web-sdk/integration-validation/web-push-notifications-integration-validation
Validate your MoEngage Web Push integration by verifying token generation, delivery, and stats.
Web Push Notifications Integration validation is performed manually to verify if the Push notifications are working.
## Validation Procedure
The validation procedure contains the following steps
1. Push Token Generation
2. Push notification received on the device
3. Notification Redirection
4. Notification Statistics
### Push Token Generation
1. On your profile page, the Web push icon has to be green.
2. You can also check this by installing the MoEngage extension on your browser ([https://chrome.google.com/webstore/detail/moengage-sdk/dhggnkfnnoebbfofpimfehcklnekmbgi)](https://chrome.google.com/webstore/detail/moengage-sdk/dhggnkfnnoebbfofpimfehcklnekmbgi\)!\[Placeholder_Image)
### Push notification received on the device
1. Create a general Push campaign on the Dashboard for your device
2. Test the notification from the test option at the 3rd stage of creation.
3. If you get a successful response create the campaign. If failed, check for the failure reasons.
### Notification Redirection
Provide the redirection URL while creating the campaign. And once the message is received click on it and check if it is redirecting you to the URL.
### Notification Statistics
* Once the campaign is sent out, the campaign stats should show the impressions and clicks.
## Validation Success Criteria
1. Push token has to be generated for the users
2. Notification should be displayed correctly
3. The redirection should work as expected
4. The Impressions and clicks have to be captured.
## Troubleshooting
1. If tokens are not generated correctly, the reachable user base will be less than the actual users. For more information about fixing token-related issue, refer to [Configuring Web Push Settings](https://help.moengage.com/hc/en-us/articles/210224063-Configure-Web-Push-Settings).
2. Incorrect Redirection will lead to confusion/miss in opportunities.
3. If the clicks and impressions are not recorded, we cannot understand the impact of the campaign.\
For more information about fixing impressions and click-tracking-related issue, refer to [Configuring Web Push Settings](https://help.moengage.com/hc/en-us/articles/210224063-Configure-Web-Push-Settings).
MoEngage recommends download and installs the Chrome Extension for integration validation.
### Have difficulties while integrating our Web SDK?
You don't have to wait for our awesome customer support to get back to you. Try our MoEngage Assist Chrome Extension. Here is a gist of what our assist can do -
1. It will be active only on those pages where our SDK is integrated
2. Gives basic information of all the configurations
3. Can forcefully fetch the configurations (instead of waiting for 24 hours to refresh)
4. Shows any errors in serviceworker integration
5. Shows the list of events and attributes tracked
6. Informs whether the user is created/subscribed or not.
7. Can track any events
8. Can add any attributes
9. Informs whether Onsite and Web Personalization is enabled or not
10. Shows the list of Onsite Campaigns and trigger condition in a nice readable format
11. Shows the list of Web Personalization Experiences and trigger condition in a nice readable format
12. Can forcefully fetch the Onsite and Web Personalization campaigns (instead of waiting for 15min to refresh)
# Configure and Integrate On-site Messaging
Source: https://moengage.com/docs/developer-guide/web-sdk/onsite-messaging/configure-and-integrate-on-site-messaging
Configure on-site messaging campaigns to show personalized pop-ups and banners on your website.
On-site Messaging Campaigns allow you to show personalized pop-ups and non-intrusive banners on your website.
Web SDK integration for On-site Messaging will automatically start working on all the pages where the web SDK is integrated.
For more information, refer to [Web SDK Integration](/developer-guide/web-sdk/web-sdk-integration/basic-integration/web-sdk-integration).
## Disabling On-site Messaging
Optional step for On-Site messaging
If you want to disable On-site Messaging on a few pages or all pages of your website, you need to add `disable_onsite: true` on the pages wherever MoEngage Web SDK is active as described:
```javascript JavaScript lines wrap theme={null}
Moengage = moe({
app_id: "XXXXXXXXXXXX",
debug_logs: 0,
disable_onsite: true
});
```
## Callback to On-site messaging events
```javascript JavaScript lines wrap theme={null}
window.addEventListener('MOE_AUTOMATED_EVENTS', function (event) {
if (event.detail.name === 'MOE_ONSITE_MESSAGE_SHOWN' && event.detail.data && event.detail.data.length) {
//do some processing on event.detail.data
}
});
```
In the above example, we have `event.detail.name` = `'MOE_ONSITE_MESSAGE_SHOWN'`. Similarly, we provide callbacks to other On-site messaging events
| event.detail.name | description |
| ----------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| MOE\_ONSITE\_MESSAGE\_SHOWN | On-site message is shown to the user |
| MOE\_ONSITE\_MESSAGE\_CLICKED | User clicks on the element on which `moe-inapp-click` class is present |
| MOE\_ONSITE\_MESSAGE\_DISMISSED | User clicks on the element on which `moe-inapp-close` class is present |
| MOE\_ONSITE\_MESSAGE\_AUTO\_DISMISS | The On-site message is auto-closed after the time configured while creating the On-site messaging campaign |
Here is a sample of `event.detail.data` when `event.detail.name` = `'MOE_ONSITE_MESSAGE_SHOWN'`
```javascript JSON lines wrap theme={null}
[
{
"key": "campaign_id",
"value": < the campaign ID >
},
{
"key": "campaign_name",
"value": < the campaign name >
},
{
"key": "type",
"value": "onsite" //this is fixed value
},
{
"key": "templateType",
"value": "POP_UP" //just an example, the templateType can be POP_UP, SELF_HANDLED or BANNER according to the type of template you had chosen for your campaign
},
{
"key": "cid",
"value": "643e2a69dcb2c753d3a1b8a3_F_T_ON_AB_1_P_0_L_0" //just an example, this is an extension of the campaign ID
},
{
"key": "moe_locale_name",
"value": "Default" //just an example
},
{
"key": "moe_locale_id",
"value": "0" //just an example
},
{
"key": "moe_variation_id",
"value": "1" //just an example
},
{
"key": "moe_logged_in_status",
"value": false //just an example, tells us if the user is a logged-in user
},
{
"key": "moe_first_visit",
"value": true //just an example
},
{
"key": "URL",
"value": < the url of the page on which the On-site message is shown >
}
]
```
`event.detail.data` of other On-site messaging events (eg: for `MOE_ONSITE_MESSAGE_DISMISSED`) will have similar (not identical) payload. You can check the data by logging it to the console: `console.log(event.detail.data)`
## Troubleshooting
### Sticky Banner type campaign is overlapping the website header.
Sticky banner type campaign has `fixed` position with `top: 0`. So if your website also has any fixed position element with `top: 0`, then it will overlap. This is the tech limitation and should be handled by your end.
Solution:
You can update the position of you fixed position element as soon as the OSM template is displayed from Moengage. Use this:
```javascript JavaScript lines wrap theme={null}
window.addEventListener('MOE_AUTOMATED_EVENTS', function (event) {
if (event.detail.name === 'MOE_ONSITE_MESSAGE_SHOWN' && event.detail.data && event.detail.data.length) {
const campaign = event.detail.data.find(item => item.key === "campaign_id");
if (campaign && campaign.value === < your campaign ID > ) {
//perform your action here
}
}
});
```
### On-site messaging campaign is not displayed.
Verify the following:
1. Check if the Trigger Action condition is matching or not
2. If you have Selected Pages for onsite messaging, then check whether the URL is matching or not
3. Check the segmentation of the Audience is matching or not.
4. Check the platform (Web or Mobile Web) is appropriately selected.
### On-site messaging test campaign is not working
Moengage Web SDK uses window\.opener.postMessage to communicate between the Moengage dashboard and your website, in order to show the test OSM campaign.
However, it may be that the window\.opener is blocked between different origin in your website. Please check whether `Cross-Origin-Opener-Policy': 'same-origin'` header is added in your website.
If the above header exist in your website, then the test campaign will not work. You can either remove this and test or create a live campaign and target yourself using segmentation.
For further assistance, please contact your MoEngage Customer Success Manager (CSM) or the Support team.
# Self Handled On-Site Messaging
Source: https://moengage.com/docs/developer-guide/web-sdk/onsite-messaging/self-handled-on-site-messaging
Receive on-site messaging campaign data as JSON and build custom UI for your website.
## Overview
Self-Handled On-site Messaging (OSM) is a powerful feature that gives developers the flexibility to receive campaign data directly as a JSON payload. Instead of having the MoEngage SDK render a predefined template, this approach allows your application to build and display a custom UI that seamlessly integrates with your website's native design and user experience.\
This method is ideal for creating highly customized, dynamic, and deeply integrated on-site messages.
You must use the MoEngage Web SDK version *2.55.0* or later.
## Receive Campaign Data
To receive campaign data, you must register a callback function. The MoEngage SDK executes this function when the trigger conditions for a Self-Handled OSM campaign are met.
### *Moengage.onsite.getSelfHandledOSM(callbackFunction)*
This method registers a listener for Self-Handled OSM campaigns. MoEngage recommends calling this method on page load to ensure the listener is active and ready to receive data.
Example Implementation:
```javascript JavaScript lines wrap theme={null}
Moengage.onsite.getSelfHandledOSM(function(fullCampaignData) {
// This callback function is the entry point for handling campaign data.
console.log("Received Self-Handled OSM Data:", fullCampaignData);
// Proceed with custom UI rendering and event tracking.
});
```
## Understand the Campaign Data Payload
When a campaign triggers your registered callback, the function receives a `fullCampaignData` object containing all the necessary information about the campaign.
Example `fullCampaignData` Payload:
```javascript JavaScript lines wrap theme={null}
[{
"campaignId": "000000000000000000000001",
"campaignName": "Holiday Sale Banner",
"expiryTime": "2025-12-31T23:59:59.000Z",
"updatedTime": "2025-10-06T10:30:00.000Z",
"status": "ACTIVE",
"jsonPayload": "{\"title\":\"Holiday Sale!\",\"message\":\"Get up to 50% off all items.\"}",
"dismissInterval": 86400,
"context": {
"campaign_name": "Holiday Sale Banner",
"cid": "000000000000000000000001_v2",
"moe_locale_id": "eng-us",
"moe_locale_name": "English (US)",
"moe_variation_id": "variation_b_12345"
},
"urlFilters": null
}]
```
### Payload Fields
| Field | Type | Description |
| --------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| campaignId | String | The unique identifier for the campaign. |
| campaignName | String | The name of the campaign as defined in the MoEngage dashboard. |
| expiryTime | String | The expiry time of the campaign. |
| updatedTime | String | The time when the campaign was updated. |
| status | String | The campaign's current status. It will always be ACTIVE. |
| jsonPayload | String | A stringified JSON object containing the custom data for your UI. Parse this string to access its contents. |
| dismissInterval | Number | Specifies the time in seconds before the campaign can be automatically dismissed. The default value is 86400 (24 hours). |
| context | Object | An object containing metadata required for accurate campaign tracking. You must include this object when calling the tracking methods. |
| urlFilters | Object | Defines URL-based targeting rules for the campaign. Developers must implement logic to check whether the current page URL matches the defined targeting rules and display the campaign only when a match is found. If null, no URL-specific targeting applies. |
Example `urlFilters` Object
The `urlFilters` object defines the logic that determines on which pages a campaign can appear. The example below shows a configuration that displays the campaign when the URL contains either "loc" or "hos".
```javascript JavaScript lines wrap theme={null}
"urlFilters": {
"included_filters": {
"filters": [
{
"executed": true,
"execution": {
"count": 1,
"type": "atleast"
},
"action_name": "MOE_PAGE_URL_EVENT",
"attributes": {
"filter_operator": "or",
"filters": [
{
"name": "URL",
"data_type": "string",
"operator": "containsInTheFollowing",
"value": [
"loc"
],
"value1": "",
"negate": false,
"case_sensitive": false,
"array_filter_type": "any_of"
},
{
"name": "URL",
"data_type": "string",
"operator": "containsInTheFollowing",
"value": [
"hos"
],
"value1": "",
"negate": false,
"case_sensitive": false,
"array_filter_type": "any_of"
}
]
},
"filter_type": "actions"
}
],
"filter_operator": "or"
}
}
```
## Campaign Delivery Logic and Best Practices
When an event is triggered, MoEngage evaluates all eligible campaigns and selects a single campaign to deliver.
### Campaign Selection Algorithm:
* **Filtering**: MoEngage filters campaigns based on user eligibility and targeting criteria.
* **Exclusion**: MoEngage removes ineligible campaigns based on rules like frequency capping, delays, and expiration status.
* **Prioritization**: MoEngage sorts the remaining campaigns by priority (P0 is the highest).
* **Tie-Breaking**: If multiple campaigns share the highest priority, MoEngage selects the one with the most recent "last updated" timestamp.
Your `getSelfHandledOSM` callback receives only the single winning campaign.
### Best Practices for Campaign Organization:
To ensure you show the correct campaign in the right context, organize your campaigns with clear priorities.
* **Homepage Context**: Campaign A (P0), Campaign B (P1)
* **Product Page Context**: Campaign C (P0), Campaign D (P1)
* **Checkout Context**: Campaign E (P0)
## Track Campaign Statistics
Because your application controls the UI, you are responsible for notifying the SDK of user interactions. This step is essential for accurate analytics.
| Method | Description |
| ------------------------------------------ | ----------------------------------------------------------------------- |
| Moengage.onsite.selfHandledShown(data) | Call this method after the message is rendered and visible to the user. |
| Moengage.onsite.selfHandledClicked(data) | Call this method when the user clicks on the message. |
| Moengage.onsite.selfHandledDismissed(data) | Call this method when the user dismisses the message. |
### Construct the Tracking Data Object
The *data* object passed to the tracking methods is not the entire `fullCampaignData` object. You must construct a new, specific object for tracking.
Required `trackingData` Format:
```javascript JavaScript lines wrap theme={null}
const trackingData = {
campaignId: fullCampaignData.campaignId,
campaignName: fullCampaignData.campaignName,
context: fullCampaignData.context // Pass the context object exactly as received.
};
```
## Code Implementation Example
This example demonstrates the core logic for receiving data and preparing it for the tracking methods.
```javascript JavaScript lines wrap theme={null}
// Register the callback function to listen for campaigns.
Moengage.onsite.getSelfHandledOSM(function(fullCampaignData) {
console.log("Full campaign data received:", fullCampaignData);
var firstCampaignData = fullCampaignData[0];
// Construct the specific object required for tracking events.
const trackingData = {
campaignId: firstCampaignData.campaignId,
campaignName: firstCampaignData.campaignName,
context: firstCampaignData.context
};
// --- Example Tracking Calls ---
// Call this once your custom UI is rendered and visible.
Moengage.onsite.selfHandledShown(trackingData);
// In your button's click handler, call this.
// myButton.addEventListener('click', () => {
// Moengage.onsite.selfHandledClicked(trackingData);
// });
// In your dismiss element's click handler, call this.
// myDismissButton.addEventListener('click', () => {
// Moengage.onsite.selfHandledDismissed(trackingData);
// });
});
```
## Troubleshooting
If your `Moengage.onsite.getSelfHandledOSM` callback function is not being triggered, we recommend checking the following common issues:
* **SDK Initialization**: Ensure you call `getSelfHandledOSM()` only after the MoEngage SDK is successfully initialized. Calling this method too early in the page load sequence can prevent the callback from registering correctly.
* **Correct Method**: Verify you are using the `Moengage.onsite.getSelfHandledOSM()`method. Ensure you are not accidentally calling a method from a different module.
* **SDK Version Compatibility**: Check that your Web SDK version meets the minimum requirement specified in the Prerequisites.
* **Browser Console Errors**: Open the developer console in your browser and check for any JavaScript errors originating from the MoEngage SDK that could disrupt its operation.
# Configure and Integrate AMP Event Analytics
Source: https://moengage.com/docs/developer-guide/web-sdk/other-supported-web-sdk-integration/configure-and-integrate-amp-event-analytics
Track user attributes and events on your AMP pages using the MoEngage AMP analytics plugin.
MoEngage AMP event analytics plugin helps in track user attributes and events, and run third-party javascript. MoEngage AMP event analytics plugin ensures to address the differences in AMP pages and HTML page restriction for tracking user attributes and events.
The MoEngage AMP event analytics plugin is different from the AMP analytics module.
To add event tracking and user attribute tracking to your AMP pages follow these steps-
## Add AMP Analytics Script
Ensure to include the script in all of your AMP pages in the `` section of your .amp file where you want to use AMP analytics and track user attributes and events.
```HTML HTML lines wrap theme={null}
```
### Add Anywhere in your HTML
```HTML HTML lines wrap theme={null}
```
Note
Ensure to replace Your\_Workspace\_ID with the actual Workspace Id from MoEngage Dashboard -> Settings -> App -> General Settings
For dataCenter, please contact our support team to know more.
Note
To redirect data to test environment, append '\_DEBUG' to appId. For example, if your appId is \
YOUR\_WORKSPACE\_ID then for test environment, it would be YOUR\_WORKSPACE\_ID\_DEBUG
## Tracking Users
All the users visiting your AMP pages will be tracked automatically once you followed the above steps.\
But these users will be anonymous users by default.\
However, if any user of your website who visited your normal HTML pages earlier and has not deleted their cookies, will be treated as the same user in AMP pages also.
## Tracking Events
Page Viewed event is tracked by default if you followed the above steps.\
However with AMP framework limitations on event tracking, only a few kinds of events can be tracked such as `Page Viewed`, `Element Clicked`, `Page Scroll`.
For more information on the list of events, refer to [AMP Analytics Examples](https://amp.dev/documentation/examples/components/amp-analytics/).
### Example 1: Element Click Event
You can track a Click Event when an HTML element with id `test` is clicked as described:
```HTML HTML lines wrap theme={null}
```
| Parameter | Description |
| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `on` | Type of event |
| `selector` | standard CSS selector |
| `request` | Should always be an event |
| `a` | Event attributes. In this example, the `title` is an attribute. Verify the change in the variable `title` using `data-vars-title` from the button element. |
| `e` | Event name |
### Example 2: Page Scroll Event
```HTML HTML lines wrap theme={null}
```
The scroll event needs `scrollSpec` object, that contains `verticalBoundaries` and `horizontalBoundaries`. At least one of the two properties is required for a scroll event to fire. The values for both of the properties should be arrays of numbers containing the boundaries on which a scroll event is generated. For instance, in the following code snippet, the scroll event will be fired when the page is scrolled vertically by 25%, 50% and 90%. The attributes sent here is `scrolledUpto` which holds an inbuilt variable `scrollTop` that provides the number of pixels that the user has scrolled from the top.
For more information about the list of all supported variables, refer to [Supported Variables](https://github.com/ampproject/amphtml/blob/main/docs/spec/amp-var-substitutions.md).
### Example 3: Form Submit Event
```HTML HTML lines wrap theme={null}
```
In the above example, we are setting the id of the form as the selector value (**#testForm**). Inside "extraUrlParams", "e" is the event name and "a" contains the key and the value which we want to track for this event.
## Tracking User Attributes
Important
If any user attribute is configured as an identity for your account, then track it as part of [login](#Tracking-User-Login-and-Logout) instead of simply tracking it as a user attribute as it is shown in this section. Refer to [this document](https://help.moengage.com/hc/en-us/articles/24050999467284-Unified-Identity-Identity-Resolution) to learn more.
You can track user attributes using the "EVENT\_ACTION\_USER\_ATTRIBUTE" event. For example, you have this button on your website:
```HTML HTML lines theme={null}
```
Then, track the first name (considering it to be the user's first name) like this:
```HTML HTML lines wrap theme={null}
```
Similarly, to track the user's email upon clicking the below button
```HTML HTML lines theme={null}
```
```HTML HTML lines wrap theme={null}
```
In the same way, you can track other **pre-defined user attributes**
```HTML HTML lines wrap theme={null}
```
```HTML HTML lines wrap theme={null}
```
Here, USER\_ATTRIBUTE\_NAME has to be replaced with one of the following
```javascript JavaScript lines wrap theme={null}
USER_ATTRIBUTE_USER_EMAIL //for user email - value needs to be string, eg: "dom@level5.com"
USER_ATTRIBUTE_USER_NAME //for user name - value needs to be string, eg: "Dominick (Dom) Cobb"
USER_ATTRIBUTE_USER_FIRST_NAME //for user first name - value needs to be string, eg: "Dominick"
USER_ATTRIBUTE_USER_LAST_NAME //for user last name - value needs to be string, eg: "Cobb"
USER_ATTRIBUTE_USER_MOBILE //for user mobile - value needs to be string, eg: "+12399999999"
USER_ATTRIBUTE_USER_GENDER //for user gender - value needs to be string, eg: "M"
USER_ATTRIBUTE_USER_BDAY //for user birthday - value needs to be in date format, eg: new Date(1980, 2, 31)
```
To track a **custom user attribute**, in place of USER\_ATTRIBUTE\_NAME you have to use your own custom attribute name. For example-
```HTML HTML lines wrap theme={null}
```
In the above example, we are tracking a custom attribute named "colors". This attribute's value is an array- `["blue","green","red"]`
## Tracking User Login and Logout
[Previous way of logging-in users](/developer-guide/web-sdk/other-supported-web-sdk-integration/User-Login-in-AMP-Older-Proces) has been changed. The below method follows the User Identity Resolution feature of MoEngage. [Learn More](https://help.moengage.com/hc/en-us/articles/24050999467284-Unified-Identity-Identity-Resolution).
Ensure log in and log out of users are implemented correctly during the visit to your website and users are authenticated.
Important
If the user log in and log out is not handled correctly, user data may get corrupted. Refer [this section](/developer-guide/web-sdk/data-tracking/web-sdk-user-attributes-tracking#User-Login-and-Logout) for more details.
### Track Login
```HTML HTML lines wrap theme={null}
```
Here, we want to track ID "someUniqueId" and Email "[emailValue@emailDomain.com](mailto:emailValue@emailDomain.com)" as the identities for the user.
Important
If you are setting the ID, make sure to add/update its value in both `identifiers` -> `moe_user_id` as well as inside `identifiers` -> `user_identities`
```html HTML lines wrap theme={null}
```
Here, `uid` is ID and `u_em` is Email (Standard) attributes. Please refer to the below table for key names which need to be used to set standard user attributes as identities.
| User Attribute Name | Key name to be used in user\_identities |
| ------------------------ | --------------------------------------- |
| ID | uid |
| Email (Standard) | u\_em |
| Gender | u\_gd |
| Birthday | u\_bd |
| Name | u\_n |
| First Name | u\_fn |
| Last Name | u\_ln |
| Mobile Number (Standard) | u\_mb |
If we want to identify the user with just mobile number (for example)-
```HTML HTML lines wrap theme={null}
```
```html HTML lines wrap theme={null}
```
Note
Here, we do not have to send the value of mobile number in `identifiers` -> `moe_user_id` as Mobile and ID are two different attributes of a user. Only while adding/updating ID, the value of the ID has to be sent in `moe_user_id` as well as in `user_identities`.
Important
After tracking the login, all further attributes and events tracking should have the "identifiers" object defined inside the tracking code (with the "moe\_user\_id" and/or "user\_identities") as above, until logout event is performed. Otherwise, that attribute or event tracking will not be associated with this logged-in user in your MoEngage dashboard.
For example, if we want to track an event after identities have been set for the user-
```html HTML wrap theme={null}
```
```html HTML lines wrap theme={null}
```
### Track Identities Update
When updating the value of an identity, send the changed identities in `identifiers` -> `previous_identities`.
For example, let's assume you first set ID and Email as identities of the user.
```HTML HTML lines wrap theme={null}
```
```html HTML lines wrap theme={null}
```
Now, let's say you want to update the ID of the user.
```HTML HTML lines wrap theme={null}
```
```HTML HTML lines wrap theme={null}
```
Note
In the above example, we updated ID. You can update more than one identities but you have to mandatorily send all the changing identities in `previous_identities`.
### Track Logout
```HTML HTML lines wrap theme={null}
```
```html HTML lines wrap theme={null}
```
Important
After performing the above Moengage logout event, do NOT send "identifiers" with any further tracking code. Because the user had logged-out and further attribute/event tracking must not be associated with this user.
# Configure and Integrate AMP Web Push
Source: https://moengage.com/docs/developer-guide/web-sdk/other-supported-web-sdk-integration/configure-and-integrate-amp-web-push
Enable web push notifications on your AMP pages using the MoEngage AMP Web Push integration.
**AMP Web Push Integration Prerequisites**
1. Ensure that AMP analytics is integrated before integrating AMP Web Push.
2. Ensure that AMP analytics is integrated before integrating AMP Web Push.
3. MoEngage AMP Web Push Integration does not, by default, track the MoEngage default user attributes and events.
## AMP Web Push
Web Push Notification does not work by using the MoEngage Web SDK and serviceworker.js.\
Google has recently published a separate plugin to support the integration that enables News Publishers, Bloggers, or anyone who uses AMP to deliver their webpages quickly by encouraging users to subscribe using Push Notification.
Only Android devices are supported.
Follow these steps to integrate AMP Web Push:
## Add AMP Web Push script
Add this line in the `` section of your .amp file where you want to use Web Push.
```HTML HTML lines wrap theme={null}
```
## Add Helper files
Download the files corresponding to the dashboard you are using and ensure the files are available in the root directory of your website. Right-click and click **Save Link as...** to save the files:
| Dashboard host | Files |
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| dashboard-01.moengage.com | 1. [amp-helper-frame.html](https://cdn.moengage.com/release/dc_1/amp-helper-frame.html) 2. [amp-permission-dialog.html](https://cdn.moengage.com/release/dc_1/amp-permission-dialog.html) 3. [serviceworker\_amp.js](https://cdn.moengage.com/release/dc_1/serviceworker_amp.js) |
| dashboard-02.moengage.com | 1. [amp-helper-frame.html](https://cdn.moengage.com/release/dc_2/amp-helper-frame.html) 2. [amp-permission-dialog.html](https://cdn.moengage.com/release/dc_3/amp-permission-dialog.html) 3. [serviceworker\_amp.js](https://cdn.moengage.com/release/dc_3/serviceworker_amp.js) |
| dashboard-03.moengage.com | 1. [amp-helper-frame.html](https://cdn.moengage.com/release/dc_3/amp-helper-frame.html) 2. [amp-permission-dialog.html](https://cdn.moengage.com/release/dc_3/amp-permission-dialog.html) 3. [serviceworker\_amp.js](https://cdn.moengage.com/release/dc_3/serviceworker_amp.js) |
| dashboard-04.moengage.com | 1. [amp-helper-frame.html](https://cdn.moengage.com/release/dc_4/amp-helper-frame.html) 2. [amp-permission-dialog.html](https://cdn.moengage.com/release/dc_4/amp-permission-dialog.html) 3. [serviceworker\_amp.js](https://cdn.moengage.com/release/dc_4/serviceworker_amp.js) |
## Add Code
Add the following code inside `` tag:
```HTML HTML lines wrap theme={null}
```
Replace the following:
* DOMAIN.COM with your actual domain.
* WORKSPACE\_ID with your Workspace ID available at MoEngage Dashboard > Settings > General.
Ensure all files are available at the same source path and suffixed with HTTPS.
## Add the Subscribe or Unsubscribe Buttons
Subscribe / Unsubscribe buttons or Amp Web Push Widgets are needed to subscribe or unsubscribe the user from AMP Web Push Notifications.
The following code adds the subscribe or unsubscribe buttons:
```HTML HTML lines wrap theme={null}
{/* A subscription widget */}
{/* An unsubscription widget */}