> Synerise Documentation — Mobile SDK (Part 2 of 2)
>
> This is part 2 of 2 of the "Mobile SDK" section. To reconstruct the full section, fetch all 2 parts in order (part 1, part 2, …) and concatenate them. Each article begins with a top-level "# " heading. The manifest listing all sections is at https://hub.synerise.com/llms-full.txt
# Event tracking
## Overview
---
Everything your customers do in your mobile application is recorded in the system in real time, queued and automatically sent in batches to Synerise. Information such as the source of the visit, the URL address they have visited, and the chain of actions that followed are saved in Synerise as events and their parameters.
The scope of information gathered about events is wide. Synerise collects predefined event parameters which can be extended according to the preferences and needs of the Synerise customers.
The basic information about the tracked events includes:
- **Action name** – an indicator of the activity type, such as `screen.view`
- **Label** – human-readable information about the activity, such as the page title. Must be at least one character.
This is a deprecated field. It's not saved in the database. so it can't be used in Decision Hub or Automation Hub.
- **Time** – the time when the event occurred
- **Customer identification** – an identifier of the customer who performed the activity
- **Parameters** – additional parameters, depending on the type of the event
Click here to see example of an event
Some events are predefined, meaning they have a fixed set of fields that must be sent. For example, a `product.view` event must include the product ID.
You can [enrich events with data from catalogs in Synerise](/docs/assets/events/adding-event-parameters#enriching-events-with-data-from-catalogs), for example, a product or service event where only an ID has been provided can be enriched with other details such as the description, image URL, and more.
## Queue and flushing
As a compromise between how quick events are sent and battery life, events are collected into batches and _queued_ for sending (_flushing_) after enough events are collected or too much time passes (_timeout_), according to SDK settings.
Since Android SDK 5.17.0 and iOS SDK 4.17.0, the default settings flush the queue immediately when a push event is added to it.
You can change the queue size, timeout, list of events which trigger flushing, and other event tracking settings as described in the ["Tracker" section of the "Settings" article](/developers/mobile-sdk/settings#tracker).
To flush the queue on demand, use the following methods:
| OS | Method |
| ------------ | -------------------------------------------------------------------------------------------------------------------------------- |
| Android | [Tracker.flush()](/developers/mobile-sdk/method-reference/android/tracking#flush-events-from-tracker) |
| iOS | [flushEvents(completionHandler: (() -> Void)?)](/developers/mobile-sdk/method-reference/ios/tracking#flush-events-from-tracker) |
| React Native | [flushEvents(onSuccess: () => void)](/developers/mobile-sdk/method-reference/react-native/tracking#flush-events-from-tracker) |
| Flutter | [Synerise.tracker.flush()](/developers/mobile-sdk/method-reference/flutter/tracking#flush-events-from-tracker) |
## Events tracked automatically
---
### Auto-Tracking
Automatic tracking is available only for **Android SDK** and **iOS SDK**. Auto-tracking is not supported for applications built with **Jetpack Compose** and **SwiftUI**. These applications should use [declarative tracking](#declarative-tracking).
Auto-tracking allows you to monitor each type of the customer activity in your mobile application and it is enabled by default. Every interaction (such as click, view, swipe) with any element in the application can be sent as an event to Synerise together with a collection of details concerning the event, which are available in the overview on [the profile's card](/docs/crm/crm-profile). The frequency and the kind of the tracked events are customizable, as you can switch on tracking a particular types of interactions.
#### Configuration {id=auto-tracking-configuration}
Auto-tracking events is:
- Enabled by default for Android.
- Disabled by default for iOS.
Available modes for auto-tracking:
- `DISABLED` - Listeners are disabled (**default mode for iOS SDK**).
- `PLAIN` - Listeners are set to track screen-visits only.
- `FINE` - Listeners are attached to nearly everything that is clickable in your app, including screen visits that record the [visited screen event](#customer-visited-a-screen) (**default mode for Android SDK**).
You may configure auto-tracking with various options to customize your expected behavior and track events you want. See possible configuration options below:
1. It enables/disables auto-tracking.
2. It sets auto-tracking mode.
3. It is an array of classes that you want to exclude from auto-tracking.
4. It is an array of tag numbers for views that you want to exclude from auto-tracking.
#### Events from Auto-Tracking
| Action name | Description | Label | Additional information tracked |
|--------------------|-----------------------------------------------------------------------------------------|---------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| screen.view | This event is generated when any screen of a mobile app is displayed by a mobile app user. | Activity, Fragment names (for example, `ProductDetailsFragment`) | |
| screen.interaction | This event is generated every time a mobile app user interacts with any element of the application UI. | `viewText` or the name of control type (if not able to read a value) | Depending on the UI element type tracked, Synerise automatically reads and passes any values that are set depending on type, such as: time, date, position, progress, state, value, or if the element has been selected. |
Depending on the UI element type tracked, Synerise automatically reads and passes any values that are set depending on type, such as: time, date, position, progress, state, value, or if the element has been selected.
| Action name | Description | Activity class | Label |
|--------------------|-------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------|-------------------------------------------------------------------------|
| screen.view | This event is generated when any screen of a mobile app is displayed by a mobile app user. | `UIViewController` | View controllers name (for example, MyApp.ProductDetailsViewController) |
| screen.interaction | This event is generated every time a mobile app user interacts with any element of the application UI. | `UIButton` `UISwitch` `UISegmentedControl` `UISlider` `UIStepper` `UIDatePicker` | `viewText` or name of control type (if not able to read value) |
### Events tracked internally
In addition to declarative event tracking and Auto-Tracking, many events are generated by the SDK and the Synerise infrastructure.
Read more about all [Synerise events](/docs/assets/events/event-reference/default-events)
#### Lifecycle events
Some events are automatically generated by the SDK or backend as a result of the profile's activity.
| Action name | Source | Description |
|--------------------|--------------------|------------------|
| client.applicationStarted | **SDK** | A user opened the mobile application. This event contains additional info such as operating system, device model, the sdk version etc. |
| client.applicationCrashed | **SDK** | Report about a mobile application crash, with additional data for troubleshooting. |
| click.errorReceiver | **SDK** | The event is called when the SDK cannot start an intent because there is no attached Activity (`ActivityNotFoundException`). |
| session.start | **BACKEND** | A user opened the mobile application and a session was opened. The session ends when 30 minutes pass since the last activity. |
| session.end | **BACKEND** | 30 minutes passed since the last activity and the session was closed. |
In the following example of a`client.applicationStarted` event, the highlighted data is added automatically:
{
"action": "client.applicationStarted",
"eventUUID": "9f9f81ce-fb3d-432d-8f88-a4ce20ac3c0d",
"label": "AppStarted",
"params": {
"deviceType": "SMARTPHONE", // SMARTPHONE or TABLET
"deviceId": "B36535BD-7C80-4D90-A941-26CD4DB7FA7C",
"osLanguage": "pl", // Language set in operating system
"appVersionCode": "8", // Build number of the mobile app
"systemPushConsent": "enabled", // System consent for push notifications
"source": "MOBILE_APP",
"networkType": "WIFI", // WIFI or CELL
"cellCountry": "--",
"deviceModel": "iPhone13,1", // Model of a device
"os": "ios", // iOS or Android
"applicationType": "UNKNOWN",
"deviceRooted": "false",
"applicationName": "SDK Sample App Swift",
"appVersion": "4.16.0", // Version of the mobile app
"cellCarrier": "--",
"origin": "APP_STARTED",
"deviceManufacturer": "Apple", // Manufacturer of a device
"sdkVersion": "4.16.0", // SDK version in the mobile app
"sdkPreviousVersion": "4.15.0", // SDK version previously installed in the mobile app
"sdkPluginVersion": "1.2.0", // SDK plugin version in the mobile app (in hybrid apps, for example built with Flutter)
"osVersion": "17.3.1", // OS version of a device
"deviceId": "B36535BD-7C80-4D90-A941-26CD4DB7FA7C",
"deviceResolution": "1080x2338", // Resolution of device screen
(...)
}
}
#### Profile events
Some events are automatically generated as a result of an action or interaction with the profile such as registration, authorizations, and more.
Check details of [profile's events](/docs/assets/events/event-reference/profiles).
| Action name | Source | Description |
|--------------------|--------------------|-----------------------------------------------------------------------------------------|
| client.anonymousLogin | **BACKEND** | An anonymous profile generated a new authentication token. |
| client.simpleAuthLogin | **BACKEND** | A user logged in with [Simple Profile Authentication](/developers/mobile-sdk/user-identification-and-authorization/simple-authentication) |
| client.register | **BACKEND** | A profile was registered successfully. This event is only generated for Registration-as-a-Service. |
| client.tryToLogInToInactiveAccount | **BACKEND** | A profile tried to log in to an inactive account. |
| client.login | **BACKEND** | A user logged in mobile application. This event is only generated for OAuth and Synerise Authentication (aka RaaS). |
| client.logout | **BACKEND** | A user logged out from the mobile application. By default, this event is generated only when you use Synerise Authentication (aka RaaS). |
| client.merge | **BACKEND** | Two or more profiles were merged into one. |
| profile.updated | **BACKEND** | A profile was updated. |
#### Push Notifications events
Some events are automatically generated as a result of an action or interaction of the profile with push notifications.
To ensure correct tracking of push notification events, you must [configure push notifications](/developers/mobile-sdk/configuring-push-notifications) first.
Check details of [push notification events](/docs/assets/events/event-reference/mobile-push).
| Action name | Source | Description |
|--------------------|--------------------|-----------------------------------------------------------------------------------------|
| push.view | **SDK** | A push notification was shown to the app user. |
| push.notView | **SDK** | A push notification was sent, but the device did not display it due to the `areNotificationsEnabled` setting on the device. This event is only generated for Android 7.0 or later. |
| push.click | **SDK** | A push notification was tapped. |
| push.button.click | **SDK** | **DEPRECATED** A button in a push notification was tapped. |
| push.openInApp | **SDK** | A push notification was tapped and the app was opened. This event is only generated for iOS. |
| push.dismiss | **SDK** | A push notification was dismissed. The event requires configuring [Notification Service Extension](/developers/mobile-sdk/configuring-push-notifications/ios#synerise-notification-service-extension) for full support. |
| push.imageTimeout | **SDK** | An image in a mobile push notification could not be loaded. |
| push.controlGroup | **BACKEND** | A mobile push notification was not sent because the recipient belongs to the control group. |
| push.send | **BACKEND** | A push notification was sent to a profile. |
| push.notSent | **BACKEND** | A push notification failed to be created by the backend. Usually occurs when notification encryption is enabled in your business profile, but your application did not generate a key pair. |
| push.capping | **BACKEND** | A push notification was not sent due to message limits set for this type of communication. |
| push.skipped | **BACKEND** | A push notification was not sent because Silence Hours were active. If the process of sending multiple messages overlaps with Silence Hours, sending is stopped in progress. |
| push.tokenUpdate | **BACKEND** | A Firebase registration token was updated in the Synerise system. |
| push.tokenDelete | **BACKEND** | A Firebase registration token was deleted when a backend tried to send a push notification. Usually occurs when it is a problem with user's token. |
| push.notRegistered | **BACKEND** | A push notification was not sent due to an invalid Firebase token. |
| push.invalidRegistrationId | **BACKEND** | A push notification was not sent due to an incorrectly assigned registrationId in Firebase. |
| push.mismatchSenderId | **BACKEND** | A push notification was not sent, because the Firebase project to which the profile was registered changed. |
In these events campaign data is always tracked. See specified part of `push.view` event below:
{
"action": "push.view",
"eventUUID": "eca5662f-ecfd-418a-af5c-e65ba10ca252",
"label": "Test Simple Push",
"params": {
"id": "ecf5678d-c137-44d1-964f-83bc8d15511e", // Campaign ID
"variantId": 11598412, // Variant ID of the campaign
"campaignTitle": "Test Simple Push", // Campaign title
"campaignType": "Mobile push", // Campaign type
(...)
}
}
#### In-App Messages events
Sort events are automatically generated as a result of an action or interaction with in-app messages by the user of the mobile app.
Read more about the details of [in-app messages events](/docs/assets/events/event-reference/inapp).
| Action name | Source | Description |
|--------------------|--------------------|-----------------------------------------------------------------------------------------|
| inApp.show | **SDK** | An in-app message was shown to the app user. |
| inApp.capping | **SDK** | An in-app message was not displayed due to [capping](/docs/campaign/in-app-messages/create-inapp-message#capping) or [frequency limits](/docs/campaign/in-app-messages/create-inapp-message#frequency). |
| inApp.click | **SDK** | The content of an in-app message was tapped. |
| inApp.controlGroup | **SDK** | An in-app message was not displayed because the recipient belongs to the control group. |
| inApp.discard | **SDK** | An in-app message was closed. |
| inApp.hide | **SDK** | An in-app message was hidden. |
| inApp.customHook | **SDK** | A custom action (implemented by your app developers and included in the in-app definition) from an in-app message was triggered. |
| inApp.renderFail | **SDK** / **BACKEND** | An in-app message was not displayed due to an error. This may be caused, for example, by an error in the Jinjava syntax or a connection problem. |
In these events campaign data is always tracked. See specified part of `inApp.show` event below:
{
"action": "inApp.show",
"eventUUID": "e982ed4d-9179-4bc3-9266-322ff4a8f2eb",
"label": "In-app message was displayed in mobile app",
"params": {
"id": "83e13e0b-7930-4866-a2cf-088dcbe0b222", // Campaign ID
"variantId": "c3bbfc16-a79e-474f-a255-ef7ee1333148", // Variant ID of the campaign
(...)
}
}
#### Other campaigns events
Other events are which automatically generated as a result of an action related to campaigns.
| Action name | Source | Description |
|--------------------|--------------------|-----------------------------------------------------------------------------------------|
| screen.content | **SDK** | A Screen View campaign was generated and fetched for the profile in the mobile app. It contains data with a sorted tree of the documents. |
| client.activatePromotion | **BACKEND** | A promotion was activated by the profile. |
| client.deactivatePromotion | **BACKEND** | A promotion was deactivated by the profile. |
| recommendation.generated | **BACKEND** | A recommendation set was generated for a profile. |
| recommendation.view | **SDK** | A recommendation frame was displayed to a user. The parameters may include a list of the items in the frame, depending on your implementation. Event from Content Widget. |
| recommendation.seen | **SDK** | A recommendation frame was displayed to a user. The parameters may include a list of the items in the frame, depending on your implementation. Event from Content Widget. |
| recommendation.click | **SDK** | A recommended item was clicked. Event from Content Widget. |
| product.like | **SDK** | The Content Widget includes a "like" button that was tapped by the user. |
| product.dislike | **SDK** | The Content Widget includes a "dislike" button that was tapped by the user. |
## Declarative tracking
---
Declarative tracking is a feature of our SDK that allows you to declare additional actions for tracking.
Product views, screen views, clicking a sign up button, contact with the call center, and more: you can implement anything and declarative tracking will help you to do that.
DO NOT send `transaction.charge` events as custom events.
Transactions must be tracked with these endpoints:
- [`/v4/transactions`](https://hub.synerise.com/api-reference/data-management#operation/CreateATransaction) (single transaction)
- [`/v4/transactions/batch`](https://hub.synerise.com/api-reference/data-management#operation/BatchAddOrUpdateTransactions) (multiple transactions)
### Basic custom event
In the most basic scenario, you can pass an event as in the examples below:
Such events are passed to Synerise as the `CustomEvent` type, since the `action` can be anything that you want.
- The action name must follow the `context.action` convention. For example: `screen.view`, `product.buy`, `social.share`
- The action name must be up to 32 characters long and must match the following regular expression:
```
^[a-zA-Z0-9\.\-_]+$
```
### Custom events with more parameters
If you want to send more complex events, you can include additional parameters:
The following keys are reserved and you can't send them: **modifiedBy**, **apiKey**, **eventUUID**, **ip**, **time**, **businessProfileId**. If you add them to an event, they are ignored.
### Predefined events
Synerise offers a set of predefined event types that require a minimum set of data for the backend.
They can be sent by using Setters as in the following example. The example uses the [Product viewed](#product-viewed) event.
| **Android** | **iOS** | **React Native** | **Flutter** |
| --------------- | ----------------- | ----------------------- | ----------------------- |
| [Tracker.send(event)](/developers/mobile-sdk/method-reference/android/tracking#send-event) method | [Tracker.send(_:)](/developers/mobile-sdk/method-reference/ios/tracking#send-event) method | [Synerise.Tracker.send(event)](/developers/mobile-sdk/method-reference/react-native/tracking#send-event) method | [Synerise.tracker.send(event)](/developers/mobile-sdk/method-reference/flutter/tracking#send-event) method |
## Predefined event list
---
The list contains the list of predefined events which you can implement.
### Customer registered
---
This event may be used if you do not use [Synerise registration/authentication](/developers/mobile-sdk/user-identification-and-authorization/overview) features and rely fully on your own mechanisms, but still want to gather events when a customer registers.
**Action name of the generated event**: client.register
**Example**:
```Java
RegisteredEvent event = new RegisteredEvent("label")
Tracker.send(event);
```
```Kotlin
val event = RegisteredEvent("label")
Tracker.send(event)
```
```Swift
let event: RegisteredEvent = RegisteredEvent(label: "LABEL")
Tracker.send(event)
```
| OS | Event | Required fields |
|--------------|----------------------------------------------------------------------------------------------------------------------|-----------------|
| Android | [RegisteredEvent](/developers/mobile-sdk/class-reference/android/events#registeredevent) | Label |
| iOS | [RegisteredEvent](/developers/mobile-sdk/class-reference/ios/events#registeredevent) | Label |
| React Native | [RegisteredEvent](/developers/mobile-sdk/class-reference/react-native/events#registeredevent) | Label |
| Flutter | [RegisteredEvent](/developers/mobile-sdk/class-reference/flutter/events#registeredevent) | Label |
### Customer logged in event
---
This event may be used if you do not use [Synerise login/authentication](/developers/mobile-sdk/user-identification-and-authorization/overview) features and rely fully on your own mechanisms, but still want to gather events when a customer logs in.
**Action name of the generated event**: client.login
Logged in event
**Example**:
```Java
LoggedInEvent event = new LoggedInEvent("label")
Tracker.send(event);
```
```Kotlin
val event = LoggedInEvent("label")
Tracker.send(event)
```
```Swift
let event: LoggedInEvent = LoggedInEvent(label: "LABEL")
Tracker.send(event)
```
| OS | Event | Required fields |
|--------------|-------------------------------------------------------------------------------------------------------------------|-----------------|
| Android | [LoggedInEvent](/developers/mobile-sdk/class-reference/android/events#loggedinevent) | Label |
| iOS | [LoggedInEvent](/developers/mobile-sdk/class-reference/ios/events#loggedinevent) | Label |
| React Native | [LoggedInEvent](/developers/mobile-sdk/class-reference/react-native/events#loggedinevent) | Label |
| Flutter | [LoggedInEvent](/developers/mobile-sdk/class-reference/flutter/events#loggedinevent) | Label |
### Customer logged out
---
This event may be used if you do not use [Synerise login/authentication](/developers/mobile-sdk/user-identification-and-authorization/overview) features and rely fully on your own mechanisms, but still want to gather events when a customer logs out.
**Action name of the generated event**: client.logout
**Example**:
```Java
LoggedOutEvent event = new LoggedOutEvent("label")
Tracker.send(event);
```
```Kotlin
val event = LoggedOutEvent("label")
Tracker.send(event)
```
```Swift
let event: LoggedOutEvent = LoggedOutEvent(label: "LABEL")
Tracker.send(event)
```
| OS | Event | Required fields |
|--------------|---------------------------------------------------------------------------------------------------------------------|-----------------|
| Android | [LoggedOutEvent](/developers/mobile-sdk/class-reference/android/events#loggedoutevent) | Label |
| iOS | [LoggedOutEvent](/developers/mobile-sdk/class-reference/ios/events#loggedoutevent) | Label |
| React Native | [LoggedOutEvent](/developers/mobile-sdk/class-reference/react-native/events#loggedoutevent) | Label |
| Flutter | [LoggedOutEvent](/developers/mobile-sdk/class-reference/flutter/events#loggedoutevent) | Label |
### Product viewed
---
Use this event to track customer visits to a product in your mobile application.
**Action name of the generated event**: product.view
Event sent when the mobile app user sees an item
**Example**:
```Java
ProductViewEvent event = new ProductViewEvent("label", "productId", "productName");
Tracker.send(event);
```
```Kotlin
val event = ProductViewEvent("label", "productId", "productName")
Tracker.send(event)
```
| OS | Event | Required fields |
|--------------|-------------------------------------------------------------------------------------------------------------------------|------------------------|
| Android | [ProductViewEvent](/developers/mobile-sdk/class-reference/android/events#productviewevent) | Label, ProductId, Name |
| iOS | [ProductViewedEvent](/developers/mobile-sdk/class-reference/ios/events#productviewedevent) | Label, ProductId, Name |
| React Native | [ProductViewedEvent](/developers/mobile-sdk/class-reference/react-native/events#productviewedevent) | Label, ProductId, Name |
| Flutter | [ProductViewedEvent](/developers/mobile-sdk/class-reference/flutter/events#productviewedevent) | Label, ProductId, Name |
### Product added to favorites
---
Use this event to track adding a product to favorites in your mobile application.
**Action name of the generated event**: product.addToFavorite
Event sent when a mobile app user adds an item to favorites
**Example**:
```Java
AddedToFavoritesEvent event = new AddedToFavoritesEvent("label");
Tracker.send(event);
```
```Kotlin
val event = AddedToFavoritesEvent("label")
Tracker.send(event)
```
```Swift
let event: ProductAddedToFavoritesEvent = ProductAddedToFavoritesEvent(label: "LABEL")
Tracker.send(event)
```
| OS | Event | Required fields |
|--------------|---------------------------------------------------------------------------------------------------------------------------------|-----------------------------------|
| Android | [AddedToFavoritesEvent](/developers/mobile-sdk/class-reference/android/events#addedtofavoritesevent) | Label |
| iOS | [ProductAddedToFavoritesEvent](/developers/mobile-sdk/class-reference/ios/events#productremovedfromcartevent) | Label |
| React Native | [ProductAddedToFavouritesEvent](/developers/mobile-sdk/class-reference/react-native/events#productaddedtofavoritesevent) | Label |
| Flutter | [ProductAddedToFavouritesEvent](/developers/mobile-sdk/class-reference/flutter/events#productaddedtofavoritesevent) | Label |
### Product added to cart
---
Use this event to track adding a product to a cart in your mobile application.
**Action name of the generated event**: product.addToCart
Event sent when a mobile app user adds an item to cart
**Example**:
```Java
UnitPrice unitPrice = new UnitPrice(price, Currency.getInstance(Locale.US));
AddedToCartEvent event = new AddedToCartEvent("label", "sku", unitPrice, 1);
Tracker.send(event);
```
```Kotlin
val unitPrice = UnitPrice(price, Currency.getInstance(Locale.US))
val event = AddedToCartEvent("label", "sku", unitPrice, 1)
Tracker.send(event)
```
| OS | Event | Required fields |
|--------------|---------------------------------------------------------------------------------------------------------------------------------|-----------------------------------|
| Android | [RemovedFromCartEvent](/developers/mobile-sdk/class-reference/android/events#removedfromcartevent) | Label, Sku, FinalPrice, Quantity |
| iOS | [ProductRemovedFromCartEvent](/developers/mobile-sdk/class-reference/ios/events#productremovedfromcartevent) | Label, SKU, FinalPrice, Quantity |
| React Native | [ProductRemovedFromCartEvent](/developers/mobile-sdk/class-reference/react-native/events#productremovedfromcartevent) | Label, SKU, FinalPrice, Quantity |
| Flutter | [ProductRemovedFromCartEvent](/developers/mobile-sdk/class-reference/flutter/events#productremovedfromcartevent) | Label, SKU, FinalPrice, Quantity |
### Recommendation viewed
Use this event to track when a recommendation is displayed to a customer.
**Action name of the generated event**: recommendation.view
**For iOS and Android only**: If you use the [Widget](/developers/mobile-sdk/displaying-recommendations/content-widget/android) to present recommendations, this event is tracked automatically.
**Example**:
```Java
List items = Arrays.asList("PRODUCT_ID_1", "PRODUCT_ID_2!");
RecommendationViewEvent event = new RecommendationViewEvent("LABEL", items, "12345", "1234", "corr", params)
Tracker.send(event)
```
```Kotlin
val items = listOf("PRODUCT_ID_1", "PRODUCT_ID_2")
val event = RecommendationViewEvent("LABEL", items, "12345", "1234", "corr", params)
Tracker.send(event)
```
This is a legacy event. You should use [recommendation.view](#recommendation-viewed) instead.
Use this event to track recommendation display to a customer.
**Action name of the generated event**: recommendation.seen
**For iOS and Android only**: If you use the [Widget](/developers/mobile-sdk/displaying-recommendations/content-widget/android) to present recommendations, this event is tracked automatically.
**Example**:
| OS | Event | Required fields |
|--------------|---------------------------------------------------------------------------------------------------------------------------------------| --- |
| Android | [RecommendationClickEvent](/developers/mobile-sdk/class-reference/android/events#recommendationclickevent) | Label, ProductId,Name, CampaignId, CampaignHash |
| iOS | [RecommendationClickEvent](/developers/mobile-sdk/class-reference/ios/events#recommendationclickevent) | Label, ProductId, Name, CampaignId, CampaignHash |
| React Native | [RecommendationClickEvent](/developers/mobile-sdk/class-reference/react-native/events#recommendationclickevent) | Label, ProductId, Name, CampaignId, CampaignHash |
| Flutter | [RecommendationClickEvent](/developers/mobile-sdk/class-reference/flutter/events#recommendationclickevent) | Label, ProductId, Name, CampaignId, CampaignHash |
### Customer appeared in location
---
Use this event to track a customer's presence at a location by passing geographic coordinates.
1. Send a [silent push](/developers/mobile-sdk/campaigns/silent-push) with the Synerise command `GET_LOCATION`.
2. SDK retrieves the location.
3. Use the data from the `GET_LOCATION` response to send the `AppearedInLocation` event.
**Action name of the generated event**: client.location
The "appeared in location" event is sent after a silent push
**Example**:
```Java
AppearedInLocationEvent event = new AppearedInLocationEvent("label", 48.1599, 11.5761);
Tracker.send(event);
```
```Kotlin
val event = AppearedInLocationEvent("label", 48.1599, 11.5761)
Tracker.send(event)
```
```Swift
let latitude: CLLocationDegrees = CLLocationDegrees(52.237049)
let longitude: CLLocationDegrees = CLLocationDegrees(21.017532)
let location: CLLocation = CLLocation(latitude: latitude, longitude: longitude)
let event: AppearedInLocationEvent = AppearedInLocationEvent(label: "LABEL", location: location)
Tracker.send(event)
```
| OS | Event | Required fields |
|--------------|----------------------------------------------------------------------------------------------------------------- |----------------------------|
| Android | [AppearedInLocationEvent](/developers/mobile-sdk/class-reference/android/events#appearedinlocationevent) | Label, Latitude, Longitude |
| iOS | [AppearedInLocationEvent](/developers/mobile-sdk/class-reference/ios/events#appearedinlocationevent) | Label, Latitude, Longitude |
| React Native | [AppearedInLocationEvent](/developers/mobile-sdk/class-reference/react-native/events#appearedinlocationevent) | Label, Latitude, Longitude |
| Flutter | [AppearedInLocationEvent](/developers/mobile-sdk/class-reference/flutter/events#appearedinlocationevent) | Label, Latitude, Longitude |
### Customer activity timer
---
Use this event to measure the duration of any customer activity - send Hit timer when a customer starts an activity and send it again with a different time signature when the customer finishes. After that, you can use the [Decision Hub](/docs/analytics) to measure, for example, average activity time. You can add a custom parameter to the timer events so you can recognize them.
**Action name of the generated event**: client.hitTimer
**Example**:
```Java
HitTimerEvent event = new HitTimerEvent("label");
Tracker.send(event);
```
```Kotlin
val event = HitTimerEvent("label")
Tracker.send(event)
```
```Swift
let event: HitTimerEvent = HitTimerEvent(label: "LABEL")
Tracker.send(event)
```
| OS | Event | Required fields |
|--------------|-------------------------------------------------------------------------------------------------------------------|-----------------|
| Android | [HitTimerEvent](/developers/mobile-sdk/class-reference/android/events#hittimerevent) | Label |
| iOS | [HitTimerEvent](/developers/mobile-sdk/class-reference/ios/events#hittimerevent) | Label |
| React Native | [HitTimerEvent](/developers/mobile-sdk/class-reference/react-native/events#hittimerevent) | Label |
| Flutter | [HitTimerEvent](/developers/mobile-sdk/class-reference/flutter/events#hittimerevent) | Label |
### Customer searched
---
Use this event to track search queries - every time a customer types a query in the search box in your mobile application, this event will be generated.
**Action name of the generated event**: client.search
**Example**:
```Java
SearchedEvent event = new SearchedEvent("label");
Tracker.send(event);
```
```Kotlin
val event = SearchedEvent("label")
Tracker.send(event)
```
```Swift
let event: SearchedEvent = SearchedEvent(label: "LABEL")
Tracker.send(event)
```
```JavaScript
var object: Object = {
sharedEvents: '5',
field: 'test',
}
let event = new SharedEvent('Shared Event Label', object)
Synerise.Tracker.send(event)
```
```Dart
SharedEvent event = new SharedEvent('label',{});
Synerise.tracker.send(event);
```
| OS | Event | Required fields |
|--------------|--------------------------------------------------------------------------------------------------------------|-----------------|
| Android | [SharedEvent](/developers/mobile-sdk/class-reference/android/events#sharedevent) | Label |
| iOS | [SharedEvent](/developers/mobile-sdk/class-reference/ios/events#sharedevent) | Label |
| React Native | [SharedEvent](/developers/mobile-sdk/class-reference/react-native/events#sharedevent) | Label |
| Flutter | [SharedEvent](/developers/mobile-sdk/class-reference/flutter/events#sharedevent) | Label |
### Customer visited a screen
---
This event is used when a customer visits a particular screen in your application.
**Action name of the generated event**: screen.view
Event sent when a mobile app user visits a screen
**Example**:
```Java
VisitedScreenEvent event = new VisitedScreenEvent("label");
Tracker.send(event);
```
```Kotlin
val event = VisitedScreenEvent("label")
Tracker.send(event)
```
```Swift
let event: VisitedScreenEvent = VisitedScreenEvent(label: "LABEL")
Tracker.send(event)
```
| OS | Event | Required fields |
|--------------|----------------------------------------------------------------------------------------------------------------------|-----------------|
| Android | [VisitedScreenEvent](/developers/mobile-sdk/class-reference/android/events#visitedscreenevent) | Label |
| iOS | [VisitedScreenEvent](/developers/mobile-sdk/class-reference/ios/events#visitedscreenevent) | Label |
| React Native | [VisitedScreenEvent](/developers/mobile-sdk/class-reference/react-native/events#visitedscreenevent) | Label |
| Flutter | [VisitedScreenEvent](/developers/mobile-sdk/class-reference/flutter/events#visitedscreenevent) | Label |
### Crash Event
---
This event is used when the application crashes.
The event is sent automatically by **Synerise SDK** when you enable [crash handling](/developers/mobile-sdk/miscellaneous#crash-handling) while configuring the SDK.
You can send it by yourself when you handle an uncaught exception.
**Action name of the generated event**: client.applicationCrashed
**Example**:
Push events are tracked automatically for Android and React Native (if the notifications have been configured for React Native according to [iOS](/developers/mobile-sdk/configuring-push-notifications/react-native#setting-up-ios) or [Android](/developers/mobile-sdk/configuring-push-notifications/react-native#setting-up-android) ).
**Action name of the generated event**: push.view
```Swift
let event: PushViewedEvent = PushViewedEvent(label: "LABEL")
Tracker.send(event)
```
Push events are tracked automatically for Android and React Native (if the notifications have been configured for React Native according to [iOS](/developers/mobile-sdk/configuring-push-notifications/react-native#setting-up-ios) or [Android](/developers/mobile-sdk/configuring-push-notifications/react-native#setting-up-android) ).
**Action name of the generated event**: push.click
```Swift
let event: PushClickedEvent = PushClickedEvent(label: "LABEL")
Tracker.send(event)
```
Push events are tracked automatically for Android and React Native (if the notifications have been configured for React Native according to [iOS](/developers/mobile-sdk/configuring-push-notifications/react-native#setting-up-ios) or [Android](/developers/mobile-sdk/configuring-push-notifications/react-native#setting-up-android) ).
**Action name of the generated event**: push.dismiss
```Swift
let event: PushCancelledEvent = PushCancelledEvent(label: "LABEL")
Tracker.send(event)
```
**Discussion:**
Learn more about the methods and the purpose of this listener [here](/developers/mobile-sdk/listeners-and-delegates/ios-delegates#notification-delegate).
## Set In-App Message delegate
---
This method sets an object for in-app message campaigns delegate methods.
**Declared In:**
Headers/SNRInjector.h
**Related To:**
[InjectorInAppMessageDelegate](/developers/mobile-sdk/listeners-and-delegates/ios-delegates#injector-in-app-message-delegate)
**Class:**
[Injector](/developers/mobile-sdk/class-reference/ios/modules#injector)
**Declaration:**
**Discussion:**
Learn more about the methods and the purpose of this listener [here](/developers/mobile-sdk/listeners-and-delegates/ios-delegates#injector-in-app-message-delegate).
## Close In-App message
---
Closes an in-app message and sends an `inApp.discard` event.
Usage examples:
- Closing a top bar or bottom bar when the user taps outside the in-app area.
- Automatically dismissing messages when navigating away from a screen.
- Controlling in-app visibility based on app logic for a smoother user experience.
| | **iOS SDK** | **Android SDK** | **React Native SDK** | **Flutter SDK** |
| ----------------------------------------------- | ----------- | --------------- | -------------------- | --------------- |
| Introduced in: | 5.7.0 | 6.7.0 | 1.5.0 | 2.5.0 |
**Declared In:**
Headers/SNRInjector.h
**Class:**
[Injector](/developers/mobile-sdk/class-reference/ios/modules#injector)
**Declaration:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **notificationCategories** | Set | yes | - | A set of objects containing all the actions displayed in the notification interface. |
**Return Value:**
No value is returned.
## Register for push notifications
---
This method passes the Firebase Token to Synerise for notifications.
- You should call this method every time the user changes the system or application consent for notifications.
- The API key must have the `API_PERSONAL_DEVICE_CLIENT_UPDATE` permission from the **Client** group.
- If the registration fails, the SDK requests a token update again by a listener/delegate method ([Android](/developers/mobile-sdk/listeners-and-delegates/android-listeners#on-register-for-push-listener), [iOS](/developers/mobile-sdk/listeners-and-delegates/ios-delegates#synerise-delegate-register-for-push-notifications-is-needed), [React Native](/developers/mobile-sdk/listeners-and-delegates/react-native-listeners#notifications-listener), [Flutter](/developers/mobile-sdk/listeners-and-delegates/flutter-listeners#notifications-listener)).
## Register for push notifications without agreement
---
This method passes the Firebase Token to Synerise for notifications and doesn't update the agreement of the profile.
| | **iOS SDK** | **Android SDK** | **React Native SDK** | **Flutter SDK** |
| --- | --- | --- | --- | --- |
| Introduced in: | 4.14.0 | 5.7.1 | 0.15.0 | 1.1.0 |
The API key must have the `API_PERSONAL_DEVICE_CLIENT_UPDATE` permission from the **Client** group.
If the registration fails, the SDK requests a token update again by a listener/delegate method ([Android](/developers/mobile-sdk/listeners-and-delegates/android-listeners#on-register-for-push-listener), [iOS](/developers/mobile-sdk/listeners-and-delegates/ios-delegates#synerise-delegate-register-for-push-notifications-is-needed), [React Native](/developers/mobile-sdk/listeners-and-delegates/react-native-listeners#notifications-listener), [Flutter](/developers/mobile-sdk/listeners-and-delegates/flutter-listeners#notifications-listener)).
## Check if push notification is from Synerise
---
This method verifies if a notification was sent by Synerise.
**Declared In:**
Headers/SNRSynerise.h
**Class:**
[Synerise](/developers/mobile-sdk/class-reference/ios/modules#synerise)
**Declaration:**
```Objective-C
#pragma mark - UNUserNotificationCenterDelegate
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler NS_AVAILABLE_IOS(10) {
NSDictionary *userInfo = response.notification.request.content.userInfo;
BOOL isSyneriseNotification = [SNRSynerise isSyneriseNotification:userInfo];
if (isSyneriseNotification == YES) {
// notification is from Synerise
}
}
```
## Check if push notification is a Simple Push Campaign
---
This method verifies if a notification’s sender is Synerise and if the notification is a Simple Push campaign
**Declared In:**
Headers/SNRSynerise.h
**Class:**
[Synerise](/developers/mobile-sdk/class-reference/ios/modules#synerise)
**Declaration:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **userInfo** | [AnyHashable: Any] | yes | - | Key-Value map of data |
**Return Value:**
**true** if the notification is Synerise Simple Push provided by Synerise, otherwise returns **false**.
**Example:**
```Swift
//MARK: - UNUserNotificationCenterDelegateextension NotificationService: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
let userInfo = response.notification.request.content.userInfolet isSyneriseNotification = Synerise.isSyneriseNotification(userInfo)
if isSyneriseNotification == true {
// notification is from Synerise let isSyneriseSimplePush = Synerise.isSyneriseSimplePush(userInfo)
if isSyneriseSimplePush == true {
// notification is Synerise Simple Push Campaign
}
}
}
}
```
```Objective-C
#pragma mark - UNUserNotificationCenterDelegate- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler NS_AVAILABLE_IOS(10) {
NSDictionary *userInfo = response.notification.request.content.userInfo; BOOL isSyneriseNotification = [SNRSynerise isSyneriseNotification:userInfo];
if (isSyneriseNotification == YES) {
// notification is from Synerise BOOL isSyneriseSimplePush = [SNRSynerise isSyneriseSimplePush:userInfo];
if (isSyneriseSimplePush == YES) {
// notification is Synerise Simple Push Campaign
}
}
}
```
## Check if push notification is a Silent Command
---
This method verifies if a notification’s sender is Synerise and if the notification is a Silent Command.
**Declared In:**
Headers/SNRSynerise.h
**Class:**
[Synerise](/developers/mobile-sdk/class-reference/ios/modules#synerise)
**Declaration:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **userInfo** | [AnyHashable: Any] | yes | - | Key-Value map of data |
**Return Value:**
**true** if the notification is Synerise Silent Command provided by Synerise, otherwise returns **false**.
**Example:**
```Swift
//MARK: - UNUserNotificationCenterDelegateextension NotificationService: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
let userInfo = response.notification.request.content.userInfolet isSyneriseNotification = Synerise.isSyneriseNotification(userInfo)
if isSyneriseNotification == true {
// notification is from Synerise let isSyneriseSilentCommand = Synerise.isSyneriseSilentCommand(userInfo)
if isSyneriseSilentCommand == true {
// notification is Synerise Silent Command
}
}
}
}
```
```Objective-C
#pragma mark - UNUserNotificationCenterDelegate- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler NS_AVAILABLE_IOS(10) {
NSDictionary *userInfo = response.notification.request.content.userInfo; BOOL isSyneriseNotification = [SNRSynerise isSyneriseNotification:userInfo];
if (isSyneriseNotification == YES) {
// notification is from Synerise BOOL isSyneriseSilentCommand = [SNRSynerise isSyneriseSilentCommand:userInfo];
if (isSyneriseSilentCommand == YES) {
// notification is Synerise Silent Command
}
}
}
```
## Check if push notification is a Silent SDK Command
---
This method verifies if a notification's sender is Synerise and if the notification is a Silent SDK Command.
**Declared In:**
Headers/SNRSynerise.h
**Class:**
[Synerise](/developers/mobile-sdk/class-reference/ios/modules#synerise)
**Declaration:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **userInfo** | [AnyHashable: Any] | yes | - | Key-Value map of data |
**Return Value:**
**true** if the notification is Synerise Silent SDK Command provided by Synerise, otherwise returns **false**.
**Example:**
```Swift
//MARK: - UNUserNotificationCenterDelegate
extension NotificationService: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
let isSyneriseNotification = Synerise.isSyneriseNotification(userInfo)
if isSyneriseNotification == true {
// notification is from Synerise let isSyneriseSilentSDKCommand = Synerise.isSyneriseSilentSDKCommand(userInfo)
if isSyneriseSilentSDKCommand == true {
// notification is Synerise Silent SDK Command
}
}
}
}
```
```Objective-C
#pragma mark - UNUserNotificationCenterDelegate
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler NS_AVAILABLE_IOS(10) {
NSDictionary *userInfo = response.notification.request.content.userInfo;
BOOL isSyneriseNotification = [SNRSynerise isSyneriseNotification:userInfo];
if (isSyneriseNotification == YES) {
// notification is from Synerise
BOOL isSyneriseSilentSDKCommand = [SNRSynerise isSyneriseSilentSDKCommand:userInfo];
if (isSyneriseSilentSDKCommand == YES) {
// notification is Synerise Silent SDK Command
}
}
}
```
## Check if push notification is encrypted
---
This method verifies if a notification is encrypted.
**Declared In:**
Headers/SNRSynerise.h
**Class:**
[Synerise](/developers/mobile-sdk/class-reference/ios/modules#synerise)
**Declaration:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **userInfo** | [AnyHashable: Any] | yes | - | Key-Value map of data |
**Return Value:**
No value is returned.
**Example:**
```Swift
//MARK: - UNUserNotificationCenterDelegate
extension NotificationService: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
let isSyneriseNotification = Synerise.isSyneriseNotification(userInfo)
if isSyneriseNotification == true {
// notification is from Synerise Synerise.handleNotification(userInfo)
}
}
}
```
```Objective-C
#pragma mark - UNUserNotificationCenterDelegate
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler NS_AVAILABLE_IOS(10) {
NSDictionary *userInfo = response.notification.request.content.userInfo;
BOOL isSyneriseNotification = [SNRSynerise isSyneriseNotification:userInfo];
if (isSyneriseNotification == YES) {
// notification is from Synerise
[SNRSynerise handleNotification:userInfo];
}
}
```
## Handle Synerise push notification with action
---
This method handles a notification payload with a user interaction and starts activity.
**Declared In:**
Headers/SNRSynerise.h
**Class:**
[Synerise](/developers/mobile-sdk/class-reference/ios/modules#synerise)
**Declaration:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **success** | (([[AnyHashable: Any]]) -> Void) | yes | - | Closure/Block to be executed when the operation is completed successfully |
| **failure** | (([ApiError](/developers/mobile-sdk/class-reference/ios/miscellaneous#snrapierror)) -> Void) | yes | - | Closure/Block to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
# Transactions
The mobile SDK doesn't provide tracking of transactions. To do so, use the following endpoints:
- [Create a transaction](https://hub.synerise.com/api-reference/data-management#operation/CreateATransaction)
- [Batch add or update transactions](https://hub.synerise.com/api-reference/data-management#operation/BatchAddOrUpdateTransactions)
# Campaigns
In this section, you will learn how to implement and handle Synerise campaigns in your mobile application.
# Content Widget
### ContentWidget
Class responsible for creating the content widget.
**Declared In:**
`com.synerise.sdk.content.widgets.ContentWidget`
**Declaration:**
```Java
public class ContentWidget
```
```Kotlin
class ContentWidget
```
**Properties:**
There are no properties.
**Initializers:**
There is a constructor.
public ContentWidget(ContentWidgetOptions contentWidgetOptions, ContentWidgetAppearance contentWidgetAppearance)
**Methods:**
Setter for widget state.
public void setOnContentWidgetListener(OnContentWidgetListener listener)
---
This method is responsible for returning widgetView.
public View getView()
---
This method reloads data.
public void load()
---
---
---
### ContentWidgetAppearance
Class responsible for configuring the content widget UI.
**Declared In:**
`com.synerise.sdk.content.widgets.model.ContentWidgetAppearance`
**Declaration:**
```Java
public class ContentWidgetAppearance
```
```Kotlin
class ContentWidgetAppearance
```
**Properties:**
| Property | Type | Optional | Default | Description |
| --- | --- | --- | --- | --- |
| **layout** | [ContentWidgetBaseLayout](/developers/mobile-sdk/class-reference/android/content-widget#contentwidgetbaselayout) | no | - | Content widget layout |
| **itemLayout** | [ContentWidgetBaseItemLayout](/developers/mobile-sdk/class-reference/android/content-widget#contentwidgetbaseitemlayout) | no | - | Single item layout |
**Initializers:**
There is a constructor.
public ContentWidgetAppearance(ContentWidgetBaseLayout layout, ContentWidgetBaseItemLayout itemLayout)
**Methods:**
There are no methods.
---
---
---
### ContentWidgetOptions
Class responsible for configuration of the content widget data.
**Declared In:**
`com.synerise.sdk.content.widgets.model.ContentWidgetOptions`
`com.synerise.sdk.content.widgets.model.ContentWidgetRecommendationsOptions`
**Declaration:**
```Java
public class ContentWidgetRecommendationsOptions
```
```Kotlin
class ContentWidgetRecommendationsOptions
```
**Properties:**
| Property | Type | Optional | Default | Description |
| --- | --- | --- | --- | --- |
| **activity** | Activity | no | - | Activity |
| **slug** | String | no | - | Slug of the document |
| **attributes** | HashMap | no | - | Attribute value |
| **ContentWidgetOptionsAttributeKeyProductId** | String | no | - | Final flag to add to attributes |
| **mapper** | [OnRecommendationModelMapper](/developers/mobile-sdk/class-reference/android/content-widget#contentwidgetrecommendationdatamodel) | no | - | Mapper responsible for mapping RecommendationResponse|
| **recommendationEventType** | RecommendationEventType | no | - | Recommendation event type.
RECOMMENDATION_VIEW_EVENT sends all products in one event. We highly recommend using this type of event in content widget.
RECOMMENDATION_SEEN_EVENT sends each event as a separate event.
|
**Initializers:**
There is a constructor.
public ContentWidgetRecommendationsOptions(@NonNull Activity activity, @NonNull String slug, OnRecommendationModelMapper mapper)
**Methods:**
There are no methods.
---
---
---
### ContentWidgetBaseLayout
Class responsible for widget layout configuration.
**Declared In:**
`com.synerise.sdk.content.widgets.layout.ContentWidgetBaseLayout`
**Declaration:**
```Java
public abstract class ContentWidgetBaseLayout
```
```Kotlin
abstract class ContentWidgetBaseLayout
```
**Properties:**
There are no properties.
**Initializers:**
There are no constructors.
#### Inheriting classes
[ContentWidgetGridLayout](/developers/mobile-sdk/class-reference/android/content-widget#contentwidgetgridlayout)
[ContentWidgetHorizontalSliderLayout](/developers/mobile-sdk/class-reference/android/content-widget#contentwidgetsliderlayout)
**Methods:**
This method defines the value of the cardview size. Any unit is acceptable, but remember to use the same unit across the whole widget.
public void setCardViewSize(int width, int height)
---
This method retrieves the preferred width of a gridView.
public float getPreferredWidth()
---
Setter for preferredWidth of a gridView.
public void setPreferredWidth(float width)
---
---
---
### ContentWidgetSliderLayout
Class responsible for slider layout configuration.
**Declared In:**
`com.synerise.sdk.content.widgets.layout.ContentWidgetHorizontalSliderLayout`
**Declaration:**
```Java
public class ContentWidgetHorizontalSliderLayout extends ContentWidgetBaseLayout
```
```Kotlin
class ContentWidgetHorizontalSliderLayout : ContentWidgetBaseLayout
```
**Properties:**
There are no properties.
**Initializers:**
There is only a default constructor.
**Methods:**
This method defines the cardview size. Any unit is acceptable, but remember to use the same unit across the whole widget.
public void setCardViewSize(int width, int height)
---
This method retrieves the preferred width of a gridView.
public float getPreferredWidth()
---
Setter for the preferredWidth of a gridView.
public void setPreferredWidth(float width)
---
---
---
### ContentWidgetGridLayout
Class responsible for grid layout configuration.
**Declared In:**
`com.synerise.sdk.content.widgets.layout.ContentWidgetGridLayout`
**Declaration:**
```Java
public class ContentWidgetGridLayout extends ContentWidgetBaseLayout
```
```Kotlin
class ContentWidgetGridLayout : ContentWidgetBaseLayout
```
**Properties:**
| Property | Type | Optional | Default | Description |
| --- | --- | --- | --- | --- |
| **itemsPerRow** | int | no | 1 | Number of items per row |
| **cardViewVerticalSpacing** | int | no | 0 | Card view vertical spacing |
| **includeEdgeSpacing** | Boolean | no | false | Defines if edge spacing is included |
**Initializers:**
Constructor with the preferred width of a grid layout.
public ContentWidgetGridLayout(float prefferedWidth)
**Methods:**
This method defines the cardview size. Any unit is acceptable, but remember to use the same unit across the whole widget.
public void setCardViewSize(int width, int height)
---
This method retrieves the preferred width of a gridView.
public float getPreferredWidth()
---
Setter for the preferredWidth of a gridView.
public void setPreferredWidth(float width)
---
---
---
### ContentWidgetBaseItemLayout
Class responsible for card layout configuration.
**Declared In:**
`com.synerise.sdk.content.widgets.layout.ContentWidgetBaseItemLayout`
**Declaration:**
```Java
public abstract class ContentWidgetBaseItemLayout
```
```Kotlin
class abstract ContentWidgetBaseItemLayout
```
#### Inheriting classes
[ContentWidgetBasicProductItemLayout](/developers/mobile-sdk/class-reference/android/content-widget#contentwidgetbasicproductitemlayout)
**Properties:**
| Property | Type | Optional | Default | Description |
| --- | --- | --- | --- | --- |
| **cardViewCornerRadius** | float | no | 0 | Card view corner radius |
| **cardViewElevation** | float | no | 0 | Card view elevation |
**Initializers:**
There is only a default constructor.
**Methods:**
There are no methods.
---
---
### ContentWidgetBasicProductItemLayout
Class responsible for the configuration of item layout.
**Declared In:**
`com.synerise.sdk.content.widgets.layout.ContentWidgetBasicProductItemLayout`
**Declaration:**
```Java
public class ContentWidgetBasicProductItemLayout extends ContentWidgetBaseItemLayout
```
```Kotlin
class ContentWidgetBasicProductItemLayout : ContentWidgetBaseItemLayout
```
**Properties:**
| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| imageHeightToCardHeightRatio | Double | 0.6 | Image height. A ratio of `0.6` means that the image height equals 60% of the entire height of an item |
| imageWidthToCardWidthRatio | Double | 1 | Image width. `1` means that the image width is equal to the width of the item |
| imageScaleType | ImageView.ScaleType | ImageView.ScaleType.CENTER_INSIDE | Scaling type of the image |
| imageMargin | int | 0 | General margin of the image |
| itemLabelStyle | Typeface | - | Typeface of the label |
| itemLabelSize | int | 12 | Size of the label |
| itemLabelColor | int | #000 | Label text color |
| itemLabelMarginLeft | int | 0 | Left margin of the label text |
| itemLabelMarginRight | int | 0 | Right margin of the label text |
| itemLabelMarginBottom | int | 0 | Bottom margin of the label text |
| itemLabelMarginTop | int | 0 | Top margin of the label text |
| cardViewCornerRadius | Float | 0 | Corner radius of the cardView |
| cardViewElevation | Float | 0 | Elevation of the cardView |
| itemTitleStyle | Typeface | - | Typeface of the product title |
| itemTitleSize | int | 12 | Size of the title |
| itemTitleColor | int | #000 | Color of the title text |
| itemTitleMarginLeft | int | 0 | Left margin of the title text |
| itemTitleMarginRight | int | 0 | Right margin of the title text |
| itemTitleMarginBottom | int | 0 | Bottom margin of the title text |
| itemTitleMarginTop | int | 0 | Top margin of the title text |
| itemTitleMaxLines | int | 1 | Maximum displayed lines of the title text |
| itemSubTitleStyle | Typeface | - | Typeface of the product subtitle |
| itemTitleSize | int | 12 | Size of the title |
| itemSubTitleColor | int | #000 | Color of the subtitle text |
| itemSubTitleMarginLeft | int | 0 | Left margin of the subtitle text |
| itemSubTitleMarginRight | int | 0 | Right margin of the subtitle text |
| itemSubTitleMarginBottom | int | 0 | Bottom margin of the subtitle text |
| itemSubTitleMarginTop | int | 0 | Top margin of the subtitle text |
| isItemSubTitleVisible | Boolean | false | Flag indicating visibility of subtitle |
| itemSubTitleGravity | int | Gravity.LEFT | Flag indicating gravity of subtitle |
| itemSubTitleMaxLines | int | 1 | Maximum displayed lines of the subtitle text |
| itemProductIdentifier | Typeface | - | Typeface of the product identifier |
| itemIdentifierSize | int | 12 | Size of the identifier |
| itemIdentifierColor | int | #000 | Color of the identifier text |
| itemIdentifierMarginLeft | int | 0 | Left margin of the identifier text |
| itemIdentifierMarginRight | int | 0 | Right margin of the identifier text |
| itemIdentifierMarginBottom | int | 0 | Bottom margin of the identifier text |
| itemIdentifierMarginTop | int | 0 | Top margin of the identifier text |
| isItemIdentifierVisible | Boolean | false | Flag indicating visibility of identifier |
| itemIdentifierGravity | int | Gravity.LEFT | Flag indicating gravity of identifier |
| itemIdentifierMaxLines | int | 1 | Maximum displayed lines of the identifier text |
| itemLoyaltyPointsStyle | Typeface | - | Typeface of the loyalty points |
| itemLoyaltyPointsSize | int | 12 | Size of the loyalty points |
| itemLoyaltyPointsColor | int | #000 | Color of the loyalty points text |
| itemLoyaltyPointsMarginLeft | int | 0 | Left margin of the loyalty points text |
| itemLoyaltyPointsMarginRight | int | 0 | Right margin of the loyalty points text |
| itemLoyaltyPointsMarginBottom | int | 0 | Bottom margin of the loyalty points text |
| itemLoyaltyPointsMarginTop | int | 0 | Top margin of the loyalty points text |
| isItemLoyaltyPointsVisible | Boolean | false | Flag indicating visibility of loyalty points |
| itemLoyaltyPointsHorizontalPosition | `HorizontalPosition` | HorizontalPosition.LEFT | Flag indicating position of loyaltyPoints |
| itemLoyaltyPointsLabel | String | "Loyalty points" | Label for loyalty points field |
| itemLoyaltyPointsLabelStyle | Typeface | - | Typeface of the loyalty points label |
| itemLoyaltyPointsLabelSize | int | 12 | Size of the loyalty points label |
| itemLoyaltyPointsLabelColor | int | #000 | Color of the loyalty points label text |
| itemLoyaltyPointsLabelMarginLeft | int | 0 | Left margin of the loyalty points label text |
| itemLoyaltyPointsLabelMarginRight | int | 0 | Right margin of the loyalty points label text |
| itemLoyaltyPointsLabelMarginBottom | int | 0 | Bottom margin of the loyalty points label text |
| itemLoyaltyPointsLabelMarginTop | int | 0 | Top margin of the loyalty points label text |
| itemPriceStyle | Typeface | - | Typeface of the price |
| itemPriceSize | int | 12 | Size of the price text |
| itemPriceColor | int | #000 | Color of the price text |
| itemPriceMarginLeft | int | 0 | Left margin of the price text |
| itemPriceMarginRight | int | 0 | Right margin of the price text |
| itemPriceMarginTop | int | 0 | Top margin of the price text |
| itemPriceMarginBottom | int | 0 | Bottom margin of the price text |
| itemPriceCurrencyHorizontalPosition | HorizontalPosition | HorizontalPosition.RIGHT | Flag indicating position of currency |
| itemPriceHorizontalPosition | HorizontalPosition | 0 | Bottom margin of the price text |
| itemSalePriceStyle | Typeface | - | Typeface of the sale price |
| itemSalePriceSize | int | 12 | Size of the sale price |
| itemSalePriceColor | int | #000 | Color of the sale price text |
| itemSalePriceGravity | int | Gravity.LEFT | Gravity of the sale price text |
| itemSalePriceMarginLeft | int | 0 | Left margin of the sale price text |
| itemSalePriceMarginRight | int | 0 | Right margin of the sale price text |
| itemSalePriceMarginTop | int | 0 | Top margin of the sale price text |
| itemSalePriceMarginBottom | int | 0 | Bottom margin of the sale price text |
| itemSalePriceOrientation | int | LinearLayout.HORIZONTAL | Orientation of the sale price text |
| isItemSalePriceVisible | Boolean | false | Flag determining whether to show the sale price or not |
| itemDiscountPercentageLabelStyle | Typeface | - | Typeface of discount percentage label |
| itemDiscountPercentageLabelColor | int | #000 | Color of discount percentage label |
| itemDiscountPercentageLabelSize | int | 12 | Size of the discount percentage label text |
| itemDiscountPercentageLabelMarginLeft | int | 0 | Left margin of the discount percentage label text |
| itemDiscountPercentageLabelMarginRight | int | 0 | Right margin of the discount percentage label text |
| itemDiscountPercentageLabelMarginTop | int | 0 | Top margin of the discount percentage label text |
| itemDiscountPercentageLabelMarginBottom | int | 0 | Bottom margin of the discount percentage label text |
| isItemDiscountPercentageLabelVisible | Boolean | false | Flag determining whether to show the discount percentage label or not |
| itemActionButton | ImageButtonCustomAction | - | Object which stores all information about the ActionButton |
| itemBadge | ContentWidgetBadge | - | Object which stores all information about the Badge |
| imageButtonCustomActionGravity | int | Gravity.TOP | Gravity of the actionButton |
**Initializers:**
There are no initializers.
**Methods:**
Setter for margins in ItemTitle.
public void setItemTitleMargins(int marginLeft, int marginRight, int marginTop, int marginBottom)
---
Setter for margins in ItemPrice.
public void setItemPriceMargins(int marginLeft, int marginRight, int marginTop, int marginBottom)
---
Setter for margins in ItemSalePrice.
public void setItemSalePriceMargins(int marginLeft, int marginRight, int marginTop, int marginBottom)
---
Setter for margins in ItemLabel.
public void setItemLabelMargins(int marginLeft, int marginRight, int marginTop, int marginBottom)
---
Setter for margins in ItemDiscountLabel.
public void setItemDiscountLabelMargins(int marginLeft, int marginRight, int marginTop, int marginBottom)
---
Setter for margins in ItemSubtitle.
public void setItemSubTitleMargins(int marginLeft, int marginRight, int marginTop, int marginBottom)
---
Setter for margins in ItemIdentifier.
public void setItemIdentifierMargins(int marginLeft, int marginRight, int marginTop, int marginBottom)
---
Setter for margins in ItemLoyaltyPoints.
public void setItemLoyaltyPointsMargins(int marginLeft, int marginRight, int marginTop, int marginBottom)
---
Setter for margins in ItemLoyaltyPointsLabel.
public void setItemLoyaltyPointsLabelMargins(int marginLeft, int marginRight, int marginTop, int marginBottom)
---
Setter for itemAction.
public void setItemAction(ImageButtonCustomAction itemImageButton)
---
Setter for the badge.
public void setBadge(ContentWidgetBadge badge)
---
---
### ContentWidgetRecommendationDataModel
Model for recommendations inside a content widget
**Declared In:**
`com.synerise.sdk.content.widgets.dataModel.ContentWidgetRecommendationDataModel`
**Declaration:**
```Java
public class ContentWidgetRecommendationDataModel
```
```Kotlin
class ContentWidgetRecommendationDataModel
```
**Properties:**
There are no properties.
**Initializers:**
Constructor:
```java
public static void removeInAppListener()
```
**Parameters:**
No parameters.
**Return Value:**
No value returned.
**Example:**
```java
Injector.removeInAppListener();
```
```kotlin
Injector.removeInAppListener()
```
## Close in-app message
---
Closes an in-app message and sends an `inApp.discard` event.
Usage examples:
- Closing a top bar or bottom bar when the user taps outside the in-app area.
- Automatically dismissing messages when navigating away from a screen.
- Controlling in-app visibility based on app logic for a smoother user experience.
| | **iOS SDK** | **Android SDK** | **React Native SDK** | **Flutter SDK** |
| ----------------------------------------------- | ----------- | --------------- | -------------------- | --------------- |
| Introduced in: | 5.7.0 | 6.7.0 | 1.5.0 | 2.5.0 |
**Method name:**
Injector.closeInAppMessage(campaignHash)
**Declaration:**
public static void closeInAppMessage(String campaignHash)
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| ---------------- | ------ | --------- | ------- | ---------------------------------------- |
| **campaignHash** | string | yes | - | Unique identifier of the in-app campaign |
**Return value:**
No value returned.
**Example**:
## Register for push notifications
---
This method passes the Firebase Token to Synerise for notifications.
- You should call this method every time the user changes the system or application consent for notifications.
- The API key must have the `API_PERSONAL_DEVICE_CLIENT_UPDATE` permission from the **Client** group.
- If the registration fails, the SDK requests a token update again by a listener/delegate method ([Android](/developers/mobile-sdk/listeners-and-delegates/android-listeners#on-register-for-push-listener), [iOS](/developers/mobile-sdk/listeners-and-delegates/ios-delegates#synerise-delegate-register-for-push-notifications-is-needed), [React Native](/developers/mobile-sdk/listeners-and-delegates/react-native-listeners#notifications-listener), [Flutter](/developers/mobile-sdk/listeners-and-delegates/flutter-listeners#notifications-listener)).
```Kotlin
val call = Client.registerForPush(refreshedToken, true)
call.execute({ Log.d(TAG, "Register for Push succeed: " + refreshedToken) },
{ apiError-> Log.w(TAG, "Register for push failed: " + refreshedToken) })
```
## Register for push notifications without agreement
---
This method passes the Firebase Token to Synerise for notifications and doesn't update the agreement of the profile.
| | **iOS SDK** | **Android SDK** | **React Native SDK** | **Flutter SDK** |
| --- | --- | --- | --- | --- |
| Introduced in: | 4.14.0 | 5.7.1 | 0.15.0 | 1.1.0 |
The API key must have the `API_PERSONAL_DEVICE_CLIENT_UPDATE` permission from the **Client** group.
If the registration fails, the SDK requests a token update again by a listener/delegate method ([Android](/developers/mobile-sdk/listeners-and-delegates/android-listeners#on-register-for-push-listener), [iOS](/developers/mobile-sdk/listeners-and-delegates/ios-delegates#synerise-delegate-register-for-push-notifications-is-needed), [React Native](/developers/mobile-sdk/listeners-and-delegates/react-native-listeners#notifications-listener), [Flutter](/developers/mobile-sdk/listeners-and-delegates/flutter-listeners#notifications-listener)).
```Kotlin
val call = Client.registerForPush(refreshedToken)
call.execute({ Log.d(TAG, "Register for Push succeed: " + refreshedToken) },
{ apiError-> Log.w(TAG, "Register for push failed: " + refreshedToken) })
```
## Check if push notification is from Synerise
---
This method verifies if a notification was sent by Synerise.
**Method name:**
Injector.isSynerisePush(pushPayload);
**Declaration:**
```java
public static boolean isSynerisePush(Map pushPayload)
```
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **pushPayload** | Map | yes | - | Key-Value map of data. The "issuer" key must be set to "Synerise". |
**Return Value:**
Boolean indicating if the incoming push contains an "issuer" key with the "Synerise" value.
**Example:**
```kotlin
var isSynerisePush = Injector.isSynerisePush(data)
```
## Check if push notification is a Simple Push Campaign
---
This method verifies if a notification’s sender is Synerise and if the notification is a Simple Push campaign
**Method name:**
Injector.isSyneriseSimplePush(pushPayload);
**Declaration:**
```java
public static boolean isSyneriseSimplePush(Map pushPayload)
```
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **pushPayload** | Map | yes | - | Key-Value map of data. The "issuer" key must be set to "Synerise". |
**Return Value:**
Boolean indicating if the incoming push contains a "content-type" key with the "simple-push" value.
**Example:**
```kotlin
var isSyneriseSimplePush = Injector.isSyneriseSimplePush(data)
```
## Check if push notification is a Silent Command
---
This method verifies if a notification’s sender is Synerise and if the notification is a Silent Command.
**Method name:**
Injector.isSilentCommand(pushPayload);
**Declaration:**
```java
public static boolean isSilentCommand(Map pushPayload)
```
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **pushPayload** | Map | yes | - | Key-Value map of data. The "issuer" key must be set to "Synerise". |
**Return Value:**
Boolean indicating if the incoming push contains a "content-type" key with the "silent-command" value.
**Example:**
```kotlin
var isSilentCommand = Injector.isSilentCommand(data)
```
## Get a Silent Command
---
Method that converts push payload into a SilentCommand object.
**Method name:**
Injector.getSilentCommand(payload);
**Declaration:**
```java
public static SilentCommand getSilentCommand(Map payload) throws ValidationException
```
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **payload** | Map | yes | - | payload received from push |
**Return Value:**
[SilentCommand](/developers/mobile-sdk/class-reference/android/campaigns#silentcommand) object, may be null if the payload is not a `SilentCommand` payload.
**Example:**
```kotlin
var silentCommand = Injector.getSilentCommand(payload)
```
## Check if push notification is a Silent SDK Command
---
This method verifies if a notification's sender is Synerise and if the notification is a Silent SDK Command.
**Method name:**
Injector.isSilentCommandSdk(pushPayload);
**Declaration:**
```java
public static boolean isSilentCommandSdk(Map pushPayload)
```
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **pushPayload** | Map | yes | - | Key-Value map of data. The "issuer" key must be set to "Synerise". |
**Return Value:**
Boolean indicating if the incoming push contains a "content-type" key with the "silent-sdk-command" value.
**Example:**
```kotlin
var isSilentCommandSdk = Injector.isSilentCommandSdk(data)
```
## Check if push notification is encrypted
---
This method verifies if a notification is encrypted.
**Method name:**
Injector.isPushEncrypted(pushPayload);
**Declaration:**
```java
public static boolean isPushEncrypted(Map pushPayload)
```
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **pushPayload** | Map | yes | - | Key-Value map of data |
**Return Value:**
Boolean indicating if the incoming push is encrypted by Synerise.
**Example:**
```java
public static boolean handlePushPayload(Bundle bundle)
public static boolean handlePushPayload(Map pushPayload)
```
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **bundle** | Bundle | yes | - | Bundle of data. Key "issuer" must be set to "Synerise". |
| **pushPayload** | Map | yes | - | Key-Value map of data. The "issuer" key must be set to "Synerise". |
**Return Value:**
Boolean indicating if the incoming push contains an "issuer" key with the value "Synerise".
**Example:**
```java
public static IDataApiCall> getPushes()
```
**Parameters:**
No parameters.
**Return Value:**
[IDataApiCall](/developers/mobile-sdk/method-reference/android/public-interfaces#idataapicall)> with a parameterized list of SynerisePushResponse to execute a request.
**Example:**
```java
public static void fetchBanners()
public static void fetchBanners(@NonNull final DataActionListener> successListener,
@NonNull final DataActionListener errorListener)
```
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **successListener** | DataActionListener> | yes | - | Success data callback with valid banners. |
| **errorListener** | DataActionListener<[ApiError](/developers/mobile-sdk/class-reference/android/miscellaneous#apierror)> | yes | - | Error callback with an ApiError instance. |
**Return Value:**
No value is returned.
**Example:**
**Parameters:**
No parameters.
**Return Value:**
List<[TemplateBanner](/developers/mobile-sdk/class-reference/android/campaigns#templatebanner)> of cached banners.
**Example:**
```java
List bannerList = Injector.getBanners();
```
```kotlin
var bannerList = Injector.getBanners()
```
```java
public static void showBanner(TemplateBanner banner, boolean markPresented)
```
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **banner** | [TemplateBanner](/developers/mobile-sdk/class-reference/android/campaigns#templatebanner) | yes | - | Banner to display |
| **markPresented** | boolean | yes | - | Flag indicating if the banner should be marked as presented and not be presented the next time |
**Return Value:**
No value returned.
**Example:**
**Parameters:**
No parameters.
**Return Value:**
No return value.
**Example:**
```java
Injector.getWalkthrough();
```
```kotlin
Injector.getWalkthrough()
```
### Show Walkthrough {#show-walkthrough}
---
This method shows a walkthrough when it is loaded.
| | **iOS SDK** | **Android SDK** | **React Native SDK** | **Flutter SDK** |
| --- | --- | --- | --- | --- |
| Removed in: | 5.0.0 | 6.0.0 | 1.0.0 | 2.0.0 |
**Method name:**
Injector.showWalkthrough();
**Declaration:**
```java
public static boolean showWalkthrough()
```
**Parameters:**
No parameters.
**Return Value:**
Boolean value is returned. `true` if the loaded or cached Walkthrough was presented, `false` otherwise.
**Example:**
```java
Injector.showWalkthrough();
```
```kotlin
Injector.showWalkthrough()
```
### Check if Walkthrough is loaded {#check-if-walkthrough-is-loaded}
---
This method checks if a walkthrough is loaded.
| | **iOS SDK** | **Android SDK** | **React Native SDK** | **Flutter SDK** |
| --- | --- | --- | --- | --- |
| Removed in: | 5.0.0 | 6.0.0 | 1.0.0 | 2.0.0 |
**Method name:**
Injector.isWalkthroughLoaded();
**Declaration:**
```java
public static boolean isWalkthroughLoaded()
```
**Parameters:**
No parameters.
**Return Value:**
Boolean value is returned. `true` if Walkthrough is already loaded, `false` otherwise.
**Example:**
```kotlin
var isWalkthroughLoaded = Injector.isWalkthroughLoaded()
```
### Check if loaded Walkthrough is unique {#check-if-loaded-walkthrough-is-unique}
---
This method checks if the walkthrough is unique compared to the previous one.
| | **iOS SDK** | **Android SDK** | **React Native SDK** | **Flutter SDK** |
| --- | --- | --- | --- | --- |
| Removed in: | 5.0.0 | 6.0.0 | 1.0.0 | 2.0.0 |
**Method name:**
Injector.isLoadedWalkthroughUnique();
**Declaration:**
```java
public static boolean isLoadedWalkthroughUnique()
```
**Parameters:**
No parameters.
**Return Value:**
Returns `true` if the loaded Walkthrough is loaded and different than previously presented, `false` otherwise.
**Example:**
### Remove Banner listener {#remove-banner-listener}
---
Remove banner listener to stop receiving callbacks.
It is recommended to call this method when your Activity is stopped.
| | **iOS SDK** | **Android SDK** | **React Native SDK** | **Flutter SDK** |
| --- | --- | --- | --- | --- |
| Removed in: | n/a | 6.0.0 | n/a | n/a |
**Method name:**
Injector.removeBannerListener();
**Declaration:**
```java
public static void removeBannerListener()
```
**Parameters:**
No parameters.
**Return Value:**
No value returned.
**Example:**
```java
Injector.removeBannerListener();
```
```kotlin
Injector.removeBannerListener()
```
# Promotions and Vouchers
---
## Promotions
---
### Get all promotions of a customer
---
This method retrieves all available promotions that are defined for a customer.
The API key must have the `PROMOTIONS_DETAILS_FOR_CLIENT_READ` permission from the **Client** group.
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **onSuccess** | Function | no | - | Function to be executed when the operation is completed successfully |
| **onError** | Function | no | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **apiQuery** | [PromotionsApiQuery](/developers/mobile-sdk/class-reference/react-native/promotions-and-vouchers#promotionsapiquery) | yes | - | [PromotionsApiQuery](/developers/mobile-sdk/class-reference/react-native/promotions-and-vouchers#promotionsapiquery) object responsible for storing all query parameters |
| **onSuccess** | Function | no | - | Function to be executed when the operation is completed successfully |
| **onError** | Function | no | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **uuid** | string | yes | - | UUID of the promotion |
| **onSuccess** | Function | no | - | Function to be executed when the operation is completed successfully |
| **onError** | Function | no | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **code** | string | yes | - | Code of the promotion |
| **onSuccess** | Function | no | - | Function to be executed when the operation is completed successfully |
| **onError** | Function | no | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **uuid** | string | yes | - | UUID of the promotion |
| **onSuccess** | Function | no | - | Function to be executed when the operation is completed successfully |
| **onError** | Function | no | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **code** | string | yes | - | Code of the promotion |
| **onSuccess** | Function | no | - | Function to be executed when the operation is completed successfully |
| **onError** | Function | no | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **promotionsIdentifiers** | Array<[PromotionIdentifier](/developers/mobile-sdk/class-reference/react-native/promotions-and-vouchers#promotionidentifier)> | yes | - | List of promotion identifiers |
| **onSuccess** | Function | no | - | Function to be executed when the operation is completed successfully |
| **onError** | Function | no | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **uuid** | string | yes | - | UUID of the promotion |
| **onSuccess** | Function | no | - | Function to be executed when the operation is completed successfully |
| **onError** | Function | no | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **code** | string | yes | - | Code of the promotion |
| **onSuccess** | Function | no | - | Function to be executed when the operation is completed successfully |
| **onError** | Function | no | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **promotionsIdentifiers** | Array<[PromotionIdentifier](/developers/mobile-sdk/class-reference/react-native/promotions-and-vouchers#promotionidentifier)> | yes | - | List of promotion identifiers |
| **onSuccess** | Function | no | - | Function to be executed when the operation is completed successfully |
| **onError** | Function | no | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
## Vouchers
---
### Get or assign voucher from pool
---
This method retrieves an assigned voucher code or assigns a voucher from a pool identified by UUID to the customer.
Once a voucher is assigned using this method, **the same** voucher is returned for the profile every time the method is called.
When the voucher is assigned for the first time, a [voucherCode.assigned](/docs/assets/events/event-reference/loyalty#vouchercodeassigned) event is produced.
The API key must have the `VOUCHERS_ITEM_ASSIGN_CREATE` and `VOUCHERS_ITEM_ASSIGN_READ` permission from the **Assign** group.
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **poolUuid** | string | yes | - | Unique identifier of a code pool |
| **onSuccess** | Function | no | - | Function to be executed when the operation is completed successfully |
| **onError** | Function | no | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
### Assign voucher code from pool
---
This method assigns a voucher from a pool identified by UUID to the profile.
Every request returns a **different code** until the pool is empty.
A [voucherCode.assigned](/docs/assets/events/event-reference/loyalty#vouchercodeassigned) event is produced.
Returns the HTTP 416 status code when the pool is empty.
The API key must have the `VOUCHERS_ITEM_ASSIGN_CREATE` and `VOUCHERS_ITEM_ASSIGN_READ` permission from the **Assign** group.
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **poolUuid** | string | yes | - | Unique identifier of a code pool |
| **onSuccess** | Function | no | - | Function to be executed when the operation is completed successfully |
| **onError** | Function | no | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **onSuccess** | Function | no | - | Function to be executed when the operation is completed successfully |
| **onError** | Function | no | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
# Content Widget
### ContentWidget
Content Widget is a feature in our Software Development Kit that allows you to embed an easily customizable view with various types of content in your application.
**Declared In:**
Headers/SNRContentWidget.h
**Related To:**
[ContentWidgetOptions](/developers/mobile-sdk/class-reference/ios/content-widget#contentwidgetoptions)
[ContentWidgetAppearance](/developers/mobile-sdk/class-reference/ios/content-widget#contentwidgetappearance)
[ContentWidgetDelegate](/developers/mobile-sdk/listeners-and-delegates/ios-delegates#content-widget-delegate)
**Inherits From:**
[NSObject](https://developer.apple.com/documentation/objectivec/nsobject)
**Declaration:**
**Methods:**
Starts operation of fetching data and creates view structure of widget.
```Swift
func load()
```
```Objective-C
- (void)load
```
---
Checks whether widget is loaded with success.
```Swift
func isLoaded() -> Bool
```
```Objective-C
- (BOOL)isLoaded
```
---
Gets root view of whole widget view structure.
```Swift
func getView() -> UIView
```
```Objective-C
- (UIView *)getView
```
---
---
### ContentWidgetAppearance
The **ContentWidgetAppearance** class is responsible for defining the appearance of the widget.
**Declared In:**
Headers/SNRContentWidgetAppearance.h
**Related To:**
[SNRContentWidget](/developers/mobile-sdk/class-reference/ios/content-widget#contentwidget)
[SNRContentWidgetLayout](/developers/mobile-sdk/class-reference/ios/content-widget#contentwidgetlayout)
[SNRContentWidgetHorizontalSliderLayout](/developers/mobile-sdk/class-reference/ios/content-widget#contentwidgethorizontalsliderlayout)
[SNRContentWidgetGridLayout](/developers/mobile-sdk/class-reference/ios/content-widget#contentwidgetgridlayout)
[SNRContentWidgetItemLayout](/developers/mobile-sdk/class-reference/ios/content-widget#contentwidgetitemlayout)
[SNRContentWidgetBasicProductItemLayout](/developers/mobile-sdk/class-reference/ios/content-widget#contentwidgetbasicproductitemlayout)
**Inherits From:**
[NSObject](https://developer.apple.com/documentation/objectivec/nsobject)
**Declaration:**
```Swift
class ContentWidgetAppearance: NSObject
```
---
---
### ContentWidgetRecommendationsOptions
The **ContentWidgetRecommendationsOptions** class is responsible for defining the business logic options of the widget.
**Declared In:**
Headers/SNRContentWidgetOptions.h
**Related To:**
[SNRContentWidget](/developers/mobile-sdk/class-reference/ios/content-widget#contentwidget)
**Inherits From:**
[NSObject](https://developer.apple.com/documentation/objectivec/nsobject)
**Declaration:**
```Swift
class ContentWidgetRecommendationsOptions: NSObject
```
**Properties:**
| Property | Type | Optional | Description |
| --- | --- | --- | --- |
| **backgroundColor** | UIColor | yes | Background color of a widget |
| **insets** | UIEdgeInsets | yes | Inner widget margins in pt |
| **itemSize** | Size | yes | Size of a single item in pt |
| **numberOfItems** | Int | yes | It returns the number of items after the widget is loaded |
**numberOfItems** property is read-only.
---
---
### ContentWidgetHorizontalSliderLayout
This layout is intended to present recommendations in a fixed-hight horizontal scrollable slider.
**Declared In:**
Headers/SNRContentWidgetHorizontalSliderLayout.h
**Related To:**
[SNRContentWidget](/developers/mobile-sdk/class-reference/ios/content-widget#contentwidget)
**Inherits From:**
[ContentWidgetLayout](/developers/mobile-sdk/class-reference/ios/content-widget#contentwidgetlayout)
**Declaration:**
```Swift
class ContentWidgetHorizontalSliderLayout: ContentWidgetLayout
```
**Properties:**
| Property | Type | Optional | Description |
| --- | --- | --- | --- |
| **backgroundColor** | UIColor | no | Background color of an item |
| **cornerRadius** | Float | no | Radius of the item corners |
| **borderWidth** | Float | no | Width of the item’s border |
| **borderColor** | UIColor | no | Color of the item’s border |
| **shadowColor** | UIColor | no | Color of the item’s shadow |
---
---
### ContentWidgetBasicProductItemLayout
This is the basic layout for items. It contains: the image, the title, and the price from the uploaded data.
**Declared In:**
Headers/SNRContentWidgetBasicProductItemLayout.h
**Related To:**
[ContentWidget](/developers/mobile-sdk/class-reference/ios/content-widget#contentwidget)
[ContentWidgetAppearance](/developers/mobile-sdk/class-reference/ios/content-widget#contentwidgetappearance)
**Inherits From:**
[ContentWidgetItemLayout](/developers/mobile-sdk/class-reference/ios/content-widget#contentwidgetitemlayout)
**Declaration:**
```Swift
class ContentWidgetBasicProductItemLayout: ContentWidgetItemLayout
```
**Properties:**
| Property | Type | Optional | Description |
| --- | --- | --- | --- |
| **imageWidthRatio** | Float | no | Image width. A ratio of 1.0 means that the image width equals to 100% of the entire height of the item |
| **imageHeightRatio** | Float | no | Image height. A ratio of 0.3 means that image height equals to 30% of the entire height of the item |
| **imageBackground** | UIColor | no | Background color of the image |
| **titleInsets** | UIEdgeInsets | no | Inner margins of the title label |
| **titleFont** | UIFont | no | Font of the item title label |
| **titleFontColor** | UIColor | no | Color of the title label |
| **titleAlignment** | NSTextAlignment | no | Alignment of the title label |
| **priceInsets** | UIEdgeInsets | no | Inner margins of the price label |
| **priceFont** | UIFont | no | Font of the price label |
| **priceFontColor** | UIColor | no | Color of the price label |
| **priceAlignment** | NSTextAlignment | no | Alignment of the price label |
| **priceGroupSeparator** | String | no | Separator of price group |
| **priceDecimalSeparator** | String | no | Separator of price decimal |
| **isSalePriceVisible** | Bool | no | Flag determining whether to show the sale price label or not |
| **salePriceOrientation** | UILayoutConstraintAxis | no | Orientation of the sale price label |
| **salePriceMargin** | Float | no | Margin between the price label and the sale price label |
| **regularPriceFont** | UIFont | no | Font of the regular price label |
| **regularPriceFontColor** | UIColor | no | Color of the regular price label |
| **salePriceFont** | UIFont | no | Font of the sale price label |
| **salePriceFontColor** | UIColor | no | Color of the sale price label |
| **actionButton** | ContentWidgetImageButtonCustomAction | no | Optional button for your own custom action |
| **actionButtonPosition** | CGPoint | no | Position of the action button |
---
---
### ContentWidgetBaseCustomAction
Main widget custom action abstract class for inheriting classes.
**Declared In:**
Headers/SNRContentWidgetItemLayout.h
**Related To:**
[ContentWidget](/developers/mobile-sdk/class-reference/ios/content-widget#contentwidget)
[ContentWidgetAppearance](/developers/mobile-sdk/class-reference/ios/content-widget#contentwidgetappearance)
**Inherits From:**
[NSObject](https://developer.apple.com/documentation/objectivec/nsobject)
**Declaration:**
```Swift
class ContentWidgetBaseCustomAction: NSObject
```
**Properties:**
| Property | Type | Optional | Description |
| --- | --- | --- | --- |
| **predefinedActionType** | ContentWidgetBaseCustomActionPredefiniedActionType | no | It determines which event is on click |
---
---
### ContentWidgetImageButtonCustomAction
**ContentWidgetImageButtonCustomAction** is used to add an image button to your widget (only if the item layout allows). You can add a button with a single state or make it selectable.
**Declared In:**
Headers/SNRContentWidgetImageButtonCustomAction.h
**Related To:**
[ContentWidget](/developers/mobile-sdk/class-reference/ios/content-widget#contentwidget)
[ContentWidgetAppearance](/developers/mobile-sdk/class-reference/ios/content-widget#contentwidgetappearance)
**Inherits From:**
[ContentWidgetBaseCustomAction](/developers/mobile-sdk/class-reference/ios/content-widget#contentwidgetbasecustomaction)
**Declaration:**
```Swift
class ContentWidgetImageButtonCustomAction: NSObject
```
**Properties:**
| Property | Type | Optional | Description |
| --- | --- | --- | --- |
| **size** | Size | yes | Button size |
| **backgroundColor** | UIColor | yes | Background color of the button |
| **tintColor** | UIColor | yes | Fill color of the button’s image, if an asset supports it |
| **image** | UIImage | yes | Button image |
| **isSelectable** | Bool | yes | Flag determining whether the button is selectable |
| **selectedImage** | UIImage | yes | Image of the button when the button is selected |
| **isSelected** | ContentWidgetImageButtonCustomActionIsSelectedBlock | yes | Block/closure to be executed when the widget needs to determine the state of a button in the cell |
| **onReceiveClick** | ContentWidgetImageButtonCustomActionReceiveClickBlock | yes | Block/closure to be executed when the button is clicked |
---
---
### ContentWidgetBaseCustomActionPredefiniedActionType
**Declared In:**
Headers/SNRContentWidgetBaseCustomAction.h
**Declaration:**
```Swift
enum ContentWidgetBaseCustomActionPredefiniedActionType: Int {
none,
sendLikeEvent
}
```
# Loyalty
Loyalty in mobile SDK covers two features:
- [Promotions](/developers/mobile-sdk/loyalty#promotions) - In Synerise, Promotions lets you:
- introduce a system of awarding and spending loyalty points so your profiles can use them and purchase your products.
- use promotions as a distribution channel for discounted products.
Read more about [implementing promotions in your store](/docs/ai-hub/promotions/introduction-to-promotions).
- [Vouchers](/developers/mobile-sdk/loyalty#vouchers) - In Synerise, you can create a pool of discount codes which you can distribute through the mobile application.
Read more about [voucher pools](/docs/assets/code-pools).
## Promotions
---
### Overview {id=promotions-overview}
Promotions let you fetch special offers for your profiles.
Documentation on how to prepare promotions is available [here](/docs/ai-hub/promotions/creating-promotions).
**Class reference** for promotions: [Android](/developers/mobile-sdk/class-reference/android/promotions-and-vouchers#promotions), [iOS](/developers/mobile-sdk/class-reference/ios/promotions-and-vouchers#promotions), [React Native](/developers/mobile-sdk/class-reference/react-native/promotions-and-vouchers#promotions), [Flutter](/developers/mobile-sdk/class-reference/flutter/promotions-and-vouchers#promotions).
**Method reference** for promotions: [Android](/developers/mobile-sdk/method-reference/android/promotions), [iOS](/developers/mobile-sdk/method-reference/ios/promotions), [React Native](/developers/mobile-sdk/method-reference/react-native/promotions), [Flutter](/developers/mobile-sdk/method-reference/flutter/promotions).
### Basic implementation {id=promotions-basic-implementation}
The example below is the basic implementation and retrieves all promotions for a profile, without any parameters to filter them.
### Advanced implementation {id=promotions-advanced-implementation}
If you want to have full possibilities of configuring the query for promotions, getting items using the `PromotionsApiQuery` is the best way to achieve it.
The table explains the filtering options available when fetching promotions.
| Property | Type | Default | Description |
| --- | --- | --- | --- |
| statuses | [`List`](/developers/mobile-sdk/class-reference/android/promotions-and-vouchers#promotionstatus) | [] | List of statuses for query |
| types | [`List`](/developers/mobile-sdk/class-reference/android/promotions-and-vouchers#promotiontype) | [] | List of types for query |
| sortParameters | `LinkedHashMap` | [] | Specifies [sorting rules](#promotion-sorting-options) for items in the response |
| limit | `Int` | 100 | Limit of items per page in the response |
| page | `Int` | 1 | Page number |
| includeMeta | `Boolean` | false | Specifies if metadata should be included in the response |
| Property | Type | Default | Description |
| --- | --- | --- | --- |
| statuses | [`[PromotionStatus]`](/developers/mobile-sdk/class-reference/ios/promotions-and-vouchers/#promotionstatus) | [] | List of statuses for query |
| types | [`[PromotionType]`](/developers/mobile-sdk/class-reference/ios/promotions-and-vouchers/#promotiontype) | [] | List of types for query |
| sorting | `[[SNRPromotionSortingKey: SNRApiQuerySortingOrderString]]` | [] | Specifies [sorting rules](#promotion-sorting-options) for items in the response |
| limit | `Int` | 100 | Limit of items per page in the response |
| page | `Int` | 1 | Page number |
| includeMeta | `Bool` | false | Specifies if meta data should be included in the response |
| Property | Type | Default | Description |
| --- | --- | --- | --- |
| statuses | [`Array`](/developers/mobile-sdk/class-reference/react-native/promotions-and-vouchers#promotionstatus) | [] | List of statuses for query |
| types | [`Array`](/developers/mobile-sdk/class-reference/react-native/promotions-and-vouchers#promotiontype) | [] | List of types for query |
| sorting | `Array` | [] | Specifies [sorting rules](#promotion-sorting-options) for items in the response |
| limit | `number` | 100 | Limit of items per page in the response |
| page | `number` | 1 | Page number |
| includeMeta | `boolean` | false | Specifies if meta data should be included in the response |
| Property | Type | Default | Description |
| --- | --- | --- | --- |
| statuses | [`List`](/developers/mobile-sdk/class-reference/flutter/promotions-and-vouchers#promotionstatus) | [] | List of statuses for query |
| types | [`List`](/developers/mobile-sdk/class-reference/flutter/promotions-and-vouchers#promotiontype) | [] | List of types for query |
| sorting | `List` | [] | Specifies [sorting rules](#promotion-sorting-options) for items in the response |
| limit | `int` | 100 | Limit of items per page in the response |
| page | `int` | 1 | Page number |
| includeMeta | `bool` | false | Specifies if meta data should be included in the response |
The example below is the advanced implementation and fetches promotions using `PromotionsApiQuery` object.
```java
List statuses = new ArrayList<>();
if (activeBox.isChecked()) statuses.add(PromotionStatus.ACTIVE);
if (assignedBox.isChecked()) statuses.add(PromotionStatus.ASSIGNED);
if (redeemedBox.isChecked()) statuses.add(PromotionStatus.REDEEMED);
List types = new ArrayList<>();
if (generalBox.isChecked()) types.add(PromotionType.GENERAL);
if (customBox.isChecked()) types.add(PromotionType.CUSTOM);
if (membersOnlyBox.isChecked()) types.add(PromotionType.MEMBERS_ONLY);
PromotionsApiQuery query = new PromotionsApiQuery();
query.limit = 100;
query.statuses = statuses;
query.types = types;
query.page = page;
query.includeMeta = includeButton.isChecked();
LinkedHashMap sortParams = new LinkedHashMap<>();
sortParams.put(PromotionSortingKey.TYPE, ApiQuerySortingOrder.ASCENDING);
sortParams.put(PromotionSortingKey.CREATED_AT, ApiQuerySortingOrder.ASCENDING);
sortParams.put(PromotionSortingKey.EXPIRE_AT, ApiQuerySortingOrder.DESCENDING);
query.setSortParameters(sortParams);
IDataApiCall apiCall = Promotions.getPromotions(query);
apiCall.execute(onSuccess, new DataActionListener() {
@Override
public void onDataAction(ApiError apiError) {
// error handling
}
});
```
```kotlin
val statuses = ArrayList()
if (activeBox.isChecked()) statuses.add(PromotionStatus.ACTIVE)
if (assignedBox.isChecked()) statuses.add(PromotionStatus.ASSIGNED)
if (redeemedBox.isChecked()) statuses.add(PromotionStatus.REDEEMED)
val types = ArrayList()
if (generalBox.isChecked()) types.add(PromotionType.GENERAL)
if (customBox.isChecked()) types.add(PromotionType.CUSTOM)
if (membersOnlyBox.isChecked()) types.add(PromotionType.MEMBERS_ONLY)
val query = PromotionsApiQuery()
query.limit = 100
query.statuses = statuses
query.types = types
query.page = page
query.includeMeta = includeButton.isChecked()
val sortParams = LinkedHashMap()
sortParams.put(PromotionSortingKey.TYPE, ApiQuerySortingOrder.ASCENDING)
sortParams.put(PromotionSortingKey.CREATED_AT, ApiQuerySortingOrder.ASCENDING)
sortParams.put(PromotionSortingKey.EXPIRE_AT, ApiQuerySortingOrder.DESCENDING)
query.setSortParameters(sortParams)
val apiCall = Promotions.getPromotions(query)
apiCall.execute(onSuccess, object:DataActionListener() {
fun onDataAction(apiError:ApiError) {
// error handling
}
})
```
### Promotion type
The promotion type options correspond to the [promotion type options available in the Synerise application](/docs/ai-hub/promotions/creating-promotions-for-entire-basket#type--limits) in the creating promotion form.
- **GENERAL** - promotions are available to all profiles.
- **MEMBERS_ONLY** - promotions are available to profiles who joined a loyalty program.
- **HANDBILL** - promotions which can only be selected by the [AI promotion engine for a customer](/docs/ai-hub/personalized-promotions).
- **CUSTOM** - custom promotions are a category that has custom configuration, tailored for chosen profiles.
Constants in the SDK correlated with promotion types:
| Android | iOS | React Native | Flutter |
| --- | --- | --- | --- |
| `PromotionType.GENERAL` | `SNR_PROMOTION_TYPE_GENERAL` | `PromotionType.General` | `PromotionType.general` |
| `PromotionType.MEMBERS_ONLY` | `SNR_PROMOTION_TYPE_MEMBERS_ONLY` | `PromotionType.MembersOnly` | `PromotionType.membersOnly` |
| `PromotionType.CUSTOM` | `SNR_PROMOTION_TYPE_CUSTOM` | `PromotionType.Custom` | `PromotionType.custom` |
| `PromotionType.HANDBILL` | `SNR_PROMOTION_TYPE_HANDBILL` | `PromotionType.Handbill` | `PromotionType.handbill` |
### Promotion status
- **ACTIVE** - promotion is activated by the profile.
- **ASSIGNED** - promotion is assigned to a profile and visible to them.
- **REDEEMED** - promotion is redeemed and finished for the profile.
Constants in the SDK correlated with promotion statuses:
| Android | iOS | React Native | Flutter |
| --- | --- | --- | --- |
| `PromotionStatus.ACTIVE` | `SNR_PROMOTION_STATUS_ACTIVE` | `PromotionStatus.Active` | `PromotionStatus.active` |
| `PromotionStatus.ASSIGNED` | `SNR_PROMOTION_STATUS_ASSIGNED` | `PromotionStatus.Assigned` | `PromotionStatus.assigned` |
| `PromotionStatus.REDEEMED` | `SNR_PROMOTION_STATUS_REDEEMED` | `PromotionStatus.Redeemed` | `PromotionStatus.redeemed` |
### Promotion sorting options
You can set an array of sorting options. Each sorting option is a key-value pair. The key is the sorting key constant and the value is the sorting order.
Promotion-related sorting constants:
- **EXPIRE_AT** - time when the promotion expires.
- **CREATED_AT** - time when the promotion was created.
- **LASTING_AT** - time when the promotion stops being active for the profile.
- **REQUIRE_REDEEMED_POINTS** - how many loyalty points are needed to redeem the promotion.
- **UPDATED_AT** - time when the promotion was last updated.
- **TYPE** - type of the promotion.
- **PRIORITY** - priority of the promotion.
Constants in the SDK correlated with promotion sorting options:
| Android | iOS | React Native | Flutter |
| --- | --- | --- | --- |
| `PromotionSortingKey.EXPIRE_AT` | `SNR_PROMOTION_SORTING_KEY_EXPIRE_AT` | `PromotionSortingKey.ExpireAt` | `PromotionSortingKey.expireAt` |
| `PromotionSortingKey.CREATED_AT` | `SNR_PROMOTION_SORTING_KEY_CREATED_AT` | `PromotionSortingKey.CreatedAt` | `PromotionSortingKey.createdAt` |
| `PromotionSortingKey.LASTING_AT` | `SNR_PROMOTION_SORTING_KEY_LASTING_AT` | `PromotionSortingKey.LastingAt` | `PromotionSortingKey.lastingAt` |
| `PromotionSortingKey.REQUIRE_REDEEMED_POINTS` | `SNR_PROMOTION_SORTING_KEY_REQUIRE_REDEEMED_POINTS` | `PromotionSortingKey.requireRedeemPoints` | `PromotionSortingKey.ExpireAt` |
| `PromotionSortingKey.UPDATED_AT` | `SNR_PROMOTION_SORTING_KEY_UPDATED_AT` | `PromotionSortingKey.UpdatedAt` | `PromotionSortingKey.updatedAt` |
| `PromotionSortingKey.TYPE` | `SNR_PROMOTION_SORTING_KEY_TYPE` | `PromotionSortingKey.Type` | `PromotionSortingKey.type` |
| `PromotionSortingKey.PRIORITY` | `SNR_PROMOTION_SORTING_KEY_PRIORITY` | `PromotionSortingKey.Priority` | `PromotionSortingKey.priority` |
You can sort each of the above ascending or descending by using the values:
- **ASCENDING**
- **DESCENDING**
Constants in the SDK correlated with sorting order values:
| Android | iOS | React Native | Flutter |
| --- | --- | --- | --- |
| `ApiQuerySortingOrder.ASCENDING` | `SNR_API_QUERY_SORTING_ASC` | `ApiQuerySortingOrder.Ascending` | `ApiQuerySortingOrder.ascending` |
| `ApiQuerySortingOrder.DESCENDING` | `SNR_API_QUERY_SORTING_DESC` | `ApiQuerySortingOrder.Descending` | `ApiQuerySortingOrder.descending` |
You can add a number of key-value pairs for sorting.
### Working with single promotions
---
In addition to getting all promotions or a filtered list, you can get a single promotion.
You can get a single promotion by:
- UUID of the promotion
- Code of the promotion
These are the basic identity properties for a promotion. They are useful and thanks to them, you can **activate** and **deactivate** a single promotion too.
The following methods are available:
| Android | iOS | React Native |
| --- | --- | --- |
| [Get promotion identified by UUID](/developers/mobile-sdk/method-reference/android/promotions#get-promotion-by-uuid) | [Get promotion identified by UUID](/developers/mobile-sdk/method-reference/ios/promotions#get-promotion-by-uuid) | [Get promotion identified by UUID](/developers/mobile-sdk/method-reference/react-native/promotions#get-promotion-by-uuid) |
| [Get promotion identified by code](/developers/mobile-sdk/method-reference/android/promotions#get-promotion-by-code) | [Get promotion identified by code](/developers/mobile-sdk/method-reference/ios/promotions#get-promotion-by-code) | [Get promotion identified by code](/developers/mobile-sdk/method-reference/react-native/promotions#get-promotion-by-code) |
| [Activate promotion identified by UUID](/developers/mobile-sdk/method-reference/android/promotions#activate-promotion-by-uuid) | [Activates promotion identified by UUID](/developers/mobile-sdk/method-reference/ios/promotions#activate-promotion-by-uuid) | [Activates promotion identified by UUID](/developers/mobile-sdk/method-reference/react-native/promotions#activate-promotion-by-uuid) |
| [Activate promotion identified by code](/developers/mobile-sdk/method-reference/android/promotions#activate-promotion-by-code) | [Activate promotion identified by code](/developers/mobile-sdk/method-reference/ios/promotions#activate-promotion-by-code) | [Activate promotion identified by code](/developers/mobile-sdk/method-reference/react-native/promotions#activate-promotion-by-code) |
| [Activate promotions](/developers/mobile-sdk/method-reference/android/promotions#activate-promotions-in-a-batch) | [Activate promotions](/developers/mobile-sdk/method-reference/ios/promotions#activate-promotions-in-a-batch) | [Activate promotions](/developers/mobile-sdk/method-reference/react-native/promotions#activate-promotions-in-a-batch) |
| [De-activate promotion identified by UUID](/developers/mobile-sdk/method-reference/android/promotions#deactivate-promotion-by-uuid) | [De-activate promotion identified by UUID](/developers/mobile-sdk/method-reference/ios/promotions#deactivate-promotion-by-uuid) | [De-activate promotion identified by UUID](/developers/mobile-sdk/method-reference/react-native/promotions#deactivate-promotion-by-uuid) |
| [De-activate promotion identified by code](/developers/mobile-sdk/method-reference/android/promotions#deactivate-promotion-by-code) | [De-activate promotion identified by code](/developers/mobile-sdk/method-reference/ios/promotions#deactivate-promotion-by-code) |[De-activate promotion identified by code](/developers/mobile-sdk/method-reference/react-native/promotions#deactivate-promotion-by-code) |
| [De-activate promotions](/developers/mobile-sdk/method-reference/android/promotions#deactivate-promotions-in-a-batch) | [De-activate promotions](/developers/mobile-sdk/method-reference/ios/promotions#deactivate-promotions-in-a-batch) | [De-activate promotions](/developers/mobile-sdk/method-reference/react-native/promotions#deactivate-promotions-in-a-batch) |
## Vouchers
---
### Overview {id=vouchers-overview}
In Synerise, you can create a voucher pool to distribute discount codes to your profiles for the campaign purposes.
The codes in a voucher pool get two forms:
- a text string
- a barcode
Before using it in your mobile app, [create a voucher pool in Synerise](/docs/assets/code-pools).
**Class reference** for vouchers: [Android](/developers/mobile-sdk/class-reference/android/modules#promotions), [iOS](/developers/mobile-sdk/class-reference/ios/modules#promotions), [React Native](/developers/mobile-sdk/class-reference/ios/modules#promotions), [Flutter](/developers/mobile-sdk/class-reference/flutter/modules#promotions).
**Method reference** for vouchers: [Android](/developers/mobile-sdk/method-reference/android/promotions#vouchers), [iOS](/developers/mobile-sdk/method-reference/ios/promotions#vouchers), [React Native](/developers/mobile-sdk/method-reference/react-native/promotions#vouchers), [Flutter](/developers/mobile-sdk/method-reference/flutter/promotions#vouchers).
### Voucher status
- **UNASSIGNED** - voucher is unassigned to any profile.
- **ASSIGNED** - voucher is assigned to a profile and visible to them.
- **REDEEMED** - voucher is redeemed and finished for the profile.
- **CANCELED** - voucher is canceled for the profile.
### Working with vouchers
The following methods are available:
| Android | iOS | React Native |
| --- | --- | --- |
| [Get voucher code only once or assign a voucher with provided pool UUID for the profile](/developers/mobile-sdk/method-reference/android/promotions#get-or-assign-voucher-from-pool)| [Get voucher code only once or assign a voucher with provided pool UUID for the profile](/developers/mobile-sdk/method-reference/ios/promotions#get-or-assign-voucher-from-pool) |[Get voucher code only once or assign a voucher with provided pool UUID for the client](/developers/mobile-sdk/method-reference/react-native/promotions#get-or-assign-voucher-from-pool) |
| [Assign voucher with provided pool UUID for the profile](/developers/mobile-sdk/method-reference/android/promotions#assign-voucher-code-from-pool) | [Assign voucher with provided pool UUID for the profile](/developers/mobile-sdk/method-reference/ios/promotions#assign-voucher-code-from-pool) | [Assign voucher with provided pool UUID for the profile](/developers/mobile-sdk/method-reference/react-native/promotions#assign-voucher-code-from-pool) |
| [Get profile's voucher codes](/developers/mobile-sdk/method-reference/android/promotions#get-voucher-codes-assigned-to-customer) | [Get profile's voucher codes](/developers/mobile-sdk/method-reference/ios/promotions#get-voucher-codes-assigned-to-customer) | [Get profile's voucher codes](/developers/mobile-sdk/method-reference/react-native/promotions#get-voucher-codes-assigned-to-customer) |
# Promotions and Vouchers
---
## Promotions
---
### Get all promotions of a customer
---
This method retrieves all available promotions that are defined for a customer.
The API key must have the `PROMOTIONS_DETAILS_FOR_CLIENT_READ` permission from the **Client** group.
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **onSuccess** | Function([PromotionResponse](/developers/mobile-sdk/class-reference/flutter/promotions-and-vouchers#promotionresponse) promotionResponse) | yes | - | Function to be executed when the operation is completed successfully |
| **onError** | Function([SyneriseError](/developers/mobile-sdk/class-reference/flutter/miscellaneous#syneriseerror) error) | yes | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **apiQuery** | [PromotionsApiQuery](/developers/mobile-sdk/class-reference/flutter/promotions-and-vouchers#promotionsapiquery) | yes | - | Object that stores all query parameters |
| **onSuccess** | Function([PromotionResponse](/developers/mobile-sdk/class-reference/flutter/promotions-and-vouchers#promotionresponse) promotionResponse) | yes | - | Function to be executed when the operation is completed successfully |
| **onError** | Function([SyneriseError](/developers/mobile-sdk/class-reference/flutter/miscellaneous#syneriseerror) error) | yes | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **uuid** | String | yes | - | UUID of the promotion |
| **onSuccess** | Function([Promotion](/developers/mobile-sdk/class-reference/flutter/promotions-and-vouchers#promotion) promotion) | yes | - | Function to be executed when the operation is completed successfully |
| **onError** | Function([SyneriseError](/developers/mobile-sdk/class-reference/flutter/miscellaneous#syneriseerror) error) | yes | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **code** | String | yes | - | Code of the promotion |
| **onSuccess** | Function([Promotion](/developers/mobile-sdk/class-reference/flutter/promotions-and-vouchers#promotion) promotion) | yes | - | Function to be executed when the operation is completed successfully |
| **onError** | Function([SyneriseError](/developers/mobile-sdk/class-reference/flutter/miscellaneous#syneriseerror) error) | yes | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **uuid** | String | yes | - | UUID of the promotion |
| **onSuccess** | Function() | yes | - | Function to be executed when the operation is completed successfully |
| **onError** | Function([SyneriseError](/developers/mobile-sdk/class-reference/flutter/miscellaneous#syneriseerror) error) | yes | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **code** | String | yes | - | Code of the promotion |
| **onSuccess** | Function() | yes | - | Function to be executed when the operation is completed successfully |
| **onError** | Function([SyneriseError](/developers/mobile-sdk/class-reference/flutter/miscellaneous#syneriseerror) error) | yes | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **promotionsToActivate** | List<[PromotionIdentifier](/developers/mobile-sdk/class-reference/flutter/promotions-and-vouchers#promotionidentifier)> | yes | - | List of promotion identifiers |
| **onSuccess** | Function() | yes | - | Function to be executed when the operation is completed successfully |
| **onError** | Function([SyneriseError](/developers/mobile-sdk/class-reference/flutter/miscellaneous#syneriseerror) error) | yes | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **uuid** | String | yes | - | UUID of the promotion |
| **onSuccess** | Function() | yes | - | Function to be executed when the operation is completed successfully |
| **onError** | Function([SyneriseError](/developers/mobile-sdk/class-reference/flutter/miscellaneous#syneriseerror) error) | yes | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **code** | String | yes | - | Code of the promotion |
| **onSuccess** | Function() | yes | - | Function to be executed when the operation is completed successfully |
| **onError** | Function([SyneriseError](/developers/mobile-sdk/class-reference/flutter/miscellaneous#syneriseerror) error) | yes | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **promotionsIdentifiers** | List<[PromotionIdentifier](/developers/mobile-sdk/class-reference/flutter/promotions-and-vouchers#promotionidentifier)> | yes | - | List of promotion identifiers |
| **onSuccess** | Function() | yes | - | Function to be executed when the operation is completed successfully |
| **onError** | Function([SyneriseError](/developers/mobile-sdk/class-reference/flutter/miscellaneous#syneriseerror) error) | yes | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
## Vouchers
---
### Get or assign voucher from pool
---
This method retrieves an assigned voucher code or assigns a voucher from a pool identified by UUID to the customer.
Once a voucher is assigned using this method, **the same** voucher is returned for the profile every time the method is called.
When the voucher is assigned for the first time, a [voucherCode.assigned](/docs/assets/events/event-reference/loyalty#vouchercodeassigned) event is produced.
The API key must have the `VOUCHERS_ITEM_ASSIGN_CREATE` and `VOUCHERS_ITEM_ASSIGN_READ` permission from the **Assign** group.
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **poolUuid** | String | yes | - | Unique identifier of a code pool |
| **onSuccess** | Function([AssignVoucherResponse](/developers/mobile-sdk/class-reference/flutter/promotions-and-vouchers#assignvoucherresponse) assignVoucherResponse) | yes | - | Function to be executed when the operation is completed successfully |
| **onError** | Function([SyneriseError](/developers/mobile-sdk/class-reference/flutter/miscellaneous#syneriseerror) error) | yes | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
### Assign voucher code from pool
---
This method assigns a voucher from a pool identified by UUID to the profile.
Every request returns a **different code** until the pool is empty.
A [voucherCode.assigned](/docs/assets/events/event-reference/loyalty#vouchercodeassigned) event is produced.
Returns the HTTP 416 status code when the pool is empty.
The API key must have the `VOUCHERS_ITEM_ASSIGN_CREATE` and `VOUCHERS_ITEM_ASSIGN_READ` permission from the **Assign** group.
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **poolUuid** | String | yes | - | Unique identifier of a code pool |
| **onSuccess** | Function([AssignVoucherResponse](/developers/mobile-sdk/class-reference/flutter/promotions-and-vouchers#assignvoucherresponse) assignVoucherResponse) | yes | - | Function to be executed when the operation is completed successfully, returning the [AssignVoucherResponse](/developers/mobile-sdk/class-reference/flutter/promotions-and-vouchers#assignvoucherresponse) |
| **onError** | Function([SyneriseError](/developers/mobile-sdk/class-reference/flutter/miscellaneous#syneriseerror) error) | yes | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **onSuccess** | Function([VoucherCodesResponse](/developers/mobile-sdk/class-reference/flutter/promotions-and-vouchers#vouchercodesresponse) voucherCodesResponse) | yes | - | Function to be executed when the operation is completed successfully |
| **onError** | Function([SyneriseError](/developers/mobile-sdk/class-reference/flutter/miscellaneous#syneriseerror) error) | yes | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
# Promotions and Vouchers
## Promotions
---
### Get all promotions of a customer
---
This method retrieves all available promotions that are defined for a customer.
The API key must have the `PROMOTIONS_DETAILS_FOR_CLIENT_READ` permission from the **Client** group.
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **success** | (([PromotionResponse](/developers/mobile-sdk/class-reference/ios/promotions-and-vouchers#promotionresponse)) -> Void) | yes | - | Closure/Block to be executed when the operation is completed successfully |
| **failure** | (([ApiError](/developers/mobile-sdk/class-reference/ios/miscellaneous#snrapierror)) -> Void) | yes | - | Closure/Block to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
```Swift
Promotions.getPromotions(success: { (promotionResponse) in
// success
print(promotionResponse.items)
}, failure: { (error) in
// failure
})
```
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **apiQuery** | [PromotionsApiQuery](/developers/mobile-sdk/class-reference/ios/promotions-and-vouchers#promotionsapiquery) | no | - | Object that stores all query parameters |
| **success** | (([PromotionResponse](/developers/mobile-sdk/class-reference/ios/promotions-and-vouchers#promotionresponse)) -> Void) | yes | - | Closure/Block to be executed when the operation is completed successfully |
| **failure** | (([ApiError](/developers/mobile-sdk/class-reference/ios/miscellaneous#snrapierror)) -> Void) | yes | - | Closure/Block to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **uuid** | String | yes | - | UUID of the promotion |
| **success** | (([Promotion](/developers/mobile-sdk/class-reference/ios/promotions-and-vouchers#promotion)) -> Void) | yes | - | Closure/Block to be executed when the operation is completed successfully |
| **failure** | (([ApiError](/developers/mobile-sdk/class-reference/ios/miscellaneous#snrapierror)) -> Void) | yes | - | Closure/Block to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
```Swift
let UUID: String = "UUID"
Promotions.getPromotion(uuid: UUID, success: { (promotion) in
// success
print(promotion.code)
print(promotion.discountValue)
}, failure: { (error) in
// failure
})
```
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **code** | String | true | - | Code of the promotion |
| **success** | (([Promotion](/developers/mobile-sdk/class-reference/ios/promotions-and-vouchers#promotion)) -> Void) | yes | - | Closure/Block to be executed when the operation is completed successfully |
| **failure** | (([ApiError](/developers/mobile-sdk/class-reference/ios/miscellaneous#snrapierror)) -> Void) | yes | - | Closure/Block to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
```Swift
let code: String = "CODE"
Promotions.getPromotion(code: code, success: { (promotion) in
// success
print(promotion.code)
print(promotion.discountValue)
}, failure: { (error) in
// failure
})
```
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **uuid** | String | yes | - | UUID of the promotion |
| **success** | ((Bool) -> Void) | yes | - | Closure/Block to be executed when the operation is completed successfully |
| **failure** | (([ApiError](/developers/mobile-sdk/class-reference/ios/miscellaneous#snrapierror)) -> Void) | yes | - | Closure/Block to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
```Swift
let UUID: String = "UUID"
Promotions.activatePromotion(uuid: UUID, success: { (isSuccess) in
// success
}, failure: { (error) in
// failure
})
```
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **code** | String | yes | - | Code of the promotion |
| **success** | ((Bool) -> Void) | yes | - | Closure/Block to be executed when the operation is completed successfully |
| **failure** | (([ApiError](/developers/mobile-sdk/class-reference/ios/miscellaneous#snrapierror)) -> Void) | yes | - | Closure/Block to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
```Swift
let code: String = "CODE"
Promotions.activatePromotion(code: code, success: { (isSuccess) in
// success
}, failure: { (error) in
// failure
})
```
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **identifiers** | [[PromotionIdentifier]](/developers/mobile-sdk/class-reference/ios/promotions-and-vouchers/#promotionidentifier) | yes | - | List of identifiers of the promotions that you want to activate |
| **success** | ((Bool) -> Void) | yes | - | Closure/Block to be executed when the operation is completed successfully |
| **failure** | (([ApiError](/developers/mobile-sdk/class-reference/ios/miscellaneous#snrapierror)) -> Void) | yes | - | Closure/Block to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
```Swift
let UUIDs = "UUID_1, UUID2, UUID_3"
let UUIDsArray = UUIDs.components(separatedBy: ",").filter { !$0.isEmpty }
var promotionIdentifiers: [PromotionIdentifier] = [PromotionIdentifier]()
UUIDsArray.forEach { uuid in
let promotionIdentifier = PromotionIdentifier(uuid: uuid)
promotionIdentifiers.append(promotionIdentifier)
}
Promotions.activatePromotions(identifiers: promotionIdentifiers, success: { (success) in
// success
}, failure: { (error) in
// failure
})
```
### Deactivate promotion by UUID
---
This method deactivates the promotion with the specified UUID.
The API key must have the `PROMOTIONS_DEACTIVATE_PROMOTIONS_UPDATE` permission from the **Promotions** group.
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **uuid** | String | yes | - | UUID of the promotion |
| **success** | ((Bool) -> Void) | yes | - | Closure/Block to be executed when the operation is completed successfully |
| **failure** | (([ApiError](/developers/mobile-sdk/class-reference/ios/miscellaneous#snrapierror)) -> Void) | yes | - | Closure/Block to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
```Swift
let UUID: String = "UUID"
Promotions.deactivatePromotion(uuid: UUID, success: { (isSuccess) in
// success
}, failure: { (error) in
// failure
})
```
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **code** | String | yes | - | Code of the promotion |
| **success** | ((Bool) -> Void) | yes | - | Closure/Block to be executed when the operation is completed successfully |
| **failure** | (([ApiError](/developers/mobile-sdk/class-reference/ios/miscellaneous#snrapierror)) -> Void) | yes | - | Closure/Block to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
```Swift
let code: String = "CODE"
Promotions.deactivatePromotion(code: code, success: { (isSuccess) in
// success
}, failure: { (error) in
// failure
})
```
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **identifiers** | [[PromotionIdentifier]](/developers/mobile-sdk/class-reference/ios/promotions-and-vouchers/#promotionidentifier) | yes | - | List of identifiers of the promotions that you want to de-activate |
| **success** | ((Bool) -> Void) | yes | - | Closure/Block to be executed when the operation is completed successfully |
| **failure** | (([ApiError](/developers/mobile-sdk/class-reference/ios/miscellaneous#snrapierror)) -> Void) | yes | - | Closure/Block to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
```Swift
let UUIDs = "UUID_1, UUID2, UUID_3"
let UUIDsArray = UUIDs.components(separatedBy: ",").filter { !$0.isEmpty }
var promotionIdentifiers: [PromotionIdentifier] = [PromotionIdentifier]()
UUIDsArray.forEach { uuid in
let promotionIdentifier = PromotionIdentifier(uuid: uuid)
promotionIdentifiers.append(promotionIdentifier)
}
Promotions.deactivatePromotions(identifiers: promotionIdentifiers, success: { (success) in
// success
}, failure: { (error) in
// failure
})
```
## Vouchers
---
### Get or assign voucher from pool
---
This method retrieves an assigned voucher code or assigns a voucher from a pool identified by UUID to the customer.
Once a voucher is assigned using this method, **the same** voucher is returned for the profile every time the method is called.
When the voucher is assigned for the first time, a [voucherCode.assigned](/docs/assets/events/event-reference/loyalty#vouchercodeassigned) event is produced.
The API key must have the `VOUCHERS_ITEM_ASSIGN_CREATE` and `VOUCHERS_ITEM_ASSIGN_READ` permission from the **Assign** group.
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **poolUUID** | String | no | - | Unique identifier of a code pool |
| **success** | (([AssignVoucherResponse](/developers/mobile-sdk/class-reference/ios/promotions-and-vouchers#assignvoucherresponse)) -> Void) | yes | - | Closure/Block to be executed when the operation is completed successfully |
| **failure** | (([ApiError](/developers/mobile-sdk/class-reference/ios/miscellaneous#snrapierror)) -> Void) | yes | - | Closure/Block to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
```Swift
let poolUUID: String = "POOL_UUID"
Promotions.getOrAssignVoucher(poolUUID: poolUUID, success: { (assignVoucherResponse) in
// success
failure: { (error) in
// failure
})
```
### Assign voucher code from pool
---
This method assigns a voucher from a pool identified by UUID to the profile.
Every request returns a **different code** until the pool is empty.
A [voucherCode.assigned](/docs/assets/events/event-reference/loyalty#vouchercodeassigned) event is produced.
Returns the HTTP 416 status code when the pool is empty.
The API key must have the `VOUCHERS_ITEM_ASSIGN_CREATE` and `VOUCHERS_ITEM_ASSIGN_READ` permission from the **Assign** group.
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **poolUUID** | String | yes | - | Unique identifier of a code pool |
| **success** | (([AssignVoucherResponse](/developers/mobile-sdk/class-reference/ios/promotions-and-vouchers#assignvoucherresponse)) -> Void) | yes | - | Closure/Block to be executed when the operation is completed successfully |
| **failure** | (([ApiError](/developers/mobile-sdk/class-reference/ios/miscellaneous#snrapierror)) -> Void) | yes | - | Closure/Block to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
```Swift
let poolUUID: String = "POOL_UUID"
Promotions.assignVoucherCode(poolUUID: poolUUID, success: { (assignVoucherResponse) in
// success
}, failure: { (error) in
// failure
})
```
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **success** | ((VoucherCodesResponse) -> Void) | yes | - | Closure/Block to be executed when the operation is completed successfully |
| **failure** | (([ApiError](/developers/mobile-sdk/class-reference/ios/miscellaneous#snrapierror)) -> Void) | yes | - | Closure/Block to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
```Swift
Promotions.getAssignedVoucherCodes(success: { (voucherCodesResponse) in
// success
}, failure: { (error) in
// failure
})
```
# In-app message
## Overview
---
In-app message is a banner that can be displayed when your app is running. It may have various layout variants, because it is fully customizable by HTML. The campaign is triggered and displayed depending on the configuration settings.
Read more about creating in-app messages [here](/docs/campaign/in-app-messages/create-inapp-message).
Due to operating system differences and web engines, in-app message appearance may differ between systems or not be as expected. You should test your in-app messages.
In in-app messages, you can use:
- the **safe area** mode on iOS from the `5.1.0` version,
- the **display cutouts** mode on Android from the `6.1.0` version.
## Requirements
---
- Recommended Mobile SDK version:
- Android - 5.3.0 or newer
- iOS - 4.12.0 or newer
- React Native - 0.12.0 or newer
- Flutter - 0.5.0 or newer
- If your in-app content (such as JavaScript, CSS, images, or fonts) is being loaded from your own server via HTTP and you have configured **CORS policies**, you need to set the **contentBaseUrl** to your server's address. For example, if you're loading resources from `https://www.synerise.com/example/font.woff`, you should configure **contentBaseUrl** to `https://www.synerise.com` (check this option in the [Settings](/developers/mobile-sdk/settings#content-base-url-for-in-app-message)).
- Enable the `IN_APP_DEFINITIONS_COMMUNICATION_READ` (**Experience Hub**) permission in the Profile (formerly Client) [API key](/docs/settings/tool/api) used by the mobile application so the mobile application can fetch in-app messages.
The API key permission matrix with the in-app permission
## Good practices
---
### Campaign planning recommendations
Using a large number of in-app messages in your application can impact rendering time, message delivery, and battery usage.
To maintain optimal application performance when using in-app campaigns:
- Avoid assigning more than 10 in-app messages to the same trigger event.
- Avoid having more than 20 in-app messages active at the same time in your application.
- Review and archive in-app campaigns that you no longer need.
### Template construction
When creating or editing in-app message content:
- Place the the `SRInApp.close()` (or `SRInApp.hide()`) method at the beginning of the JS script.
- Use try/catch to handle possible fatal errors in the JS script.
- Handle situations where Jinjava inserts return empty data.
- When adding external links to your message:
- Only link to sites you trust.
- Don't link to large images that may negatively affect performance.
- Don't link to resources whose CSS/HTML may be blocked. If you have resources loaded from your own URLs, set `Synerise.settings.inAppMessaging.contentBaseUrl` and use relative paths in HTML/CSS.
## Configuration
---
In-app message campaigns are served by the Synerise backend.
Check possible available configuration options in the [Settings](/developers/mobile-sdk/settings#in-app-messaging).
## JavaScript methods in in-app messages
---
See ["Using in-app template builder" in the User Guide](/docs/campaign/in-app-messages/creating-inapp-templates/creating-inapp-template#javascript-methods-in-in-app-messages).
## Events generated by in-app messaging
---
For information about events generated by in-app messaging, see the [event reference](/docs/assets/events/event-reference/inapp).
You can disable sending the `inApp.capping` event in the SDK Settings - [Enable/disable sending in-app capping event](/developers/mobile-sdk/settings#enabledisable-sending-inappcapping-event).
## Setting up a global control group for in-app message
---
For information about global control groups in in-app messages, see the [global control group](/docs/settings/configuration/global-control-group) article.
## Handling actions from in-app messages
---
Handling main actions from campaigns depends on the campaign type and operating system and it is described [here](/developers/mobile-sdk/campaigns/action-handling).
## Controlling behavior and actions
---
You may control an incoming in-app message and decide whether to show it (the display of in-app message can be triggered by occurrence of specific events). By default, the SDK allows in-app message display.
The user interface allows selecting up to 3 trigger events, however, in Android, only for `5.8.1` SDK version (released on 28.08.2023) or higher all triggers are considered altogether. For older SDK versions in Android, only the last event from the trigger list will be considered.
These limitations don't apply in iOS.
Also, you can be notified (in the form of events) about the campaign actions in the following cases:
- When the in-app message is presented.
- When the in-app message disappeared.
- When additional context is needed to render the campaign.
- When the customer invoked an action.
You can handle the message using:
- [OnInAppListener](/developers/mobile-sdk/listeners-and-delegates/android-listeners#on-in-app-listener) methods for Android.
- [InjectorInAppMessageDelegate](/developers/mobile-sdk/listeners-and-delegates/ios-delegates#injector-in-app-message-delegate) methods for iOS.
- [InjectorInAppMessageListener](/developers/mobile-sdk/listeners-and-delegates/react-native-listeners#injector-in-app-message-listener) methods for React Native.
- [InjectorInAppMessageListener](/developers/mobile-sdk/listeners-and-delegates/flutter-listeners#injector-in-app-message-listener) methods for Flutter.
See the following code samples:
```Java
public static OnInAppListener NULL = new OnInAppListener() {
// This method is called after an in-app message is loaded and Synerise SDK asks for permission to show it.
@Override
public boolean shouldShow(InAppMessageData inAppMessageData) {
return true;
}
// This method is called after an in-app message appears.
@Override
public void onShown(InAppMessageData inAppMessageData) {
//...
}
// This method is called after an in-app message disappears.
@Override
public void onDismissed(InAppMessageData inAppMessageData) {
//...
}
// This method is called when a individual context for an in-app message is needed.
@Override
public HashMap onContextFromAppRequired(InAppMessageData inAppMessageData) {
return new HashMap<>();
}
// This method is called when the SRInApp.openUrl(url) method is used in an in-app message.
@Override
public void onHandledOpenUrl(InAppMessageData inAppMessageData) {
//...
}
// This method is called when the SRInApp.openDeeplink(url) method is used in an in-app message.
@Override
public void onHandledOpenDeepLink(InAppMessageData inAppMessageData) {
//...
}
// This method is called when the
// SRInApp.handleCustomAction(name, params) method is used in an in-app message.
@Override
public void onCustomAction(String identifier, HashMap params, InAppMessageData inAppMessageData) {
//...
}
};
```
```Kotlin
var inAppCallbacks: OnInAppListener = object : OnInAppListener() {
// This method is called after an in-app message is loaded and Synerise SDK asks for permission to show it.
override fun shouldShow(inAppMessageData: InAppMessageData): Boolean {
return true
}
// This method is called after an in-app message appears.
override fun onShown(inAppMessageData: InAppMessageData) {
//...
}
// This method is called after an in-app message disappears.
override fun onDismissed(inAppMessageData: InAppMessageData) {
//...
}
// This method is called when a individual context for an in-app message is needed.
override fun onContextFromAppRequired(inAppMessageData: InAppMessageData): HashMap {
return HashMap()
}
// This method is called when the SRInApp.openUrl(url) method is used in an in-app message.
override fun onHandledOpenUrl(inAppMessageData: InAppMessageData) {
//...
}
// This method is called when the SRInApp.openDeeplink(url) method is used in an in-app message.
override fun onHandledOpenDeepLink(inAppMessageData: InAppMessageData) {
//...
}
// This method is called when the
// SRInApp.handleCustomAction(name, params) method is used in an in-app message.
override fun onCustomAction(identifier: String?, params: HashMap?, inAppMessageData: InAppMessageData?) {
//...
}
}
```
```Swift
// MARK: - InjectorInAppMessageDelegate
// This method is called after an in-app message is loaded and Synerise SDK asks for permission to show it.
func snr_shouldInAppMessageAppear(data: InAppMessageData) -> Bool {
return true
}
// This method is called after an in-app message appears.
func snr_inAppMessageDidAppear(data: InAppMessageData) {
//...
}
// This method is called after an in-app message disappears.
func snr_inAppMessageDidDisappear(data: InAppMessageData) {
//...
}
// This method is called when an in-app message changes size.
func snr_inAppMessageDidChangeSize(rect: CGRect) {
//...
}
// This method is called when a individual context for an in-app message is needed.
func snr_inAppMessageContextIsNeeded(data: InAppMessageData) -> [AnyHashable: Any]? {
return []
}
// This method is called when the SRInApp.openUrl(url) method is used in an in-app message.
func snr_inAppMessageHandledAction(data: InAppMessageData, url: URL) {
//...
}
// This method is called when the SRInApp.openDeeplink(url) method is used in an in-app message.
func snr_inAppMessageHandledAction(data: InAppMessageData, deeplink: String) {
//...
}
// This method is called when the
// SRInApp.handleCustomAction(name, params) method is used in an in-app message.
func snr_inAppMessageHandledCustomAction(data: InAppMessageData, name: String, parameters: [AnyHashable: Any]) {
//...
}
```
```Objective-C
#pragma mark - SNRInjectorInAppMessageDelegate
// This method is called after an in-app message is loaded and Synerise SDK asks for permission to show it.
- (BOOL)SNR_shouldInAppMessageAppear:(SNRInAppMessageData *)data {
//...
}
// This method is called after an in-app message appears.
- (void)SNR_inAppMessageDidAppear:(SNRInAppMessageData *)data {
//...
}
// This method is called after an in-app message disappears.
- (void)SNR_inAppMessageDidDisappear:(SNRInAppMessageData *)data {
//...
}
// This method is called when an in-app message changes size.
- (void)SNR_inAppMessageDidChangeSize:(CGRect)rect {
//...
}
// This method is called when a individual context for an in-app message is needed.
- (nullable NSDictionary *)SNR_inAppMessageContextIsNeeded:(SNRInAppMessageData *)data {
//...
}
// This method is called when the SRInApp.openUrl(url) method is used in an in-app message.
- (void)SNR_inAppMessageHandledURLAction:(SNRInAppMessageData *)data url:(NSURL *)url {
//...
}
// This method is called when the SRInApp.openDeeplink(url) method is used in an in-app message.
- (void)SNR_inAppMessageHandledDeeplinkAction:(SNRInAppMessageData *)data deeplink:(NSString *)deeplink {
//...
}
// This method is called when the
// SRInApp.handleCustomAction(name, params) method is used in an in-app message.
- (void)SNR_inAppMessageHandledCustomAction:(SNRInAppMessageData *)data name:(NSString *)name parameters:(NSDictionary *)parameters {
//...
}
```
```JavaScript
Synerise.onReady(function() {
Synerise.Injector.setInAppMessageListener({
// This method is called after an in-app message is loaded and Synerise SDK asks for permission to show it.
shouldPresent: function(data) {
return true;
},
// This method is called after an in-app message appears.
onPresent: function(data) {
//...
},
// This method is called after an in-app message disappears.
onHide: function(data) {
//...
},
// This method is called when a individual context for an in-app message is needed.
contextIsNeeded: function(data) {
return {}
},
// This method is called when the SRInApp.openUrl(url) method is used in an in-app message.
onOpenUrl: function(data, url) {
//...
},
// This method is called when the SRInApp.openDeeplink(url) method is used in an in-app message.
onDeepLink: function(data, deepLink) {
//...
},
// This method is called when Synerise handles custom action from in-app messages.
onCustomAction: function(data, name, parameters) {
//...
}
});
})
```
```Dart
Synerise.injector.inAppMessageListener((listener) {
// This method is called after an in-app message appears.
listener.onPresent = (data) {
//...
};
// This method is called after an in-app message disappears.
listener.onHide = (data) {
//...
};
// This method is called when the SRInApp.openUrl(url) method is used in an in-app message.
listener.onOpenUrl = (data, url) {
//...
};
// This method is called when the SRInApp.openDeeplink(url) method is used in an in-app message.
listener.onDeepLink = (data, deepLink) {
//...
};
// This method is called when Synerise handles custom action from in-app messages.
listener.onCustomAction(data, name, parameters) {
//...
};
});
```
## Closing a message
In-app messages can be closed with a [JS method included in their content](/docs/campaign/in-app-messages/creating-inapp-templates/creating-inapp-template#close-a-message), but you can also use a mobile SDK method. This can be used to close top or bottom bar in-app from somewhere else on the screen.
Using this method generates an `inApp.discard` event.
See the method reference:
- [Android](/developers/mobile-sdk/method-reference/android/campaigns#close-in-app-message)
- [Flutter](/developers/mobile-sdk/method-reference/flutter/campaigns#close-in-app-message)
- [iOS](/developers/mobile-sdk/method-reference/ios/campaigns#close-in-app-message)
- [React Native](/developers/mobile-sdk/method-reference/react-native/campaigns#close-in-app-message)
## Example
---
This is an in-app message campaign example with full screen presentation.
In-app message campaign (Android)In-app message campaign (iOS)
# Promotions and Vouchers
## Promotions
---
### Get all promotions of a customer
---
This method retrieves all available promotions that are defined for a customer.
The API key must have the `PROMOTIONS_DETAILS_FOR_CLIENT_READ` permission from the **Client** group.
Methods using arguments are now deprecated.
Only Promotions.getPromotions(promotionsApiQuery) is valid.
**Declaration:**
```java
public static IDataApiCall getPromotions(@Nullable List statuses,
@Nullable List types, int page)
public static IDataApiCall getPromotions(@Nullable List statuses,
@Nullable List types, int limit, int page)
public static IDataApiCall getPromotions(@Nullable List statuses,
@Nullable List types, int page, boolean includeMeta)
public static IDataApiCall getPromotions(PromotionsApiQuery promotionsApiQuery)
```
```kotlin
fun getPromotions(@Nullable statuses:List,
@Nullable types:List, page:Int):IDataApiCall
fun getPromotions(@Nullable statuses:List,
@Nullable types:List, limit:Int, page:Int):IDataApiCall
fun getPromotions(@Nullable statuses:List,
@Nullable types:List, page:Int, includeMeta:Boolean):IDataApiCall
fun getPromotions(promotionsApiQuery:PromotionsApiQuery):IDataApiCall
```
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **statuses** | List | yes | - | Specify a status filter, can be any combination or an empty list. |
| **types** | List | yes | - | Specify type filter, can be any combination or an empty list. |
| **page** | int | yes | - | Query for a specific page, minimum 1. |
| **limit** | int | yes | 100 | Query for promotions limit. |
| **includeMeta** | boolean | yes | false | Decide whether to include metadata in the final response. |
| **promotionsApiQuery** | [PromotionsApiQuery](/developers/mobile-sdk/class-reference/android/promotions-and-vouchers#promotionsapiquery) | yes | --- | Class responsible for storing all queryParameters. |
**Return Value:**
IDataApiCall<[PromotionResponse](/developers/mobile-sdk/class-reference/android/promotions-and-vouchers#promotionresponse)> object to execute the request.
**Example:**
## Vouchers
---
### Get or assign voucher from pool
---
This method retrieves an assigned voucher code or assigns a voucher from a pool identified by UUID to the customer.
Once a voucher is assigned using this method, **the same** voucher is returned for the profile every time the method is called.
When the voucher is assigned for the first time, a [voucherCode.assigned](/docs/assets/events/event-reference/loyalty#vouchercodeassigned) event is produced.
The API key must have the `VOUCHERS_ITEM_ASSIGN_CREATE` and `VOUCHERS_ITEM_ASSIGN_READ` permission from the **Assign** group.
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **poolUUID** | String | no | - | Unique identifier of a code pool |
| **success** | (([AssignVoucherResponse](/developers/mobile-sdk/class-reference/ios/promotions-and-vouchers#assignvoucherresponse)) -> Void) | yes | - | Closure/Block to be executed when the operation is completed successfully |
| **failure** | (([ApiError](/developers/mobile-sdk/class-reference/ios/miscellaneous#snrapierror)) -> Void) | yes | - | Closure/Block to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
```Swift
let poolUUID: String = "POOL_UUID"
Promotions.getOrAssignVoucher(poolUUID: poolUUID, success: { (assignVoucherResponse) in
// success
failure: { (error) in
// failure
})
```
### Assign voucher code from pool
---
This method assigns a voucher from a pool identified by UUID to the profile.
Every request returns a **different code** until the pool is empty.
A [voucherCode.assigned](/docs/assets/events/event-reference/loyalty#vouchercodeassigned) event is produced.
Returns the HTTP 416 status code when the pool is empty.
The API key must have the `VOUCHERS_ITEM_ASSIGN_CREATE` and `VOUCHERS_ITEM_ASSIGN_READ` permission from the **Assign** group.
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **poolUUID** | String | yes | - | Unique identifier of a code pool |
| **success** | (([AssignVoucherResponse](/developers/mobile-sdk/class-reference/ios/promotions-and-vouchers#assignvoucherresponse)) -> Void) | yes | - | Closure/Block to be executed when the operation is completed successfully |
| **failure** | (([ApiError](/developers/mobile-sdk/class-reference/ios/miscellaneous#snrapierror)) -> Void) | yes | - | Closure/Block to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
```Swift
let poolUUID: String = "POOL_UUID"
Promotions.assignVoucherCode(poolUUID: poolUUID, success: { (assignVoucherResponse) in
// success
}, failure: { (error) in
// failure
})
```
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **success** | ((VoucherCodesResponse) -> Void) | yes | - | Closure/Block to be executed when the operation is completed successfully |
| **failure** | (([ApiError](/developers/mobile-sdk/class-reference/ios/miscellaneous#snrapierror)) -> Void) | yes | - | Closure/Block to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
```Swift
Promotions.getAssignedVoucherCodes(success: { (voucherCodesResponse) in
// success
}, failure: { (error) in
// failure
})
```
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **slug** | String | yes | - | Slug of the document |
| **onSuccess** | Function([Document](/developers/mobile-sdk/class-reference/flutter/recommendations-and-documents#document) document) | yes | - | Function to be executed when the operation is completed successfully |
| **onError** | Function([SyneriseError](/developers/mobile-sdk/class-reference/flutter/miscellaneous#syneriseerror) error) | yes | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **apiQuery** | [DocumentApiQuery](/developers/mobile-sdk/class-reference/flutter/recommendations-and-documents#documentapiquery) | yes | - | Object that stores all query parameters |
| **onSuccess** | Function([Document](/developers/mobile-sdk/class-reference/flutter/recommendations-and-documents#document) document) | yes | - | Function to be executed when the operation is completed successfully |
| **onError** | Function([SyneriseError](/developers/mobile-sdk/class-reference/flutter/miscellaneous#syneriseerror) error) | yes | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
## Get Recommendations (v2)
---
This method generates recommendations that are defined for the options provided. The recommendations are generated by using a document with an insert.
For instructions, see ["Displaying AI recommendations > With documents and screen views"](/developers/mobile-sdk/displaying-recommendations/documents).
| | **iOS SDK** | **Android SDK** | **React Native SDK** | **Flutter SDK** |
| --- | --- | --- | --- | --- |
| Introduced in: | 4.13.0 | 5.5.0 | 0.17.0 | 0.6.0 |
The API key must have the `SCHEMA_SERVICE_SCHEMA_READ` permission from the **Schema** group.
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **recommendationOptions** | [RecommendationOptions](/developers/mobile-sdk/class-reference/flutter/recommendations-and-documents#recommendationoptions) | yes | - | Options for recommendations |
| **onSuccess** | Function([RecommendationResponse](/developers/mobile-sdk/class-reference/flutter/recommendations-and-documents#recommendationresponse) recommendationResponse) | yes | - | Function to be executed when the operation is completed successfully |
| **onError** | Function([SyneriseError](/developers/mobile-sdk/class-reference/flutter/miscellaneous#syneriseerror) error) | yes | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **feedSlug** | String | yes | - | Identifies a specific screen view feed |
| **onSuccess** | Function([ScreenView](/developers/mobile-sdk/class-reference/flutter/miscellaneous#screenview) screenView) | yes | - | Function to be executed when the operation is completed successfully |
| **onError** | Function([SyneriseError](/developers/mobile-sdk/class-reference/flutter/miscellaneous#syneriseerror) error) | yes | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
## Generate screen view with query parameters
---
This method generates customer's highest-priority screen view campaign that is defined for parameters provided in the query object.
**Declared In:**
lib/modules/content/content_impl.dart
**Related To:**
[ScreenViewApiQuery](/developers/mobile-sdk/class-reference/flutter/miscellaneous#screenviewapiquery)
[ScreenView](/developers/mobile-sdk/class-reference/flutter/miscellaneous#screenview)
**Class:**
[ContentImpl](/developers/mobile-sdk/class-reference/flutter/modules#content)
**Declaration:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **apiQuery** | [ScreenViewApiQuery](/developers/mobile-sdk/class-reference/flutter/miscellaneous#screenviewapiquery) | yes | - | Object that stores all query parameters |
| **onSuccess** | Function([ScreenView](/developers/mobile-sdk/class-reference/flutter/miscellaneous#screenview) screenView) | yes | - | Function to be executed when the operation is completed successfully |
| **onError** | Function([SyneriseError](/developers/mobile-sdk/class-reference/flutter/miscellaneous#syneriseerror) error) | yes | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
## Generate Brickworks
This method generates content from a published version of a [Brickworks](/docs/assets/brickworks) record. Inserts and fields which require a customer context fetch it automatically from the current user.
| | **iOS SDK** | **Android SDK** | **React Native SDK** | **Flutter SDK** |
| ----------------------------------------------- | ----------- | --------------- | -------------------- | --------------- |
| Introduced in: | 5.8.1 | 6.8.0 | 1.6.0 | 2.6.0 |
The API key must have the `BRICKWORKS_RECORDS_READ` permission from the **RECORDS** group.
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **apiQuery** | [BrickworksApiQuery](/developers/mobile-sdk/class-reference/flutter/miscellaneous#brickworksapiquery) | yes | - | Object that stores all query parameters |
| **onSuccess** | Function(Map brickworks) | yes | - | Function to be executed when the operation is completed successfully |
| **onError** | Function([SyneriseError](/developers/mobile-sdk/class-reference/flutter/miscellaneous#syneriseerror) error) | yes | - | Function to be executed when the operation is completed with an error |
**Return Value:**
Object with content generated from a record.
**Example:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **slug** | String | yes | - | Name of the slug |
| **onSuccess** | Function([Document](/developers/mobile-sdk/class-reference/flutter/recommendations-and-documents#document) document) | yes | - | Function to be executed when the operation is completed successfully |
| **onError** | Function([SyneriseError](/developers/mobile-sdk/class-reference/flutter/miscellaneous#syneriseerror) error) | yes | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **recommendationOptions** | [RecommendationOptions](/developers/mobile-sdk/class-reference/flutter/recommendations-and-documents#recommendationoptions) | yes | - | Object for configuration of the options parameters |
| **onSuccess** | Function([RecommendationResponse](/developers/mobile-sdk/class-reference/flutter/recommendations-and-documents#recommendationresponse) recommendationResponse) | yes | - | Function to be executed when the operation is completed successfully |
| **onError** | Function([SyneriseError](/developers/mobile-sdk/class-reference/flutter/miscellaneous#syneriseerror) error) | yes | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **onSuccess** | Function([ScreenViewResponse](/developers/mobile-sdk/class-reference/flutter/miscellaneous#screenviewresponse) screenViewResponse) | yes | - | Function to be executed when the operation is completed successfully |
| **onError** | Function([SyneriseError](/developers/mobile-sdk/class-reference/flutter/miscellaneous#syneriseerror) error) | yes | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **slug** | String | yes | - | Slug of the document |
| **success** | (([Document](/developers/mobile-sdk/class-reference/ios/recommendations-and-documents#document)) -> Void) | yes | - | Closure/Block to be executed when the operation is completed successfully |
| **failure** | (([SNRApiError](/developers/mobile-sdk/class-reference/ios/miscellaneous#snrapierror)]) -> Void) | yes | - | Closure/Block to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
```Swift
let slug = "similar"
Content.generateDocument(slug: slug, success: { document in
// success
}) { error in
// failure
}
```
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **apiQuery** | [DocumentApiQuery](/developers/mobile-sdk/class-reference/ios/recommendations-and-documents#documentapiquery) | yes | - | Object that stores all query parameters |
| **success** | (([Document](/developers/mobile-sdk/class-reference/ios/recommendations-and-documents#document)) -> Void) | yes | - | Closure/Block to be executed when the operation is completed successfully |
| **failure** | (([SNRApiError](/developers/mobile-sdk/class-reference/ios/miscellaneous#snrapierror)]) -> Void) | yes | - | Closure/Block to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
## Get recommendations (v2)
---
This method generates recommendations that are defined for the options provided. The recommendations are generated by using a document with an insert.
For instructions, see ["Displaying AI recommendations > With documents and screen views"](/developers/mobile-sdk/displaying-recommendations/documents).
| | **iOS SDK** | **Android SDK** | **React Native SDK** | **Flutter SDK** |
| --- | --- | --- | --- | --- |
| Introduced in: | 4.13.0 | 5.5.0 | 0.17.0 | 0.6.0 |
The API key must have the `SCHEMA_SERVICE_SCHEMA_READ` permission from the **Schema** group.
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **feedSlug** | String | yes | - | Identifies a specific screen view feed |
| **success** | (([ScreenView](/developers/mobile-sdk/class-reference/ios/miscellaneous#screenview)) -> Void) | yes | - | Closure/Block to be executed when the operation is completed successfully |
| **failure** | (([SNRApiError](/developers/mobile-sdk/class-reference/ios/miscellaneous#snrapierror)]) -> Void) | yes | - | Closure/Block to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
## Generate screen view with query parameters
---
This method generates customer's highest-priority screen view campaign that is defined for parameters provided in the query object.
**Declared In:**
Headers/SNRContent.h
**Related To:**
[ScreenViewApiQuery](/developers/mobile-sdk/class-reference/ios/miscellaneous#screenviewapiquery)
[ScreenView](/developers/mobile-sdk/class-reference/ios/miscellaneous#screenview)
**Class:**
[Content](/developers/mobile-sdk/class-reference/ios/modules#content)
**Declaration:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **apiQuery** | [ScreenViewApiQuery](/developers/mobile-sdk/class-reference/ios/miscellaneous#screenviewapiquery) | yes | - | Object that stores all query parameters |
| **success** | (([ScreenView](/developers/mobile-sdk/class-reference/ios/miscellaneous#screenview)) -> Void) | yes | - | Closure/Block to be executed when the operation is completed successfully |
| **failure** | (([SNRApiError](/developers/mobile-sdk/class-reference/ios/miscellaneous#snrapierror)]) -> Void) | yes | - | Closure/Block to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
## Generate Brickworks
---
This method generates content from a published version of a [Brickworks](/docs/assets/brickworks) record. Inserts and fields which require a customer context fetch it automatically from the current user.
| | **iOS SDK** | **Android SDK** | **React Native SDK** | **Flutter SDK** |
| ----------------------------------------------- | ----------- | --------------- | -------------------- | --------------- |
| Introduced in: | 5.8.1 | 6.8.0 | 1.6.0 | 2.6.0 |
The API key must have the `BRICKWORKS_RECORDS_READ` permission from the **RECORDS** group.
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **slug** | string | yes | - | Slug of a document |
| **onSuccess** | Function | no | - | Function to be executed when the operation is completed successfully |
| **onError** | Function | no | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **apiQuery** | [DocumentApiQuery](/developers/mobile-sdk/class-reference/react-native/recommendations-and-documents#document) | yes | - | Object that stores all query parameters |
| **onSuccess** | Function | no | - | Function to be executed when the operation is completed successfully |
| **onError** | Function | no | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
```TypeScript
let apiQuery = new DocumentApiQuery('SLUG');
documentApiQuery.productId = "PRODUCT_ID";
Synerise.Content.generateDocumentWithApiQuery(apiQuery, function(document) {
//success
}, function(error) {
//failure
})
```
## Get recommendations (v2)
---
This method generates recommendations that are defined for the options provided. The recommendations are generated by using a document with an insert.
For instructions, see ["Displaying AI recommendations > With documents and screen views"](/developers/mobile-sdk/displaying-recommendations/documents).
| | **iOS SDK** | **Android SDK** | **React Native SDK** | **Flutter SDK** |
| --- | --- | --- | --- | --- |
| Introduced in: | 4.13.0 | 5.5.0 | 0.17.0 | 0.6.0 |
The API key must have the `SCHEMA_SERVICE_SCHEMA_READ` permission from the **Schema** group.
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **recommendationOptions** | [RecommendationOptions](/developers/mobile-sdk/class-reference/react-native/recommendations-and-documents#recommendationoptions) | yes | - | Object for configuration of the options parameters |
| **onSuccess** | Function | no | - | Function to be executed when the operation is completed successfully |
| **onError** | Function | no | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **feedSlug** | string | yes | - | Identifies a specific screen view feed |
| **onSuccess** | Function | no | - | Function to be executed when the operation is completed successfully |
| **onError** | Function | no | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
## Generate screen view with query parameters
---
This method generates customer's highest-priority screen view campaign that is defined for parameters provided in the query object.
**Declared In:**
lib/main/modules/ContentModule.js
**Related To:**
[ScreenViewApiQuery](/developers/mobile-sdk/class-reference/react-native/miscellaneous#screenviewapiquery)
[ScreenView](/developers/mobile-sdk/class-reference/react-native/miscellaneous#screenview)
**Class:**
[ContentModule](/developers/mobile-sdk/class-reference/react-native/modules#content)
**Declaration:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **apiQuery** | [ScreenViewApiQuery](/developers/mobile-sdk/class-reference/react-native/miscellaneous#screenviewapiquery) | yes | - | Object that stores all query parameters |
| **onSuccess** | Function | no | - | Function to be executed when the operation is completed successfully |
| **onError** | Function | no | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
```TypeScript
let apiQuery = new ScreenViewApiQuery("FEED_SLUG", "PRODUCT_ID");
Synerise.Content.generateScreenViewWithApiQuery(apiQuery, function(screenView) {
//success
},function(error) {
//failure
})
```
## Generate Brickworks
---
This method generates content from a published version of a [Brickworks](/docs/assets/brickworks) record. Inserts and fields which require a customer context fetch it automatically from the current user.
| | **iOS SDK** | **Android SDK** | **React Native SDK** | **Flutter SDK** |
| ----------------------------------------------- | ----------- | --------------- | -------------------- | --------------- |
| Introduced in: | 5.8.1 | 6.8.0 | 1.6.0 | 2.6.0 |
The API key must have the `BRICKWORKS_RECORDS_READ` permission from the **RECORDS** group.
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **apiQuery** | [BrickworksApiQuery](/developers/mobile-sdk/class-reference/react-native/miscellaneous#brickworksapiquery) | yes | - | Object with all query parameters |
| **onSuccess** | Function | no | - | Function to be executed when the operation is completed successfully |
| **onError** | Function | no | - | Function to be executed when the operation is completed with an error |
**Return Value:**
Object with content generated from a record.
**Example:**
```TypeScript
let apiQuery = new BrickworksApiQuery("SCHEMA_SLUG", "RECORD_SLUG");
Synerise.Content.generateBrickworksWithApiQuery(apiQuery, function(brickworks) {
//success
},function(error) {
//failure
})
```
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **slug** | string | yes | - | Slug of a document |
| **onSuccess** | Function | no | - | Function to be executed when the operation is completed successfully |
| **onError** | Function | no | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **documentsApiQuery** | [DocumentsApiQuery](/developers/mobile-sdk/class-reference/react-native/recommendations-and-documents#documentsapiquery) | yes | - | [DocumentsApiQuery](/developers/mobile-sdk/class-reference/react-native/recommendations-and-documents#documentsapiquery) object responsible for storing all query parameters |
| **onSuccess** | Function | no | - | Function to be executed when the operation is completed successfully |
| **onError** | Function | no | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
```JavaScript
let documentsApiQuery = new DocumentsApiQuery(DocumentsApiQueryType.SCHEMA, 'type', '1.0.0')
Synerise.Content.getDocuments(documentsApiQuery, function(documents) {
//success
}, function(error) {
//failure
})
```
### Get recommendations {#get-recommendations}
---
This method generates recommendations that are defined for the options provided.
| | **iOS SDK** | **Android SDK** | **React Native SDK** | **Flutter SDK** |
| --- | --- | --- | --- | --- |
| Removed in: | 5.0.0 | 6.0.0 | 1.0.0 | 2.0.0 |
The API key must have the `SCHEMA_SERVICE_DOCUMENT_READ` permission from the **Document** group.
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **recommendationOptions** | [RecommendationOptions](/developers/mobile-sdk/class-reference/react-native/recommendations-and-documents#recommendationoptions) | yes | - | Object for configuration of the options parameters |
| **onSuccess** | Function | no | - | Function to be executed when the operation is completed successfully |
| **onError** | Function | no | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
**Example:**
**Parameters:**
| Parameter | Type | Mandatory | Default | Description |
| --- | --- | --- | --- | --- |
| **onSuccess** | Function | no | - | Function to be executed when the operation is completed successfully |
| **onError** | Function | no | - | Function to be executed when the operation is completed with an error |
**Return Value:**
No value is returned.
# Miscellaneous
## Error handling
---
This feature is available only in Android SDK and iOS SDK.
`ApiError` is an object for error handling. It's designed to help you handle errors within your application. It provides details about failures in communication with the Synerise API.
This error is normally returned from the SDK methods that communicate with the Synerise API.
### Properties {id=error-handling-properties}
| Property | Method |
| --- | --- |
| Throwable | apiError.getThrowable() |
| Stacktrace | apiError.printStackTrace() |
| Type | apiError.getErrorType() |
| HTTP code | apiError.getHttpErrorCategory() |
| Body | apiError.getErrorBody() |
#### Throwable {id=error-handling-android-throwable-parameter}
Returns the original Throwable instance. It may be null if ApiError was instantiated with the `ApiError(Response)` constructor.
#### Stacktrace {id=error-handling-android-stacktrace-parameter}
Prints the stack trace of the original Throwable instance.
#### Type {id=error-handling-android-type-parameter}
`ErrorType.HTTP_ERROR` is returned when a request is executed, but something else goes wrong and an error code is returned (for example, 403).
`ErrorType.NETWORK_ERROR` is returned when a request failed to execute (for example, due to no Internet connection).
`ErrorType.UNKNOWN` is returned when an unknown error occurs (for example, no response from the server when expected).
#### HTTP code {id=error-handling-android-http-code-parameter}
Returns the HTTP status code. If the request failed to execute (for example, due to no Internet connection), this value will be `-1`.
#### HTTP error category {id=error-handling-android-http-error-category-parameter}
Returns the mapped response's HTTP code (for example, HTTP 400 code will be mapped to `HttpErrorCategory.BAD_REQUEST`, or 403 to `HttpErrorCategory.FORBIDDEN`).
#### Body {id=error-handling-android-body-parameter}
Returns the ApiErrorBody parsed from the error's response body. May be null if error type is different than `ErrorType.HTTP_ERROR`.
| Property | Method |
| --- | --- |
| Type | apiError.getType() |
| HTTP code | apiError.getHttpCode() |
| Body | apiError.getBody() |
#### Type {id=error-handling-ios-body-parameter}
`SNRApiErrorType.Http` is returned when a request is executed, but something else goes wrong and an error code is returned (for example, 403).
`SNRApiErrorType.Network` is returned when a request failed to execute (for example, due to no Internet connection).
`SNRApiErrorType.Unknown` is returned when an unknown error occurs (for example, no response from the server when expected).
#### HTTP code {id=error-handling-ios-http-code-parameter}
The method returns the HTTP status code. If a request failed to execute (for example, due to no Internet connection), this value is `-1`.
#### Body {id=error-handling-ios-body-parameter}
Returns a description parsed from the response's error cause list. It may be null if the error type is different than `ApiErrorTypeHttp`.
### Sample {id=sample-code-for-error-handling}
See the following code samples for reading errors:
```Java
private void showAlertError(ApiError apiError) {
ApiErrorBody errorBody = apiError.getErrorBody();
int httpCode = apiError.getHttpCode();
// create AlertDialog with icon and title
AlertDialog.Builder dialog = new AlertDialog.Builder(this).setIcon(R.drawable.sygnet_synerise);
if (httpCode != ApiError.UNKNOWN_CODE) {
dialog.setTitle(String.valueOf(httpCode));
} else {
dialog.setTitle(R.string.default_error);
}
// append all available messages from API
if (errorBody != null) {
List errorCauses = errorBody.getErrorCauses();
StringBuilder message = new StringBuilder(errorBody.getMessage());
if (!errorCauses.isEmpty())
for (ApiErrorCause errorCause : errorCauses)
message.append("\n").append(errorCause.getCode()).append(": ").append(errorCause.getMessage());
dialog.setMessage(message.toString());
// if there is no available messages, set default one
} else {
switch (apiError.getErrorType()) {
case HTTP_ERROR:
if (apiError.getHttpErrorCategory() == UNAUTHORIZED) {
dialog.setMessage(getString(R.string.error_unauthorized));
} else {
dialog.setMessage(getString(R.string.error_http));
}
break;
case NETWORK_ERROR:
dialog.setMessage(getString(R.string.error_network));
break;
default:
dialog.setMessage(getString(R.string.error_default));
}
}
// show dialog
dialog.show();
}
```
```Kotlin
private fun showAlertError(apiError: ApiError) {
val errorBody = apiError.errorBody
val httpCode = apiError.httpCode
// create AlertDialog with icon and title
val dialog: AlertDialog.Builder = Builder(this).setIcon(R.drawable.sygnet_synerise)
if (httpCode != ApiError.UNKNOWN_CODE) {
dialog.setTitle(httpCode.toString())
} else {
dialog.setTitle(R.string.default_error)
}
// append all available messages from API
if (errorBody != null) {
val errorCauses = errorBody.errorCauses
val message = StringBuilder(errorBody.message!!)
if (!errorCauses.isEmpty()) for (errorCause in errorCauses) message.append("\n").append(errorCause.code).append(": ").append(errorCause.message)
dialog.setMessage(message.toString())
// if there is no available messages, set default one
} else {
when (apiError.errorType) {
ErrorType.HTTP_ERROR -> if (apiError.httpErrorCategory == UNAUTHORIZED) {
dialog.setMessage(getString(R.string.error_unauthorized))
} else {
dialog.setMessage(getString(R.string.error_http))
}
ErrorType.NETWORK_ERROR -> dialog.setMessage(getString(R.string.error_network))
else -> dialog.setMessage(getString(R.string.error_default))
}
}
// show dialog
dialog.show()
}
```
```Swift
func presentAlert(title: String, message: String) {
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: .default, handler: nil)
alertController.addAction(okAction)
self.present(alertController, animated: true, completion: nil)
}
func showErrorInfo(_ error: NSError, title: String = "Error", debug: Bool = true) {
if let apiError = error as? SNRApiError {
var apiErrorDebugInfo: String = String()
let apiErrorType: SNRApiErrorType = apiError.getType()
switch (apiErrorType) {
case .network: apiErrorDebugInfo.append("NETWORK ERROR")
case .unauthorizedSession: apiErrorDebugInfo.append("UNAUTHORIZED SESSION ERROR")
case .http: apiErrorDebugInfo.append("HTTP ERROR: \(apiError.getHttpCode())")
case .unknown: apiErrorDebugInfo.append("UNKNOWN ERROR")
}
apiErrorDebugInfo.append("\n\n")
apiErrorDebugInfo.append("\(apiError.localizedDescription)")
// first approach
if let apiErrorCauses = apiError.errors, !apiErrorCauses.isEmpty {
apiErrorDebugInfo.append("\n\n")
apiErrorCauses.forEach({ (error) in
let apiErrorCause: NSError = error as NSError
var apiErrorCauseString: String = String()
apiErrorCauseString.append("CODE: \(apiErrorCause.code)")
apiErrorCauseString.append("\n")
apiErrorCauseString.append("MESSAGE: \(apiErrorCause.localizedDescription)")
apiErrorDebugInfo.append(apiErrorCauseString)
apiErrorDebugInfo.append("\n\n")
})
}
// second approach
// apiErrorDebugInfo.append("\n\n")
//
// let apiErrorCauseString: String = apiError.getBody() ?? ""
// apiErrorDebugInfo.append(apiErrorCauseString)
self.presentAlert(title: "Debug SNRApiError", message: apiErrorDebugInfo)
if debug {
DebugUtils.print("\(title) \(apiError.code) \(apiError.localizedDescription)")
}
return
}
if debug {
DebugUtils.print("\(title) \(error.code) \(error.localizedDescription)")
}
}
func signIn(email: String, password: String) {
Client.signIn(email: email, password: password, deviceId: nil, success: { (success) in
//...
}, failure: { (error) in
self.showErrorInfo(error as NSError)
})
}
```
```Objective-C
[SNRClient signInWithEmail:email password:password deviceId:nil success:^(BOOL isSuccess) {
} failure:^(NSError * _Nonnull error) {
if ([error isKindOfClass:[SNRApiError class]]) {
SNRApiError *apiError = (SNRApiError *)error;
NSLog(apiError.localizedFailureReason) // print information string about all issues
NSLog(apiError.errors) // print list of error objects about issues that occurred
}
}];
```
## Crash handling
---
Crash handler allows you to detect mobile app users whose mobile applications crashed. This information is saved on the activity list of a mobile app user in Behavioral Data Hub in the form of an event.
The crash is connected with a customer. Using the data from our crash handler, you can send a personalized apology when the application crashes.
You can enable crash handling for Synerise SDK by using an SDK method (Android and iOS) or during initialization by using a builder method (React Native).
When it is enabled, the **Synerise SDK** passes info about an application crash in the form of a dedicated event to the backend (`client.applicationCrashed` is the **action** parameter of those events).
See sample codes below:
This feature is available only in Android and iOS SDK.
**Cache Manager** provides you with an easy-to-use option to retrieve cached data if communication problems with the backend occur. If a request fails, you can obtain the cached data.
Currently, our Cache Manager supports:
| Model | Description |
| --- | --- |
| [`GetAccountInformation`](/developers/mobile-sdk/class-reference/android/client#getaccountinformation) | Caching after a successful `Client.getAccount()` response. |
| Model | Description |
| --- | --- |
| [`ClientAccountInformation`](/developers/mobile-sdk/class-reference/ios/client#clientaccountinformation) | Caching after a successful `Client.getAccount()` response. |
See the following code examples for accessing the cache: