EMMA tiene unos bindings nativos para Flutter que conforman el SDK de EMMA para Flutter.
En el pubspec.yaml añade la siguiente línea:
dependencies:
emma_flutter_sdk: 1.6.4
Para importar la librería en el código Dart:
import 'package:emma_flutter_sdk/emma_flutter_sdk.dart';
La versión más reciente del SDK para Flutter es la 1.7.0.
Es importante que en AndroidManifest.xml la Activity MainActivity tenga como atributo launchMode="singleTask":
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize">
En Android debemos incluir el icono de la notificación como drawable.
/app/res/drawable del proyecto de Android Studio.Para integrar el push hay que añadir el servicio push de EMMA en el AndroidManifest.xml de la app de Android, dentro del tag <application>. Este servicio es el que monta y muestra la notificacion push:
<service
android:name="io.emma.android.push.EMMAFcmMessagingService"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
Indica el uso del plugin de google-services en android/build.gradle:
buildscript {
....
repositories {
....
google()
}
dependencies {
...
classpath 'com.google.gms:google-services:4.3.15'
}
}
Una vez el servicio esté incluido añadimos las dependencias de push y aplicamos el plugin de google-services en el archivo android/app/build.gradle:
dependencies {
....
implementation 'com.google.firebase:firebase-messaging:21.0.1'
}
apply plugin: 'com.google.gms.google-services'
No olvidar añadir el
google-services.jsonobtenido en la consola de Firebase en la rutaandroid/app/.
Para utilizar el Powlink o Deeplinking en Android es necesario añadir la siguiente Activity al AndroidManifest.xml de la app, dentro de <application>:
<activity
android:name="io.emma.android.activities.EMMADeepLinkActivity"
android:noHistory="true"
android:exported="true"
android:theme="@android:style/Theme.NoDisplay">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="${DEEPLINK_SCHEME}"/>
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data
android:host="${CUSTOM_POWLINK_DOMAIN}.powlink.io"
android:scheme="https"/>
<data
android:host="${CUSTOM_SHORT_POWLINK_DOMAIN}.pwlnk.io"
android:scheme="https"/>
</intent-filter>
</activity>
Reemplazar ${DEEPLINK_SCHEME} por el esquema de deeplink de la app, por ejemplo: emmarn (de emmarn://). El esquema básico de deeplink se utiliza para realizar acciones desde comunicación In-App, también para utilizar la landing de redirección de deeplinks en AppTracker.
Reemplazar ${CUSTOM_POWLINK_DOMAIN} y ${CUSTOM_SHORT_POWLINK_DOMAIN} por los dominios configurados en el dashboard de EMMA en la sección de preferencias de la app.
Debajo de la Activity, en el mismo AndroidManifest.xml, hay que añadir también el siguiente <meta-data>:
<meta-data
android:name="io.emma.DEEPLINK_OPEN_ACTIVITY"
android:value="${PACKAGE_NAME}.MainActivity"/>
${PACKAGE_NAME} por la ruta del fichero MainActivity, por ejemplo (com.example.MainActivity). Este meta-data indica al SDK de EMMA qué Activity tiene que abrir al recibir un deeplink, en el caso de los SDKs híbridos solo suele haber una Activity.La configuración descrita en esta sección (Powlink y Deeplinking) es también necesaria para que los Rich Push URL definidos en campañas de notificaciones push sean correctamente capturados en la app de Flutter. Al pulsar sobre la notificación, nos podemos encontrar con dos escenarios:
MainActivity y si has configurado el handler en Flutter (setDeepLinkHandler), recibirás el deeplink para gestionarlo.En Android, es fundamental añadir el método
checkForRichPushpara comprobar elrichPushUrlcuando se abre la app desde la notificación.
Para más detalles en la integración, véase la sección Powlink y Deeplinking contenida en el apartado de Integración en Dart.
Asegúrate al arrancar el proyecto que la dependencia de EMMA está instalada. Para ello, ejecuta flutter build ipa.
Para añadir el Powlink (Universal Link) dirígete a la sección Capabilities dentro del target de la app en Xcode y añade Associated Domains. Seguidamente, añadiremos el Powlink con el formato applinks:customsubdomain.powlink.io.
Nótese que
customdomaines el subdominio configurado en el Dashboard de EMMA.


En el caso del deeplink básico, es necesario añadir el esquema en la sección Info dentro del target de la app en Xcode y en URL Types añade una nueva entrada dónde puedes definir el esquema de la app.

Las configuraciones de Powlink (Universal Links) y URL Schemes descritas aquí (Powlink y Deeplinking) son también necesarias para que la app pueda recibir correctamente los Rich Push URL definidos desde el dashboard de EMMA en campañas de notificaciones push.
Cuando un usuario pulsa la notificación, el sistema abrirá la app y EMMA entregará el deeplink a través del método setDeepLinkHandler del SDK en Flutter. En caso de ser una URL, la abrirá.
Asegúrate de haber configurado previamente:
applinks:subdominio.powlink.io en Associated Domains.startSession() y startPushSystem() al inicio de la app.Para más detalles en la integración, véase la sección Powlink y Deeplinking contenida en el apartado de Integración en Dart.
Para integrar SKAdNetwork consulta la documentación nativa aquí.
Para usar la localización es necesario añadir los siguientes permisos en el archivo Info.plist de la App:
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>$(PRODUCT_NAME) needs location access</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>$(PRODUCT_NAME) needs location access</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>$(PRODUCT_NAME) needs location access</string>
Para solicitar el IDFA es necesario añadir el siguiente permiso al Info.plist:
<key>NSUserTrackingUsageDescription</key>
<string>Uso del indentificador para redes de terceros</string>
Los ejemplos de está sección se realizan sobre archivos dart.
Para importar el SDK en el código usa el siguiente import:
import 'package:emma_flutter_sdk/emma_flutter_sdk.dart';
Actualmente, la clase
StartSessiondebe importarse de forma explícita.
import 'package:emma_flutter_sdk/src/start_session.dart';
Ejemplo de archivo main.dart:
@override
void initState() {
super.initState();
initPlatformState();
initEMMA()
}
final startSessionParams = StartSession(
sessionKey: "<EMMAKey>",
queueTime: 10,
isDebug: true,
customShortPowlinkDomains: ["emma.shortLink.mycompany.com"],
customPowlinkDomains: ["emma.link.mycompany.com"],
trackScreenEvents: false,
skanAttribution: true, // Solo para iOS
familiesPolicyTreatment: false, // Solo para Android
);
Future<void> initEMMA() async {
await EmmaFlutterSdk.shared
.startSession(startSessionParams);
}
Parámetros de configuración para el inicio de sesión:
| Parámetro | Tipo | Descripción |
|---|---|---|
| sessionKey | String | Clave de EMMA para identificación en el inicio de sesión. |
| apiUrl | String (Optional) | Añade la URL si se usa un proxy. |
| queueTime | Int (Optional) | Tiempo para vaciar la cola de operaciones. |
| isDebug | Boolean (Optional) | Activa/desactiva los logs en el SDK. |
| customPowlinkDomains | String (Optional) | Añade los dominios si la app usa dominios custom en EMMA (los subdominios que se configuran en preferencias de la app no son dominios custom). |
| customShortPowlinkDomains | String (Optional) | Añade los dominios cortos si la app usa dominios custom en EMMA (los subdominios que se configuran en preferencias de la app no son dominios custom). |
| trackScreenEvents | Boolean (Optional) | Activa/desactiva el seguimiento de pantallas automáticas. |
| skanAttribution | Boolean (Optional) (iOS) | Habilita la atribución de SKAdNetwork. Por defecto se envía como true. |
| familiesPolicyTreatment | Boolean (Optional) (Android) | Activa/desactiva el cumplimiento de la política de familias asociada al programa "Designed for Families". En caso de estar a true, se desactiva el rastreo de advertising ID para proteger la privacidad de menores. Solo necesario para Android. |
Añade el startPushSystem en el archivo main.dart después del startSession:
Future<void> initEMMA() async {
await EmmaFlutterSdk.shared
.startSession('<SESSION_KEY>', debugEnabled: true);
await EmmaFlutterSdk.shared.startPushSystem('icimage');
}
Parámetros del startPushSystem:
| Parámetro | Tipo | Descripción |
|---|---|---|
| notificationIcon | String | El icono que contendrá la notificación en la status bar y en el menú de notificaciones. El SDK busca ese icono de la carpeta drawable o drawable-xxx. Por tanto, es importante que el nombre que se incluya en este parámetro coincida con el png de drawable. |
| notificationChannelId | String (Opcional) | Si la aplicación usa un canal de notificaciones ya existente, sino creará uno nuevo. |
| notificationChannel | String (Opcional) | Añade el nombre del nuevo canal. |
El uso del
startPushSystemes válido para Android e iOS, aunque los parámetros solo sean usados en Android ya que en iOS coge los valores por defecto de la App.
Para obtener el deeplink o powlink una vez abierta la aplicación, añade el siguiente handler después de iniciar sesión:
// El DeepLink/Powlink es capturado en este handler.
EmmaFlutterSdk.shared.setDeepLinkHandler((url) {
print(url);
});
En caso de querer notificar a EMMA por tener un sistema de gestión personalizado y no sometido a la integración automática de EMMA, para procesar el link y enviar el click a EMMA, disponemos del método handleLink:
EmmaFlutterSdk.shared.handleLink(url);
En Android, para comprobar el
richPushUrlcuando se abre la app desde la notificación, debemos añadir el métodocheckForRichPushUrl.
Cuando se envía una notificación push desde el dashboard de EMMA con un Rich Push URL configurado, este handler capturará automáticamente el deeplink al pulsar sobre la notificación.
Puedes utilizar este valor para redirigir al usuario dentro de la app, por ejemplo:
EmmaFlutterSdk.shared.setDeepLinkHandler((url) {
if (url != null) {
// Navegar
}
});
Asegúrate de haber configurado correctamente el sistema de deeplinks de EMMA tanto en Android como en iOS.
En caso de ser una URL, EMMA la abrirá.
// main.dart
// class _MyAppState extends State<MyApp>
@override
void initState() {
super.initState();
initEMMA()
.then((value) => initEMMAPush())
}
Future<void> initEMMA() async {
await EmmaFlutterSdk.shared.startSession(startSessionParams);
EmmaFlutterSdk.shared.setDeepLinkHandler((url) {
this.deeplink = url;
print(url);
});
}
Future<void> initEMMAPush() async {
if (Platform.isAndroid) {
EmmaFlutterSdk.shared.setPermissionStatusHandler((status) {
print('Notifications permission status: ' + status.toString());
});
await EmmaFlutterSdk.shared.requestNotificationsPermission();
await EmmaFlutterSdk.shared.checkForRichPush();
}
return await EmmaFlutterSdk.shared.startPushSystem('icimage');
}
Se puede consultar la solución completa de EMMA en Flutter en la app de ejemplo.
EMMA permite el envío de eventos personalizados y de varios eventos por defecto. Por ejemplo, el evento por defecto Apertura se envía al iniciar sesión en el SDK. Sin embargo, el evento login y registro son eventos que hay que añadir.
Para realizar el envío de un evento personalizado con un token creado en el panel de Eventos de EMMA, empleamos el siguiente método:
await EmmaFlutterSdk.shared.trackEvent("2eb78caf404373625020285e92df446b");
Para realizar el registro y/o login es necesario enviar el id del usuario en la app (Customer ID):
await EmmaFlutterSdk.shared
.loginUser("userflutter#23243", "emma@flutter.dev");
await EmmaFlutterSdk.shared
.registerUser("userflutter#23243", "emma@flutter.dev");
EMMA permite el envío de propiedades clave/valor asociadas al dispositivo:
await EmmaFlutterSdk.shared
.trackUserTags({'TEST_TAG': 'TEST VALUE'});
Este método reemplaza al método deprecado
trackExtraUserInfo, que seguirá funcionando pero se recomienda migrar atrackUserTags.
await EmmaFlutterSdk.shared
.trackExtraUserInfo({'TEST_TAG': 'TEST VALUE'});
Para medir la localización del usuario añade el siguiente método:
await EmmaFlutterSdk.shared.trackUserLocation();
La localización del usuario solo se recogerá una vez al iniciar la app.
EMMA permite medir cualquier transacción o compra que se realice en tu app en una única llamada con el método trackPurchase.
var products = [
EmmaPurchaseProduct('prod_001', 'Jeans', 1, 29.99)
];
var request = EmmaPurchaseRequest('ORDER_12345', 29.99, products);
request.customerId = 'user_12345';
await EmmaFlutterSdk.shared.trackPurchase(request);
El método
trackPurchasereemplaza a los métodos deprecadosstartOrder,addProductytrackOrder. Se recomienda migrar al nuevo métodotrackPurchasepara un seguimiento más simple y robusto de las transacciones.
// Start order
var order = new EmmaOrder("EMMA", 100, "1");
await EmmaFlutterSdk.shared.startOrder(order);
// Add products
var product = new EmmaProduct('SDK', 'SDK', 1, 100);
await EmmaFlutterSdk.shared.addProduct(product);
// Commit order
await EmmaFlutterSdk.shared.trackOrder();
EMMA incluye 5 formatos comunicativos diferentes que puedes integrar para impactar a tus usuarios en Flutter:
El formato Banner solo está soportado en Android.
Los NativeAds de EMMA te permiten integrar publicidad personalizada que se adapta al diseño de tu aplicación. A diferencia de otros formatos (StartView, AdBall, etc.), tú controlas completamente cómo se visualiza el contenido. EMMA proporciona los datos (título, imagen, CTA, etc.) configurados en el dashboard de EMMA y tu app decide cómo mostrarlos.
Antes de solicitar un NativeAd, debes:
Para saber con más detalle cómo configurar un NativeAd en el dashboard, consulta nuestra documentación principal.
EmmaFlutterSdk.shared
.setReceivedNativeAdsHandler((List<EmmaNativeAd> nativeAds) {
nativeAds.forEach((nativeAd) {
// Procesar cada NativeAd recibido
print(nativeAd.toMap());
});
});
var request = EmmaInAppMessageRequest(InAppType.nativeAd);
request.templateId = "templateId";
request.batch = false; // o no especificar
await EmmaFlutterSdk.shared.inAppMessage(request);
var request = EmmaInAppMessageRequest(InAppType.nativeAd);
request.templateId = "template1";
request.batch = true;
await EmmaFlutterSdk.shared.inAppMessage(request);
await EmmaFlutterSdk.shared.sendInAppImpression(
InAppType.nativeAd,
nativeAd.id
);
openNativeAd() abre el CTA y maneja automáticamente el tracking de clics, no requiere llamar a sendInAppClick().
await EmmaFlutterSdk.shared.openNativeAd(nativeAd);
Si necesitas trackear el clic sin abrir el CTA.
await EmmaFlutterSdk.shared.sendInAppClick(
InAppType.nativeAd,
nativeAd.id
);
// Si el usuario cierra la comunicación sin hacer clic
await EmmaFlutterSdk.shared.sendInAppDismissedClick(
InAppType.nativeAd,
nativeAd.id
);
// Configurar handler
EmmaFlutterSdk.shared.setReceivedNativeAdsHandler(
(List<EmmaNativeAd> nativeAds) {
nativeAds.forEach((nativeAd) {
// Mostrar NaiveAd en UI
displayNativeAd(nativeAd);
// Enviar impresión
EmmaFlutterSdk.shared.sendInAppImpression(
InAppType.nativeAd,
nativeAd.id
);
});
}
);
// Solicitar múltiples NativeAds
var request = EmmaInAppMessageRequest(InAppType.nativeAd);
request.batch = true;
request.templateId = "templateId";
await EmmaFlutterSdk.shared.inAppMessage(request);
// Manejar interacción del usuario
// Cuando hace click en el CTA
await EmmaFlutterSdk.shared.openNativeAd(nativeAd);
// O cuando cierra sin interactuar
await EmmaFlutterSdk.shared.sendInAppDismissedClick(
InAppType.nativeAd,
nativeAd.id
);
Cualquier formato que no sea NativeAd no espera un resultado ya que se inyecta automáticamente en la vista. Ejemplos de uso:
// StartView
await EmmaFlutterSdk.shared.inAppMessage(new EmmaInAppMessageRequest(InAppType.startview));
// AdBall
await EmmaFlutterSdk.shared.inAppMessage(new EmmaInAppMessageRequest(InAppType.adBall));
// Banner
await EmmaFlutterSdk.shared.inAppMessage(new EmmaInAppMessageRequest(InAppType.banner));
// Strip
await EmmaFlutterSdk.shared.inAppMessage(new EmmaInAppMessageRequest(InAppType.strip));
Los formatos StartView, AdBall, Banner y Strip, al ser inyectados, envían los eventos de impresión y clic de forma automática cuando se realizan dichas acciones.
Si en la app no se usan los eventos login/registro para notificar el customerId, puedes enviarlo con el siguiente método:
await EmmaFlutterSdk.shared.setCustomerId("user#12345");
Permite asociar un email con el dispositivo del usuario.
await EmmaFlutterSdk.shared.setEmail('user@example.com');
Permite configurar el perfil del usuario de forma completa, incluyendo identificador de cliente, email (opcional) y tags personalizados (opcional) en una única llamada.
await EmmaFlutterSdk.shared.setUserProfile(
'user_12345',
email: 'user@example.com',
tags: {
'subscription': 'premium'
}
);
Establece manualmente el idioma preferido del usuario.
Este método permite sobrescribir el idioma predeterminado del dispositivo para establecer un idioma personalizado que se utilizará en todas las peticiones del SDK. Esto resulta útil en aplicaciones que permiten al usuario seleccionar un idioma diferente al configurado en el dispositivo.
Se debe usar el código de idioma en formato ISO 639-1: es (español), en (inglés), fr (francés), de (alemán), it (italiano), zh-Hans (chino simplificado), zh-Hant (chino tradicional), etc.
// En este caso, establece inglés como idioma
await EmmaFlutterSdk.shared.setUserLanguage("en");
Si no se llama a este método, EMMA utilizará por defecto el idioma preferido del usuario configurado en el sistema del dispositivo.
Para solicitar el identificador IDFA, usa el siguiente método:
if (Platform.isIOS) {
await EmmaFlutterSdk.shared.requestTrackingWithIdfa();
}
Desde Android 13, para recibir notificationes es necesario solicitar un permiso al usuario. A partir de la versión 1.2.0 se ha añadido el siguiente método para solicitar el permiso:
if (Platform.isAndroid) {
// Request notification permission for Android 13
EmmaFlutterSdk.shared.setPermissionStatusHandler((status) {
print('Notifications permission status: ' + status.toString());
});
await EmmaFlutterSdk.shared.requestNotificationsPermission();
}
Para controlar el uso de la ley de protección de datos, EMMA pone a disposición varios métodos para activar/desactivar el seguimiento de los usuarios.
// Enable user tracking
await EmmaFlutterSdk.shared.enableUserTracking();
//Disable user tracking
await EmmaFlutterSdk.shared.disableUserTracking(false);
El método disableUserTracking pone a disposición un flag para eliminar el usuario de forma permanente en el caso de que se deshabilite el seguimiento.
Hay que tener en cuenta que está acción es irreversible y todos los datos asociados al usuario se perderán.
Para comprobar si el seguimiento está activado o desactivado usa el siguiente método:
var isEnabled = await EmmaFlutterSdk.shared.isUserTrackingEnabled();