De un vistazo: El SDK V6.X para iOS de AppsFlyer, denominado SDK, proporciona la funcionalidad de atribución de aplicaciones y reportes de eventos a las aplicaciones de iOS, al mismo tiempo que permite a los propietarios y desarrolladores de aplicaciones prepararse para el próximo lanzamiento de iOS 14. Esta versión del SDK incorpora cambios significativos en el método en comparación con las versiones anteriores.
Notas de la versión (hasta V6.0.4)
¡Importante!
El SDK V5.4.4 para iOS es completamente operativo con el iOS 14. Sin embargo, recomendamos actualizar al SDK V6 para asegurar la compatibilidad con futuros lanzamientos de iOS para futuras actualizaciones de iOS. Consulta Actualización a iOS SDK V6.
1. Resumen
El SDK proporciona la funcionalidad de registro de eventos e instalación de aplicaciones. El SDK es sólido, seguro, liviano y fácil de integrar.
Puedes registrar instalaciones, actualizaciones, sesiones y eventos in-app. Los eventos in-app admiten las compras in-app, los niveles de juego, etc. para evaluar el ROI y la calidad del usuario.
Versión de iOS | Modelos de atribución admitidos |
---|---|
iOS 13 y versiones anteriores |
|
iOS 14 y superior (probado con iOS 14 beta 7) |
|
* iOS SDK V5.4 y versiones anteriores:
|
1.1 Integración del SDK: lo que necesitas hacer
Pestaña | Finalidad | Resultado |
---|---|---|
Integración del SDK |
Muestra cómo agregar y configurar el SDK. |
|
API centrales |
Muestra cómo usar las API centrales del SDK. Estas API permiten medir eventos in-app e ingresos, establecer enlaces profundos y recopilar datos de conversión. |
Los eventos in-app y los ingresos aparecen en tu panel de control. Puedes crear enlaces profundos. |
Muestra cómo implementar y usar API opcionales, como medidas de desinstalación, referencias (atribución de invitación de usuario) y notificaciones push. |
Puedes medir desinstalaciones, referencias y el engagement del usuario con notificaciones push, manejar situaciones de privacidad del usuario y más. |
|
Referencia rápida de las API del SDK para desarrolladores |
|
1.2 Compatibilidad del SDK con iOS
- Este SDK es:
- Compatible con todos los dispositivos iOS y tvOS (iPhone, iPod, iPad, Apple TV) con iOS versión 6 y posteriores y tvOS versión 9 y posteriores.
- Cumple con las redes IPv6 DNS64/NAT64 de Apple.
Nota
¡Los Apps Clips de iOS 14 de Apple están a la vuelta de la esquina!
Aprende todo sobre ellos en nuestra Guía definitiva para desarrolladores sobre App Clips
Esta pestaña explica cómo implementar e inicializar el SDK, y la escribimos para ti, el desarrollador de la aplicación. Al completar esta pestaña, se muestran dos instalaciones en el panel de control de la aplicación, una orgánica y otra no orgánica.
2. Cómo agregar el SDK a tu aplicación
2.1 Cómo descargar y agregar el SDK a Xcode
- Descarga e instala la última versión de CocoaPods.
- Agrega la siguiente fila a
Podfile
:pod 'AppsFlyerFramework'
- Ejecuta la
instalación pod
. - Usa el archivo
.xcworkspace
para abrir tu proyecto en Xcode, en lugar del archivo.xcodeproj
, de aquí en adelante.
Nota
Si estás desarrollando una aplicación tvOS, CocoaPods agrega automáticamente las dependencias relevantes de AppsFlyerFramework.
- Instala la última versión de Carthage.
- Agrega la siguiente línea a tu Cartfile binario:
https://raw.githubusercontent.com/AppsFlyerSDK/AppsFlyerFramework/master/Carthage/appsflyer-ios.json
Nota
El enlace de arriba enlaza a una biblioteca estática. Si estás actualizando a una versión más reciente de iOS, haz lo siguiente:
- Elimina la etapa Run Script de Xcode que ejecuta marcos de copia.
- Asegúrate de que la biblioteca no esté incrustada.
Para aprender más, consulta los Documentos de Carthage.
Actualmente no es compatible con las aplicaciones de tvOS.
- Descarga el SDK de iOS como un marco estático.Para verificar la integridad de la descarga del marco estático del SDK, haga clic aquí.
- Descomprime el archivo AppsFlyerLib.framework.zip que acabas de descargar
- Arrastra la AppsFlyerLib.framework y colócala en tu proyecto de Xcode
- Asegúrate de que esté marcada la opción Copiar elementos si es necesario.
Nota
Este método es compatible solamente con iOS 8 y versiones posteriores.
Para las aplicaciones de tvOS, necesitas un AppsFlyerFramework diferente:
- Clona este repositorio.
- Encuentra AppsFlyerLib.framework en esta carpeta del repositorio clonado.
- Repite los pasos 3 y 4.
2.2 Cómo agregar marcos de soporte de anuncios
Este SDK usa los siguientes marcos nativos:
- AdSupport.framework
- Para recolectar el identificador de anunciante (IDFA) de los dispositivos, necesitarás este marco.
Sin el IDFA, no podrás atribuir instalaciones de Facebook Ads, Twitter, Google Ads y otras redes. - iAd.framework
- Este marco es necesario para registrar y medir el rendimiento de Apple Search Ads en tu aplicación.
Si deseas eliminar estos marcos y deshabilitar la recopilación del identificador de anunciante (IDFA):
- Para deshabilitar la recolección del identificador de anunciante (IDFA), consulta las instrucciones aquí.
- Para desactivar iAd.framework, consulta las instrucciones aquí.
Para agregar marcos de soporte de anuncios:
- En tu proyecto de Xcode, selecciona el objetivo del proyecto.
- Selecciona la pestaña General para tu objetivo.
- Expande la sección Marcos y librerías enlazados.
- Haz clic en + para agregar un marco.
- Buscar AdSupport.framework
- Selecciona AdSupport.framework en la lista.
Repite el proceso para iAd.framework.
3. Cómo implementar e inicializar el SDK
Esta sección describe cómo implementar e inicializar el SDK de AppsFlyer para iOS.
3.1 Cómo recuperar tu clave de desarrollador
AppsFlyer usa la clave de desarrollador para identificar tu cuenta de manera exclusiva. La clave de desarrollador es obligatoria porque permite que el SDK envíe y recupere datos que pertenecen a tu cuenta de AppsFlyer de manera segura.
Para hacer esto:
- Ve al panel de control de tu aplicación.
- En el panel de control, en Configuración, haz clic en Configuración de la aplicación.
- Copia tu clave de desarrollador.
3.2 Cómo configurar el SDK en el delegado de aplicación
En AppDelegate.h, haz lo siguiente:
- Importa
AppsFlyerLib/AppsFlyerLib.h
. - Agrega
AppsFlyerLibDelegate
a la declaración de interfaz.
#import <UIKit/UIKit.h>
#import <AppsFlyerLib/AppsFlyerLib.h>
#import <AppTrackingTransparency/ATTrackingManager.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate, AppsFlyerLibDelegate>
@end
En AppDelegate.swift, haz lo siguiente:
- Import AppsFlyerLib.
- Agrega
AppsFlyerLibDelegate
a la declaración de clase.
import AppsFlyerLib
class AppDelegate: UIResponder, UIApplicationDelegate, AppsFlyerLibDelegate {
// your code here
}
3.3 Cómo inicializar el SDK
#import "AppDelegate.h"
#import <AppsFlyerLib/AppsFlyerLib.h>
#import <AppTrackingTransparency/AppTrackingTransparency.h>
#import <UserNotifications/UserNotifications.h>
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
/** APPSFLYER INIT **/
[AppsFlyerLib shared].appsFlyerDevKey = @"<YOUR_DEV_KEY>";
[AppsFlyerLib shared].appleAppID = @"<APPLE_APP_ID>";
[AppsFlyerLib shared].delegate = self;
/* Set isDebug to true to see AppsFlyer debug logs */
[AppsFlyerLib shared].isDebug = true;
if (@available(iOS 10, *)) {
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
[center requestAuthorizationWithOptions:(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error) {
}];
} else {
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes: UIUserNotificationTypeAlert | UIUserNotificationTypeSound | UIUserNotificationTypeBadge categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
}
[[UIApplication sharedApplication] registerForRemoteNotifications];
return YES;
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
[[AppsFlyerLib shared] start];
}
// Deep linking
// Open URI-scheme for iOS 9 and above
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary *) options {
[[AppsFlyerLib shared] handleOpenUrl:url options:options];
return YES;
}
// Open URI-scheme for iOS 8 and below
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString*)sourceApplication annotation:(id)annotation {
[[AppsFlyerLib shared] handleOpenURL:url sourceApplication:sourceApplication withAnnotation:annotation];
return YES;
}
// Open Universal Links
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler {
[[AppsFlyerLib shared] continueUserActivity:userActivity restorationHandler:restorationHandler];
return YES;
}
// Report Push Notification attribution data for re-engagements
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
[[AppsFlyerLib shared] handlePushNotification:userInfo];
}
// AppsFlyerLib implementation
//Handle Conversion Data (Deferred Deep Link)
-(void)onConversionDataSuccess:(NSDictionary*) installData {
id status = [installData objectForKey:@"af_status"];
if([status isEqualToString:@"Non-organic"]) {
id sourceID = [installData objectForKey:@"media_source"];
id campaign = [installData objectForKey:@"campaign"];
NSLog(@"This is a none organic install. Media source: %@ Campaign: %@",sourceID,campaign);
} else if([status isEqualToString:@"Organic"]) {
NSLog(@"This is an organic install.");
}
}
-(void)onConversionDataFail:(NSError *) error {
NSLog(@"%@",error);
}
//Handle Direct Deep Link
- (void) onAppOpenAttribution:(NSDictionary*) attributionData {
NSLog(@"%@",attributionData);
}
- (void) onAppOpenAttributionFailure:(NSError *)error {
NSLog(@"%@",error);
}
@end
import UIKit
import AppsFlyerLib
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
let defaults = UserDefaults.standard
//MARK: LifeCycle
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
AppsFlyerLib.shared().appsFlyerDevKey = "<AF_DEV_KEY>"
AppsFlyerLib.shared().appleAppID = "<APPLE_APP_ID>"
AppsFlyerLib.shared().delegate = self
AppsFlyerLib.shared().isDebug = true
// iOS 10 or later
if #available(iOS 10, *) {
UNUserNotificationCenter.current().requestAuthorization(options: [.badge, .alert, .sound]) { _, _ in }
application.registerForRemoteNotifications()
}
// iOS 9 support - Given for reference. This demo app supports iOS 13 and above
else {
UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.badge, .sound, .alert], categories: nil))
UIApplication.shared.registerForRemoteNotifications()
}
return true
}
func applicationDidBecomeActive(_ application: UIApplication) {
// Start the SDK (start the IDFA timeout set above, for iOS 14 or later)
AppsFlyerLib.shared().start()
}
// Open Univerasal Links
// For Swift version < 4.2 replace function signature with the commented out code:
// func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool {
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
print(" user info \(userInfo)")
AppsFlyerLib.shared().handlePushNotification(userInfo)
}
// Open Deeplinks
// Open URI-scheme for iOS 8 and below
private func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool {
AppsFlyerLib.shared().continue(userActivity, restorationHandler: restorationHandler)
return true
}
// Open URI-scheme for iOS 9 and above
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
AppsFlyerLib.shared().handleOpen(url, sourceApplication: sourceApplication, withAnnotation: annotation)
return true
}
// Report Push Notification attribution data for re-engagements
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
AppsFlyerLib.shared().handleOpen(url, options: options)
return true
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
AppsFlyerLib.shared().handlePushNotification(userInfo)
}
// Reports app open from deep link for iOS 10 or later
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
AppsFlyerLib.shared().continue(userActivity, restorationHandler: nil)
return true
}
}
//MARK: AppsFlyerTrackerDelegate
extension AppDelegate: AppsFlyerLibDelegate{
// Handle Organic/Non-organic installation
func onConversionDataSuccess(_ installData: [AnyHashable: Any]) {
print("onConversionDataSuccess data:")
for (key, value) in installData {
print(key, ":", value)
}
if let status = installData["af_status"] as? String {
if (status == "Non-organic") {
if let sourceID = installData["media_source"],
let campaign = installData["campaign"] {
print("This is a Non-Organic install. Media source: \(sourceID) Campaign: \(campaign)")
}
} else {
print("This is an organic install.")
}
if let is_first_launch = installData["is_first_launch"] as? Bool,
is_first_launch {
print("First Launch")
} else {
print("Not First Launch")
}
}
}
func onConversionDataFail(_ error: Error) {
print(error)
}
//Handle Deep Link
func onAppOpenAttribution(_ attributionData: [AnyHashable : Any]) {
//Handle Deep Link Data
print("onAppOpenAttribution data:")
for (key, value) in attributionData {
print(key, ":",value)
}
}
func onAppOpenAttributionFailure(_ error: Error) {
print(error)
}
}
3.4 Compatibilidad con la atribución de SKAdNetwork
SKAdNetwork es una clase que iOS utiliza y que valida las instalaciones de aplicaciones impulsadas por los anunciantes. El proceso de validación de la instalación de la aplicación involucra a la aplicación fuente y a la aplicación anunciada.
Una aplicación fuente es una aplicación que participa en campañas publicitarias mostrando los anuncios firmados por una red de publicidad. La configuración de tu aplicación para mostrar anuncios no está dentro del alcance del SDK de AppsFlyer. Para configurarla, sigue las instrucciones de Apple.
Para la aplicación anunciada (la aplicación con el SDK de AppsFlyer), la Solución SKAdNetwork de AppsFlyer utiliza SKAdNetwork para proporcionar el postback de atribución mientras AppsFlyer recopila, traduce y agrega los datos, manteniendo la privacidad del usuario. Al iniciar la aplicación por primera vez, la plataforma AppsFlyer, utilizando la configuración establecida por el marketer, instruye al SDK sobre cómo establecer el valor de conversión de SKAdNetwork.
Para usar la Solución SKAdNetwork:
- El desarrollador no hace nada.
-
El SDK de AppsFlyer llama automáticamente a las API necesarias de SKAdNetwork, es decir,
registerAppForAdNetworkAttribution()
yupdateConversionValue()
. El desarrollador no debe llamarlas. - No permitas que otros SDK llamen a las API de SKAdNet. Si esto ocurre, es posible que se retrase el envío del postback por parte de iOS a AppsFlyer y que cambie el valor de conversión que usamos para calcular las métricas de calidad del usuario del panel de control de SKAdNetwork.
- El marketer debe configurar la medición de SKAdNetwork en AppsFlyer.
No se requiere ninguna acción o proceso de registro en la tienda de aplicaciones por parte del desarrollador o del marketer.
3.4 Compatibilidad con delegados de escena
Para admitir enlaces profundos, lo cual comienza con la dirección de los usuarios a la escena predeterminada de la aplicación, agrega el siguiente código a SceneDelegate para la escena predeterminada a la que quieres que los usuarios establezcan un enlace profundo.
1. Importar la biblioteca
En SceneDelegate.h, importa AppsFlyerLib/AppsFlyerLib.h
:
#import <AppsFlyerLib/AppsFlyerLib.h>
En SceneDelegate.swift, importa AppsFlyerLib
:
import AppsFlyerLib
2. Agregar la implementación
#import "SceneDelegate.h"
@interface SceneDelegate ()
@end
@implementation SceneDelegate
- (void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts API_AVAILABLE(ios(13.0)){
NSURL* url = [[URLContexts allObjects] objectAtIndex:0].URL;
if(url){
[[AppsFlyerLib shared] handleOpenUrl:url options:nil];
}
}
- (void)scene:(UIScene *)scene continueUserActivity:(NSUserActivity *)userActivity API_AVAILABLE(ios(13.0)){
[[AppsFlyerLib shared]continueUserActivity:userActivity restorationHandler:nil];
}
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
NSUserActivity *activity = [[connectionOptions userActivities] allObjects].firstObject;
if (activity) {
[self scene:scene continueUserActivity:activity];
}
[self scene:scene openURLContexts: [connectionOptions URLContexts]];
}
- (void)sceneDidDisconnect:(UIScene *)scene API_AVAILABLE(ios(13.0)){
// Called as the scene is being released by the system.
// This occurs shortly after the scene enters the background, or when its session is discarded.
// Release any resources associated with this scene that can be re-created the next time the scene connects.
// The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
}
- (void)sceneDidBecomeActive:(UIScene *)scene API_AVAILABLE(ios(13.0)){
// Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}
- (void)sceneWillResignActive:(UIScene *)scene API_AVAILABLE(ios(13.0)){
// Called when the scene will move from an active state to an inactive state.
// This may occur due to temporary interruptions (ex. an incoming phone call).
}
- (void)sceneWillEnterForeground:(UIScene *)scene API_AVAILABLE(ios(13.0)){
// Called as the scene transitions from the background to the foreground.
// Use this method to undo the changes made on entering the background.
}
- (void)sceneDidEnterBackground:(UIScene *)scene API_AVAILABLE(ios(13.0)){
// Called as the scene transitions from the foreground to the background.
// Use this method to save data, release shared resources, and store enough scene-specific state information
// to restore the scene back to its current state.
}
@end
import UIKit
import AppsFlyerLib
@available(iOS 13.0, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Processing Universal Link from the killed state
if let userActivity = connectionOptions.userActivities.first {
self.scene(scene, continue: userActivity)
}
// Processing URI-scheme from the killed state
self.scene(scene, openURLContexts: connectionOptions.urlContexts)
guard let _ = (scene as? UIWindowScene) else { return }
}
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
AppsFlyerLib.shared().continue(userActivity, restorationHandler: nil)
}
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
if let url = URLContexts.first?.url {
AppsFlyerLib.shared().handleOpen(url, options: nil)
}
}
func sceneDidDisconnect(_ scene: UIScene) {
// Called as the scene is being released by the system.
// This occurs shortly after the scene enters the background, or when its session is discarded.
// Release any resources associated with this scene that can be re-created the next time the scene connects.
// The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
}
func sceneDidBecomeActive(_ scene: UIScene) {
// Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}
func sceneWillResignActive(_ scene: UIScene) {
// Called when the scene will move from an active state to an inactive state.
// This may occur due to temporary interruptions (ex. an incoming phone call).
}
func sceneWillEnterForeground(_ scene: UIScene) {
// Called as the scene transitions from the background to the foreground.
// Use this method to undo the changes made on entering the background.
}
func sceneDidEnterBackground(_ scene: UIScene) {
// Called as the scene transitions from the foreground to the background.
// Use this method to save data, release shared resources, and store enough scene-specific state information
// to restore the scene back to its current state.
}
}
3.7 Retraso en la inicialización del SDK
Es posible que desees retrasar la inicialización del SDK y el envío de datos hasta que el usuario lo autorice (por ejemplo, el consentimiento del RGPD y la CCPA).
Nota: Esto no está relacionado con la incorporación de ATT en iOS 14.
Para retrasar la inicialización del SDK:
- Evita que la sesión se envíe en transición de fondo a primer plano. En un método sendLaunch() que se llama en cada applicationDidBecomeActive (como en la sección 3.3), encapsula la llamada en
start
con una comprobación de la condición. Por ejemplo:
-(void)sendLaunch:(UIApplication *)application { if (consent_given) { // check the condition [[AppsFlyerLib shared] start]; // Start } }
-
Envía la sesión tan pronto como el motivo de la demora ya no sea relevante (justo después de que cambie la condición). Llama a
start
cuando estés listo para enviar los datos de la primera sesión. Por ejemplo:
... consent_given = YES; // change the condition [[AppsFlyerLib shared] start]; // Start ...
4. Cómo probar instalaciones
Ahora estás listo para probar la integración del SDK mediante la simulación de instalaciones orgánicas y no orgánicas.
4.1 Agregar tu dispositivo de prueba a la lista de permitidos
Antes de empezar a probar las instalaciones:
- Asegúrate de que tu dispositivo no tenga la aplicación instalada.
- Permite la inclusión del dispositivo que vas a probar.
4.2 Cómo simular una instalación orgánica
Las instalaciones orgánicas son instalaciones sin atribuir que, por lo general, son instalaciones directas desde tiendas de aplicaciones.
Para simular una instalación orgánica
- Asegúrate de tener un dispositivo móvil conectado a tu computadora.
- En Xcode, abre la terminal de depuración.
- Desde Xcode Studio, instala la aplicación en el dispositivo o emulador.
- Espera a que se inicie la aplicación.
- En la terminal de depuración, busca el nombre del paquete de la aplicación.
Deberías ver lo siguiente:
Enviar start() en el registro indica que el SDK informa una instalación. Estos datos provienen del método onConversionDataSuccess
en el delegado de aplicación. Más adelante en esta guía, se explica cómo obtener datos de conversión.
Nota: A partir del SDK V5, onConversionDataSuccess
es el nombre del método para obtener datos de conversión. Si estás utilizando una versión del SDK inferior a 5.0.0, el nombre del método es onConversionDataReceived
. Recomendamos que actualices al SDK 5.0.0. Para aprender más, haz clic aquí.
Ahora debería aparecer una instalación orgánica en la página de Información general del panel de control de la aplicación.
Si no ves ninguna instalación en el panel de control de la aplicación, consulta la guía de resolución de problemas del SDK.
4.3 Cómo simular una instalación no orgánica
Una instalación no orgánica es una instalación atribuida que, por lo general, tiene lugar después de una instancia de captación (engagement) de un anuncio. Para simular una instalación no orgánica, puedes usar enlaces de atribución.
Para hacer esto:
- Averigua cuál es el nombre de ID de iTunes de tu aplicación, por ejemplo id123456789.
- En la siguiente URL, reemplaza <APP_ID> por el ID de itunes de tu aplicación:
El parámetrohttps://app.appsflyer.com/<APP_ID>?pid=sdk_test&c=sdk_test
pid
representa el nombre de la fuente de medios. El parámetroc
representa el nombre de la campaña. - Envía esta URL al dispositivo (p. ej., por correo electrónico o WhatsApp).
- En el dispositivo, haz clic en la URL.
- Si la aplicación figura en la tienda de aplicaciones, se te redirigirá a la tienda de aplicaciones. No descargues la aplicación desde la tienda de aplicaciones. Sigue con el paso 5.
- Si la aplicación no figura en la tienda de aplicaciones y aún se encuentra en desarrollo, la pantalla muestra un mensaje de que la aplicación no se encuentra disponible en la tienda de aplicaciones. Simplemente sigue con el paso 5.
- En Xcode Studio, abre la terminal de depuración.
- Conecta el dispositivo a tu computadora con un cable USB.
- Desde Xcode, instala la aplicación en el dispositivo.
- En la terminal de depuración, busca el ID de iTunes de tu aplicación.
Deberías ver lo siguiente:
Ahora debería aparecer una instalación no orgánica en la página de Información general del panel de control de la aplicación.
Nota
Cuando hayas terminado de probar y depurar la integración de SDK, desactiva los registros del SDK.
En esta pestaña te explicamos cómo registrar eventos in-app e ingresos y cómo configurar enlaces profundos.
Al registrar eventos in-app e ingresos, podrás medir la calidad de tus usuarios. Los enlaces profundos te permiten ofrecerles a los usuarios una mejor experiencia.
Esta pestaña contiene instrucciones para desarrolladores, pero el aporte del marketer o vendedor es esencial porque:
- El marketer debe decidir cuáles eventos in-app es necesario registrar para medir la calidad de los usuarios.
- El marketer tiene acceso al panel de control de AppsFlyer, que es necesario para configurar OneLink para enlaces profundos.
5. Cómo atribuir eventos in-app
Los eventos in-app brindan información sobre lo que está sucediendo en tu aplicación. Te recomendamos que te tomes un tiempo para definir los eventos que deseas registrar. El registro de eventos in-app te ayuda a medir indicadores clave de rendimiento (KPI) como el retorno de la inversión (ROI) y el valor de vida útil (LTV).
Existen varias maneras de registrar eventos in-app. La forma más común consiste en enviar eventos a través del SDK, algo que analizamos en este artículo. Para conocer otras maneras de registrar eventos in-app, consulta nuestra guía general sobre eventos in-app.
Si tu aplicación pertenece a un segmento vertical determinado, p. ej., viajes, juegos, comercio electrónico, etc., puedes usar la lista completa de eventos in-app recomendados por segmento vertical.
5.1 Parámetros y nombres de eventos in-app
El SDK contiene dos tipos de constantes que representan información relacionada con eventos in-app.
- Nombres de eventos: estas constantes tienen el formato
AFEventEventName
.
Por ejemploAFEventPurchase
,AFEventAddToCart
. - Parámetros de eventos: estas constantes tienen el formato
AFEventParameterParameterName
.
Por ejemploAFEventParameterRevenue
,AFEventParamaterContentId
.
Es muy recomendable que uses estas constantes por los siguientes motivos:
- La nomenclatura estándar permite que AppsFlyer asigne automáticamente eventos a redes de autorreporte (SRN) como Facebook, Google, Twitter y Snapchat.
- Compatibilidad con versiones anteriores: si AppsFlyer decide cambiar el nombre de cualquier evento o parámetro de evento, tu implementación será compatible con las versiones anteriores.
Para usar estas dos interfaces, importa AppsFlyerLib.h si usas Objective-C, o AppsFlyerLib si usas Swift:
Pon esto en el archivo de implementación de clase.
#import AppsFlyerLib.h
Pon esto en el archivo de clase Swift.
import AppsFlyerLib
Aquí encontrarás la lista de estructuras y nombres de eventos recomendados.
5.2 Cómo registrar los ingresos
Puedes enviar los ingresos con cualquier evento in-app. Usa el parámetro del evento af_revenue
(AFEventParameterRevenue
) para incluir los ingresos en el evento in-app. Puedes rellenarlo con cualquier valor numérico, positivo o negativo.
af_revenue
es el único parámetro de evento que AppsFlyer cuenta como ingreso real en los raw data (datos sin procesar) y en el panel de control. Para más detalles, haz clic aquí.
Cuando envíes eventos con ingresos, ten en cuenta lo siguiente:
- Si estableces el código de divisa (mira el ejemplo a continuación), debe ser un código ISO 4217 de 3 caracteres (la opción predeterminada es USD).
- Puedes establecer el código de divisa para todos los eventos configurando la siguiente propiedad:
- Objective-C:
[AppsFlyerLib shared].currencyCode = @"ZZZ";
, - Swift:
AppsFlyerLib.shared().currencyCode = "ZZZ"
- Objective-C:
- El valor de los ingresos no debe contener comas separadoras, signos de divisas ni texto. Por ejemplo, un evento generador de ingresos debería ser similar a 1234.56.
Ejemplo: evento de compra in-app con ingresos
[[AppsFlyerLib shared] logEvent: @"purchase"
withValues:@{
AFEventParamContentId:@"1234567",
AFEventParamContentType : @"category_a",
AFEventParamRevenue: @200,
AFEventParamCurrency:@"USD"
}];
AppsFlyerLib.shared().logEvent("purchase",
withValues: [
AFEventParamContentId:"1234567",
AFEventParamContentType : "category_a",
AFEventParamRevenue: 200,
AFEventParamCurrency:"USD"
]);
El evento de compra anterior contiene un ingreso de $200 que aparece como ingreso en el panel de control.
Registro de ingresos negativos
Puede haber situaciones en las que quieras registrar ingresos negativos.
Ejemplo: un usuario recibe un reembolso o cancela una suscripción.
[[AppsFlyerLib shared] logEvent: @"cancel_purchase"
withValues:@{
AFEventParamContentId:@"1234567",
AFEventParamContentType : @"category_a",
AFEventParamRevenue: @-1.99,
AFEventParamCurrency:@"USD"
}];
AppsFlyerLib.shared().logEvent("cancel_purchase",
withValues: [
AFEventParamContentId:"1234567",
AFEventParamContentType : "category_a",
AFEventParamRevenue: -1.99,
AFEventParamCurrency:"USD"
]);
Nota
Observe lo siguiente en el código anterior:
- El valor de ingresos está precedido por un signo de menos
- El nombre del evento tiene un valor único de "cancel_purchase" para permitirle identificar los eventos con ingresos negativos en el panel de control y en los informes de datos sin procesar.
5.3 Validación de compras in-app
El SDK de AppsFlyer proporciona verificación de servidor para las compras in-app. Para validar una compra, llama a validateAndLogInAppPurchase
.
Esta llamada genera automáticamente un evento in-app de tipo af_purchase
, dado que la compra está validada.
Esta llamada tiene dos bloques de callback: uno para "éxito" y otro para "falla" (por cualquier motivo, incluyendo falla de validación). Tras un éxito, se devuelve un diccionario con los datos de validación de compra (receipt validation).
Ejemplo de uso de la validación de compra:
- (void) validateAndLogInAppPurchase:(NSString *) productIdentifier
price:(NSString *) price
currency:(NSString *) currency
transactionId:(NSString *) tranactionId
additionalParameters:(NSDictionary *) params
success:(void (^)(NSDictionary *response)) successBlock
failure:(void (^)(NSError *error, id reponse)) failedBlock;
[[AppsFlyerLib shared] validateAndLogInAppPurchase:@"ProductIdentifier" price:@"price"
currency:@"USD"
transactionId:@"transactionID"
additionalParameters:@{@"test": @"val" , @"test1" : @"val 1"}
success:^(NSDictionary *result){
NSLog(@"Purchase succeeded And verified!!! response: %@", result[@"receipt"]);
} failure:^(NSError *error, id response) {
NSLog(@"response = %@", response);
if([response isKindOfClass:[NSDictionary class]]) {
if([response[@"status"] isEqualToString:@"in_app_arr_empty"]){
// retry with 'SKReceiptRefreshRequest' because
// Apple has returned an empty response
// <YOUR CODE HERE>
}
} else {
//handle other errors
return;
}
}];
AppsFlyerLib
.shared()?
.validateAndLogInAppPurchase ("productIdentifier",
price: "price",
currency: "currency",
transactionId: "transactionId",
additionalParameters: [:],
success: {
guard let dictionary = $0 as? [String:Any] else { return }
dump(dictionary)
}, failure: { error, result in
guard let emptyInApp = result as? [String:Any],
let status = emptyInApp["status"] as? String,
status == "in_app_arr_empty" else {
// Try to handle other errors
return
}
// retry with 'SKReceiptRefreshRequest' because
// Apple has returned an empty response
// <YOUR CODE HERE>
})
[AppsFlyerLib shared].useReceiptValidationSandbox = YES;
AppsFlyerLib.shared().useReceiptValidationSandbox = true
Al validar una compra in-app, se envía automáticamente un evento de compra in-app a AppsFlyer. Mira a continuación una muestra de los datos que se pasan en el parámetro event_value:
{
"some_parameter":"some_value", // from additional_event_values
"af_currency":"USD", // from currency
"af_content_id":"test_id", // from purchase
"af_revenue":"10", // from revenue
"af_quantity":"1", // from purchase
"af_validated":true // flag that AF verified the purchase
}
Nota
Una llamada a validateAndTrackInAppPurchase
genera automáticamente un evento in-app af_purchase. Si envías este evento tú mismo, se crea un reporte de evento duplicado.
5.4 Limitaciones de los eventos in-app
- Nombre del evento: hasta 45 caracteres
- Valor del evento: no debe superar los 1000 caracteres; si es más largo, es probable que lo trunquemos.
- Precios e ingresos: usa solo dígitos y decimales, p. ej. 5 o 5.2.
- Los valores de precios e ingresos pueden tener hasta 5 dígitos después del punto, p. ej., 5.12345
- Se admiten caracteres no ingleses, en eventos in-app, otras API de SDK, a partir de Android SDK V4.8.1.
5.5 Ejemplos para registrar eventos in-app
Puedes registrar eventos in-app al llamar a trackEvent
con el nombre de evento y los parámetros de valor. Consulta la documentación sobre eventos in-app para conocer más detalles.
A continuación, te mostramos un ejemplo de cómo registrar un evento de compra. Para ver una lista completa de fragmentos de código listos por segmento vertical, consulta nuestra guía de eventos in-app enriquecidos por segmento vertical.
Ejemplo: evento de compra in-app
[[AppsFlyerLib shared] logEvent:AFEventPurchase
withValues: @{
AFEventParamRevenue: @200,
AFEventParamCurrency: @"USD",
AFEventParamQuantity: @2,
AFEventParamContentId: @"092",
AFEventParamReceiptId: @"9277"
}];
Nota
- El valor de evento Dictionary que se envió al SDK debe ser válido para la conversión JSON de NSJSONSerialization. Para más información, consulta aquí.
- Para los ingresos, no agregues ningún símbolo de moneda, ya que no se reconocen.
AppsFlyerLib.shared().logEvent(AFEventPurchase,
withValues: [
AFEventParamRevenue: "200",
AFEventParamCurrency: "USD",
AFEventParamQuantity: 2,
AFEventParamContent: "shoes",
AFEventParamContentId: "092",
AFEventParamReceiptId: "9277"]);
5.6 Cómo registrar eventos in-app sin conexión
Si un usuario inicia un evento cuando no tiene conexión a Internet, AppsFlyer igualmente podrá registrarlo. Así es como funciona:
- El SDK envía los eventos a los servidores de AppsFlyer y espera una respuesta.
- Si el SDK no recibe una respuesta 200, el evento se almacena en el caché.
- Una vez recibida la respuesta 200, el evento almacenado se vuelve a enviar al servidor.
- Si hay múltiples eventos en el caché, se envían al servidor uno tras otro.
Nota
El caché del SDK puede almacenar hasta 40 eventos, lo que significa que solo se guardarán los primeros 40 eventos que se den sin conexión. Todo lo que suceda después se descartará, hasta la próxima respuesta 200.
La hora del evento que aparece en el raw data es la hora en que se envía el evento a AppsFlyer después de que el dispositivo vuelve a tener conexión. No es la hora en que ocurrió el evento.
5.7 Manejar el éxito y el fracaso al atribuir eventos in-app
- Evento in-app registrado con éxito.
- Error en el registro del evento in-app.
[[AppsFlyerLib shared] logEventWithEventName:AFEventPurchase
eventValues: @{
AFEventParamRevenue: @200,
AFEventParamCurrency: @"USD",
AFEventParamQuantity: @2,
AFEventParamContentId: @"092",
AFEventParamReceiptId: @"9277"
}
completionHandler:^(NSDictionary<NSString *,id> * _Nullable dictionary, NSError * _Nullable error){
if(dictionary != nil) {
NSLog(@"In app callback success:");
for(id key in dictionary){
NSLog(@"Callback response: key=%@ value=%@", key, [dictionary objectForKey:key]);
}
}
if(error != nil) {
NSLog(@"In app callback error:", error);
}
}];
AppsFlyerLib.shared().logEvent(name: "In app event name", values: ["id": 12345, "name": "John doe"], completionHandler: { (response: [String : Any]?, error: Error?) in
if let response = response {
print("In app event callback Success: ", response)
}
if let error = error {
print("In app event callback ERROR:", error)
}
})
}
En caso de que se produzca un error durante la grabación del evento in-app, se proporciona un código de error y una descripción de la cadena, como se indica en la tabla que figura a continuación.
Código del error | Descripción de la cadena |
---|---|
10 |
"Event timeout. Check 'minTimeBetweenSessions' param" ("Tiempo de espera del evento agotado. Comprueba el parámetro 'minTimeBetweenSessions'") |
11 |
"Skipping event because 'isStopTracking' enabled" ("Se omite el evento porque 'isStopTracking' está activado") |
40 |
Network error: Error description comes from Android (Error de red: la descripción del error viene de Android) |
41 |
"No dev key" ("No hay clave de desarrollador") |
50 |
"Status code failure" + actual response code from the server ("Fallo del código de estado" + código de respuesta real del servidor) |
6. Enlaces profundos con OneLink
OneLink es la solución de AppsFlyer para la dirección, los enlaces profundos y la atribución multiplataforma.
6.1 Detección y redireccionamiento de dispositivos
OneLink detecta el tipo de dispositivo al hacer clic y redirige al usuario al destino correspondiente, p. ej., Google Play, tienda de aplicaciones iOS, mercados fuera de la tienda o páginas web.
En la guía sobre redireccionamiento de OneLink, analizamos la implementación de enlaces de atribución multiplataforma (sin necesidad de codificación del SDK). También es la base para los enlaces profundos.
6.2 Enlaces profundos
Los enlaces profundos te permiten enviar a usuarios hacia actividades específicas y ofrecerles contenido personalizado. Esto resulta particularmente útil cuando se ejecutan campañas de retargeting.
Para configurar enlaces profundos con OneLink, un marketer con acceso al panel de control de AppsFlyer y un desarrollador con acceso a la aplicación deben trabajar juntos.
Consulta nuestra guía sobre configuración de enlaces profundos con OneLink.
6.3 Enlaces profundos diferidos
Los enlaces profundos diferidos te permiten establecer enlaces profundos con usuarios nuevos y ofrecerles contenido personalizado después de que inician la aplicación por primera vez. Esto es diferente con respecto a los enlaces profundos normales, en los que la aplicación ya debe estar instalada en el dispositivo del usuario.
Para configurar enlaces profundos diferidos con OneLink, el desarrollador también necesita acceso al panel de control de AppsFlyer.
La configuración de enlaces profundos diferidos es prácticamente igual a la de los enlaces profundos regulares. La única diferencia es que necesitas implementar una lógica adicional en la aplicación a fin de establecer enlaces profundos con los usuarios y ofrecerles contenido personalizado después de que instalen e inicien la aplicación.
Consulta nuestra guía sobre enlaces profundos diferidos para aprender más.
6.4 Cómo obtener datos de enlaces profundos
El SDK te proporciona los datos de conversión o captación (engagement) después de cada instalación o evento de enlaces profundos. Puedes usar estos datos para personalizar el contenido y el comportamiento de la aplicación de manera programática.
Para obtener datos de enlaces profundos cuando se usa el enlace profundo directo y se abre la aplicación, implementa el método onAppOpenAttribution.
Para obtener datos de re-engagement de enlaces profundos manualmente en cualquier momento, implementa el método performOnAppAttribution. Esto permite el acceso a los datos de re-engagement sin registrar un re-engagement nuevo.
Consulta nuestra guía sobre datos de enlaces profundos para aprender más.
7. Obtener Datos de Conversión
Obtener datos de conversión
Puedes acceder a los datos de atribución de los usuarios en tiempo real para cada instalación nueva, directamente desde el SDK.
Al hacer esto, puedes ofrecerles a los usuarios contenido personalizado o enviarlos a actividades específicas dentro de la aplicación (consulta la sección sobre enlaces profundos diferidos de este artículo), lo que puede optimizar en gran medida su interacción (engagement) con tu aplicación.
Para obtener los datos de conversión del SDK para iOS, implementa los siguientes métodos:
- (void) onAppOpenAttribution:(NSDictionary*) attributionData {
NSLog(@"onAppOpenAttribution");
for(id key in attributionData){
NSLog(@"onAppOpenAttribution: key=%@ value=%@", key, [attributionData objectForKey:key]);
}
}
- (void)onAppOpenAttributionFailure:(NSError *)error {
NSLog(@"%@", [error description]);
}
-(void)onConversionDataSuccess:(NSDictionary*) installData {
BOOL first_launch_flag = [[installData objectForKey:@"is_first_launch"] boolValue];
NSString *status = [installData objectForKey:@"af_status"];
if(first_launch_flag) {
if ([status isEqualToString:@"Non-organic"]){
NSString *sourceID = [installData objectForKey:@"media_source"];
NSString *campaign = [installData objectForKey:@"campaign"];
NSLog(@"This is a non-organic install. Media source: %@ Campaign: %@", sourceID, campaign);
} else {
NSLog(@"This is an organic install");
}
} else {
NSLog(@"Not first launch");
}
}
-(void)onConversionDataFail:(NSError *) error {
NSLog(@"%@", [error description]);
}
class AppDelegate: UIResponder, UIApplicationDelegate, AppsFlyerLibDelegate{
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
AppsFlyerLib.shared().appsFlyerDevKey = "MY_DEV_KEY"
AppsFlyerLib.shared().appleAppID = "123456789"
AppsFlyerLib.shared().delegate = self
//AppsFlyerLib.shared().isDebug = true
//AppsFlyerLib.shared().appInviteOneLinkID = "ONELINK_ID";
return true
}
func applicationDidBecomeActive(_ application: UIApplication) {
AppsFlyerLib.shared().start()
}
func onConversionDataSuccess(_ installData: [AnyHashable: Any]) {
guard let first_launch_flag = installData["is_first_launch"] as? Int else {
return
}
guard let status = installData["af_status"] as? String else {
return
}
if(first_launch_flag == 1) {
if(status == "Non-organic") {
if let media_source = installData["media_source"] , let campaign = installData["campaign"]{
print("This is a Non-Organic install. Media source: \(media_source) Campaign: \(campaign)")
}
} else {
print("This is an organic install.")
}
} else {
print("Not First Launch")
}
}
func onConversionDataFail(_ error: Error!) {
if let err = error{
print(err)
}
}
func onAppOpenAttribution(_ attributionData: [AnyHashable : Any]!) {
if let data = attributionData{
print("\(data)")
}
}
func onAppOpenAttributionFailure(_ error: Error!) {
if let err = error{
print(err)
}
}
Los dos métodos más importantes son lo siguientes:
-
onInstallConversionData
: proporciona datos de conversión para instalaciones nuevas.
Nota: A partir del SDK V5,
onConversionDataSuccess
es el nombre del método para obtener datos de conversión. Si estás utilizando una versión del SDK inferior a 5.0.0, el nombre del método esonConversionDataReceived
. Recomendamos que actualices al SDK 5.0.0. Para aprender más, haz clic aquí. -
onAppOpenAttribution
: proporciona datos de conversión de retargeting cuando se inicia una aplicación existente, ya sea manualmente o a través de enlaces profundos.
Por más información sobre los datos de conversión, consulta nuestra guía sobre escenarios de datos de conversión.
8. Atribución
Medición de desinstalaciones
Para saber cómo configurar la medición de desinstalaciones, lee aquí.
Configurar un controlador de inicio de SDK
Si quieres recibir una confirmación de que el SDK comenzó satisfactoriamente y notificó a los servidores de AppsFlyer, implementa el controlador startWithCompletionHandler
. Puedes aplicar una lógica para manejar el éxito o el fracaso del inicio del SDK.
Ejemplo de implementación
[[AppsFlyerLib shared] startWithCompletionHandler:^(NSDictionary<NSString *,id> *dictionary, NSError *error) {
if (error) {
NSLog(@"%@", error);
return;
}
if (dictionary) {
NSLog(@"%@", dictionary);
return;
}
}];
AppsFlyerLib.shared()?.start(completionHandler: { (dictionnary, error) in
if (error != nil){
print(error ?? "")
return
} else {
print(dictionnary ?? "")
return
}
})
En caso de que se produzca un error durante la escucha de la solicitud, se proporciona un código de error y una descripción de la cadena, como se indica en la tabla que figura a continuación.
Código del error | Descripción de la cadena |
---|---|
10 |
"Event timeout. Check 'minTimeBetweenSessions' param" ("Tiempo de espera del evento agotado. Comprueba el parámetro 'minTimeBetweenSessions'") |
11 |
"Skipping event because 'isStopTracking' enabled" ("Se omite el evento porque 'isStopTracking' está activado") |
40 |
Network error: Error description comes from Android (Error de red: la descripción del error viene de Android) |
41 |
"No dev key" ("No hay clave de desarrollador") |
50 |
"Status code failure" + actual response code from the server ("Fallo del código de estado" + código de respuesta real del servidor) |
Configuración de datos personalizados adicionales
La API setAdditionalData
es necesaria para integrarse a nivel del SDK con varias plataformas de partners externos, como Segment, Adobe y Urban Airship.
Usa esta API solo si el artículo de integración de la plataforma indica específicamente que se necesita la API setAdditionalData
.
Ejemplo de código de setAdditionalData
:
NSDictionary* CustomDataMap = [[NSDictionary alloc] initWithObjectsAndKeys:@"value_of_param_1", @"custom_param_1", nil];
[[AppsFlyerLib shared] setAdditionalData:CustomDataMap];
let CustomDataMap: [AnyHashable: Any] = [
"custom_param_1" : "value_of_param_1"
]
AppsFlyerLib.shared().customData = CustomDataMap
9. Sesiones
Tiempo Personalizado Entre Sesiones
De manera predeterminada, deben pasar por lo menos 5 segundos entre 2 instancias de inicio de la aplicación para que cuenten como 2 sesiones separadas (más información acerca del recuento de sesiones).
Usa la siguiente API para establecer el tiempo mínimo entre sesiones:
[AppsFlyerLib shared].minTimeBetweenSessions = <your_custom_time_in_seconds>;
AppsFlyerLib.shared().minTimeBetweenSessions = <your_custom_time_in_seconds>
Establecer un valor alto para el tiempo personalizado entre inicios podría afectar negativamente las API que dependen de los datos de sesión, como los enlaces profundos.
Sesiones de segundo plano para aplicaciones de utilidad
No disponible en iOS.
10. Medios propios
Resolución de URL encapsuladas de enlaces profundos
Algunos servicios de terceros, como los proveedores de servicio de correo electrónico encapsulan enlaces en los mensajes de correo electrónico con sus propios dominios de registro de clics. Algunos incluso te permiten configurar tus propios dominios de registro de clics. Si OneLink está encapsulado en tales dominios, su funcionalidad podría verse limitada.
Para resolver este problema, puedes usar la API setResolveDeepLinkURLs
. Usa esta API para obtener el OneLink de los dominios de clics que inician la aplicación. Asegúrate de llamar a esta API antes de la inicialización del SDK.
Por ejemplo, tienes tres dominios de clics que redirigen a tu OneLink, que es https://mysubdomain.onelink.me/abCD. Usa esta API para obtener el OneLink al cual redirigen tus dominios de clics. Este método de API recibe una lista de dominios que el SDK resolverá.
[AppsFlyerLib shared].resolveDeepLinkURLs = @[@"example.com",@"click.example.com"];
AppsFlyerLib.shared().resolveDeepLinkURLs = ["example.com", "click.example.com"]
El código anterior te permite usar tu dominio de clics y, al mismo tiempo, preservar la funcionalidad del OneLink. Los dominios de clics son responsables de iniciar la aplicación. A su vez, la API obtiene el OneLink de estos dominios de clics y, a continuación, tú puedes usar los datos de este OneLink para establecer enlaces profundos y personalizar el contenido de los usuarios.
Atribución de notificaciones push
Con AppsFlyer, puedes medir notificaciones push como parte de las campañas de retargeting.
Para habilitar esta función, llama al método handlePushNotificationData
dentro de AppDelegate.m.
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
[[AppsFlyerLib shared] handlePushNotification:userInfo];
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
AppsFlyerLib.shared().handlePushNotification(userInfo)
}
Para obtener más información sobre la medición de notificaciones push, lee aquí.
Atribución de invitaciones de usuarios
Permitir que tus usuarios actuales inviten a sus amigos y contactos como nuevos usuarios de tu aplicación puede ser un factor de crecimiento clave para tu aplicación. Con AppsFlyer, puedes atribuir y registrar instalaciones que se originen a partir de invitaciones de usuarios dentro de tu aplicación.
Para conocer más detalles, consulta el artículo sobre atribución de invitaciones de usuarios.
Atribución de la promoción cruzada
AppsFlyer te permite registrar y atribuir instalaciones originadas en una promoción cruzada de una de tus aplicaciones dentro de la aplicación actual que tiene el usuario. Para conocer más detalles, consulta el artículo sobre atribución de promociones cruzadas aquí.
11. Identificadores de usuarios
Obtención del ID de AppsFlyer
Un ID de dispositivo exclusivo de AppsFlyer se crea para cada instalación nueva de una aplicación. Puedes usar este ID con diversos fines:
- Enviar eventos in-app de servidor a servidor.
- Vincúlala con los registros de usuarios en tus sistemas de backend.
- Asignar entradas cuando se fusionan datos de las API de extracción y envío (Pull/Push API).
Usa la siguiente API para obtener el ID único de AppsFlyer:
NSString *appsflyerId = [AppsFlyerLib shared].getAppsFlyerUID;
let appsflyerId = AppsFlyerLib.shared().getAppsFlyerUID()
Establecer ID de Usuario de Cliente
Para configurar tu ID de usuario de cliente:
[AppsFlyerLib shared].customerUserID = @"my user id";
AppsFlyerLib.shared().customerUserID = "my user id"
En iOS, el ID de usuario de cliente debe configurarse con cada inicio de la aplicación. Te recomendamos configurar el ID de usuario de cliente lo antes posible en el flujo de tu aplicación, ya que solo se asocia con los eventos reportados después de su configuración:
- Si se llama a
setCustomerUserId
antes de llamar astart
, el ID de usuario de cliente aparece en los reportes de raw data de instalaciones y eventos. - Si se configura después, el ID de usuario de cliente se asocia solo con eventos registrados después de configurar dicho ID.
Cómo obtener un ID de usuario de cliente:
Para evitar configurar el valor del ID de usuario de cliente nuevamente después del primer inicio, y reducir las llamadas a tu servidor para obtener el ID de usuario de cliente, puedes verificar si su valor está vacío, o no, de la siguiente forma:
NSString *customerUserID = [AppsFlyerLib shared].customerUserID;
let customerUserID = AppsFlyerLib.shared().customerUserID
Para obtener más información sobre el ID de usuario de cliente, haz clic aquí.
Retrasar la inicialización del SDK para customerUserID
Puedes retrasar la inicialización del SDK hasta que se configure el ID de usuario de cliente. Esto es útil si deseas que los datos de instalación y eventos contengan tu ID de usuario de cliente.
Implementa el siguiente código:
- (void)applicationDidBecomeActive:(UIApplication *)application {
NSString *customUserId = [[NSUserDefaults standardUserDefaults] stringForKey:@"customerUserId"]; // Your custom logic of retrieving CUID
if (customUserId != nil && ![customUserId isEqual: @""]) {
[AppsFlyerLib shared].customerUserID = customUserId; // Set CUID in AppsFlyer SDK for this session
[[AppsFlyerLib shared] start]; // Start
}
}
func applicationDidBecomeActive(_ application: UIApplication) {
let customUserId = UserDefaults.standard.string(forKey: "customUserId") // your logic to retrieve CUID
if(customUserId != nil && customUserId != ""){
AppsFlyerLib.shared().customerUserID = customUserId // Set CUID in AppsFlyer SDK for this session
AppsFlyerLib.shared().start() // Start
}
}
Para aprender más acerca de cómo retrasar la inicialización del SDK hasta que esté disponible el ID de usuario de cliente, ve aquí.
Advertencia
Utiliza esta API solo cuando sea adecuado para tu lógica de negocios. El uso de esta API aumenta las probabilidades de discrepancias y podría hacer que la aplicación quede más expuesta a fraudes.
12. Privacidad de los usuarios
Optar por la exclusión
En algunos casos extremos, tal vez necesites desactivar todo el registro de datos del SDK para cumplir con la ley y las políticas de privacidad. Puedes hacer esto con la propiedad isStopped. Una vez que esta propiedad se configura como verdadera, el SDK deja de funcionar y ya no se comunica con los servidores de AppsFlyer.
Existen varios casos para que un usuario opte por la exclusión. Es muy recomendable que sigas las instrucciones exactas para la situación correspondiente a tu aplicación.
Advertencia
Usa la API isStopped solo en los casos que quieras ignorar por completo a este usuario de todo registro. La utilización de esta API afecta GRAVEMENTE tus mecanismos de atribución, recopilación de datos y establecimiento de enlaces profundos.
[AppsFlyerLib shared].isStopped = true;
AppsFlyerLib.shared().isStopped = true
En cualquier evento, se puede reactivar el SDK llamando a la misma API y pasando un valor falso.
¡Importante!
No llames a start
si isStopped
está configurado como true
(verdadero).
Para empezar a registrar los datos de nuevo, configura isStopped
como false
(falso).
Anonimizar Datos de Usuarios
Usa esta API durante la Inicialización del SDK para anonimizar explícitamente las instalaciones, los eventos y las sesiones de un usuario:
[AppsFlyer shared].disableAdvertisingIdentifier = YES;
AppsFlyerLib.shared().disableAdvertisingIdentifier = true
Para reiniciar el registro de datos, puedes configurar anonymizeUser
como false (falso).
Advertencia
Anonimizar a los usuarios afecta SEVERAMENTE tu información de atribución.Usa esta opción SOLO para regiones donde la ley te impida recopilar información de tus usuarios.
Compatibilidad con AppTrackingTransparency (ATT)
Los mensajes de Apple indican que, en el futuro, iOS 14 requerirá la autorización del usuario para recolectar el Identificador de anunciante (IDFA).
Actualmente, el IDFA se recopila por defecto. Sin embargo, para el iOS 14 beta 7 y versiones posteriores, tienes la opción de solicitar la autorización del usuario para recopilar el IDFA a través de un diálogo de consentimiento. Si el usuario no lo autoriza, el IDFA no se recopila. El intervalo de tiempo de espera retrasa el envío de una solicitud a los servidores de AppsFlyer. Después de que el temporizador expira, se envía la solicitud.
Para solicitar la autorización del usuario para recopilar el IDFA, agrega el siguiente código antes de start()
:
// The following block is for applications wishing to give users the option to block IDFA collection.
// for iOS 14 and above - The user can be prompted to block IDFA collection.
// If user opts-out, the IDFA will not be collected by the SDK.
// for iOS 13 and below - The IDFA will be collected by the SDK. The user will NOT be prompted to block collection.
if #available(iOS 14, *) {
// Set a timeout for the SDK to wait for the IDFA collection before handling app launch
// If timeout expires before user asks to block IDFA collection, the IDFA will be collected.
[[AppsFlyerLib shared] waitForATTUserAuthorizationWithTimeoutInterval:60];
// Show the user the Apple IDFA consent dialog
(AppTrackingTransparency)
// MUST be called here before start() in order to prevent IDFA collection by the SDK
[ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
//....
}];
}
// The following block is for applications wishing to give users the option to block IDFA collection.
// for iOS 14 and above - The user can be prompted to block IDFA collection.
// If user opts-out, the IDFA will not be collected by the SDK.
// for iOS 13 and below - The IDFA will be collected by the SDK. The user will NOT be prompted to block collection.
if #available(iOS 14, *) {
// Set a timeout for the SDK to wait for the IDFA collection before handling app launch
// If timeout expires before user asks to block IDFA collection, the IDFA will be collected.
AppsFlyerLib.shared().waitForATTUserAuthorization(timeoutInterval: 60)
// Show the user the Apple IDFA consent dialog (AppTrackingTransparency)
// MUST be called here before start() in order to prevent IDFA collection by the SDK
ATTrackingManager.requestTrackingAuthorization { (status) in
}
}
Para configurar el texto que se le mostrará al usuario en el mensaje emergente:
- Selecciona el archivo
Info.plist
del proyecto en el navegador de proyectos de Xcode. - Agregar una entrada a la lista: presiona
+
junto aLista de propiedades de información
. - Desplázate hacia abajo y selecciona
Privacidad: Descripción de seguimiento de uso
. - Agrega como
valor
el texto que quieras presentarle al usuario al solicitar permiso para recopilar el IDFA.
Nota: textos sugeridos para ATT
- Para proporcionarte contenido basado en tus preferencias personales, la aplicación necesita tu permiso.
- Para proporcionarte contenido personalizado adecuado, la aplicación necesita acceso a tu ID de dispositivo para los anunciantes.
Las posibles acciones del usuario en la ventana emergente de ATT y los resultados (en función del temporizador establecido por el desarrollador en el método waitForATTUserAuthorization) se enumeran en la tabla a continuación.
Nota: Después de que el temporizador expira, se inicia el SDK de AppsFlyer, ya sea recopilando el IDFA o no.
Acción del usuario | Resultado |
---|---|
Autoriza la recolección del IDFA antes de que el temporizador expire. |
Se recopila el IDFA. |
Rechaza la recolección del IDFA antes de que el temporizador expire. |
El IDFA no se recopila. |
Deja el mensaje emergente de fondo sin realizar ninguna acción. |
El temporizador se detiene hasta que el usuario lo vuelva a tener en primer plano. |
Deja el mensaje emergente en primer plano sin realizar ninguna acción y luego autoriza la recolección después de que expire el temporizador. |
Se recopila el IDFA. |
Deja el mensaje emergente en primer plano sin realizar ninguna acción y luego autoriza la recolección después de que expire el temporizador. |
El IDFA no se recopila. |
Excluir a los partners de la obtención de datos
En algunos casos, es posible que los anunciantes deseen dejar de compartir datos a nivel usuario con las redes de publicidad o los partners para usuarios específicos. Las razones para esto incluyen:
- Políticas de privacidad como la CCPA o el RGPD
- Mecanismos de exclusión opcional de los usuarios
- Competencia con algunos partners (redes de publicidad, terceros)
AppsFlyer proporciona dos métodos de la API para dejar de compartir datos con algunos o todos los partners:
- setSharingFilter: Utilizado por los anunciantes para evitar el intercambio de datos con algunas (una o más) redes/partners integrados.
- setSharingFilterForAllPartners: Utilizado por los anunciantes para evitar el intercambio de datos con todas las redes y partners integrados.
Estos métodos de filtrado son compatibles a partir del SDK V5.4.1.
El método de filtrado debe llamarse cada vez que se inicializa el SDK y afecta a toda la sesión. Si se necesita tiempo para determinar si es necesario configurar los filtros de compartición, entonces retrasa la inicialización del SDK.
Cuando el método se activa antes de la primera llamada a start:
- Los usuarios de SRN se atribuyen como orgánicos, y sus datos no se comparten con los partners integrados.
- Los usuarios de redes de publicidad de clic (no SRN) se atribuyen correctamente en AppsFlyer, pero no se comparten con las redes de publicidad a través de postbacks, API, reportes de raw data o por cualquier otro método.
Actualmente, los datos de desinstalación no pueden filtrarse con estos métodos. Sin embargo, puedes dejar de enviar los eventos de desinstalación a los partners usando sus páginas de configuración en AppsFlyer.
continueUserActivity
Descripción |
Llama a onAppOpenAttribution cuando se abre una aplicación desde un enlace universal para iOS 9 y superior. |
Firma de método |
|
Ejemplo de uso |
|
currencyCode
Descripción |
Establecer el código de divisa para eventos con ingresos. Acepta códigos de divisa ISO. |
Firma de método |
|
Ejemplo de uso |
|
anonymizeUser
Descripción |
Anonimiza las instalaciones, eventos y sesiones de un usuario. Para más información, consulta la sección sobre cómo anonimizar datos de usuarios. |
Firma de método |
|
Ejemplo de uso |
|
disableCollectASA
Descripción |
A partir del SDK versión 4.8.11, el SDK de AppsFlyer carga dinámicamente el iAd.framework de Apple. Este marco es necesario para registrar y medir el rendimiento de Apple Search Ads en tu aplicación. Si no deseas que AppsFlyer cargue dinámicamente este marco, configura esta propiedad como verdadera. |
Firma de método |
|
Ejemplo de uso |
|
handleOpenUrl
Descripción |
Este método informa el esquema URI al SDK de AppsFlyer cuando la aplicación se abre utilizando enlaces profundos con el esquema URI. Este método se coloca dentro de AppDelegate. |
Firma de método |
|
Ejemplo de uso |
|
handlePushNotification
Descripción |
Mide y obtén datos de campañas de notificaciones push. Para obtener más información, consulta la sección sobre cómo registrar notificaciones push. |
Firma de método |
|
Ejemplo de uso |
|
isDebug
Descripción |
Mostrar los registros del SDK de AppsFlyer en la consola Xcode. La depuración debe restringirse a la fase de desarrollo solamente. No distribuyas la aplicación en las tiendas de aplicaciones con la depuración habilitada. Esto implica riesgos importantes de seguridad y privacidad. |
Firma de método |
|
Ejemplo de uso |
|
isStopped
Descripción |
Desactiva toda la funcionalidad del SDK. Para más información, consulta la sección sobre privacidad de usuarios y exclusión opcional. |
Firma de método |
|
Ejemplo de uso |
|
onAppOpenAttribution
Descripción |
Obtén datos de enlaces profundos cuando se abre una aplicación a través de un enlace profundo. |
Firma de método |
|
Ejemplo de uso |
|
onAppOpenAttributionFailure
Descripción |
Manejar errores al obtener datos de enlaces profundos. |
Firma de método |
|
Ejemplo de uso |
|
onConversionDataSuccess
Descripción |
Obtener datos de conversión después de una instalación. Útil para enlaces profundos diferidos. Nota: A partir del SDK V5, |
Firma de método |
|
Ejemplo de uso |
|
onConversionDataFail
Descripción |
Maneja errores cuando no se obtienen los datos de conversión de las instalaciones. |
Firma de método |
|
Ejemplo de uso |
|
performOnAppAttribution
Descripción |
Permite a los desarrolladores volver a activar manualmente onAppOpenAttribution con un enlace específico (URI o URL), sin registrar un re-engagement nuevo. Este método puede ser necesario si la aplicación necesita redirigir a los usuarios en función del enlace dado o resolver la URL corta de AppsFlyer mientras permanece en primer plano/abierta. Esto podría ser necesario porque la devolución de llamada habitual de onAppOpenAttribution solo se realiza si la aplicación se abrió con el enlace profundo. |
Firma de método |
|
Ejemplo de uso |
|
registerUninstall
Descripción |
Medición de desinstalaciones. Consulta medición de desinstalaciones en iOS. |
Firma de método |
|
Ejemplo de uso |
|
resolveDeepLinkURLs
Descripción |
Resuelve OneLink para dominios de clics. Para más información, consulta la sección sobre cómo resolver las URL de enlaces profundos encapsulados. |
Firma de método |
|
Ejemplo de uso |
|
setAdditionalData
Descripción |
Se agregan datos adicionales para enviarlos a plataformas de partners externos. |
Firma de método |
|
Ejemplo de uso |
Consulta cómo configurar datos personalizados adicionales. |
setAppInviteOneLink
Descripción |
Configura el ID de plantilla de OneLink que se usa para crear enlaces de atribución personalizados para invitaciones de usuarios. |
Firma de método |
|
Ejemplo de uso |
Consulta la sección sobre cómo configurar OneLink para la atribución de invitaciones de usuarios. |
setAppleAppID
Descripción |
Configura el ID de tu aplicación (el ID de iTunes) para que el SDK pueda enviar datos al panel de control correcto de la aplicación. Úsalo cuando inicialices el SDK. |
Firma de método |
|
Ejemplo de uso |
|
appsFlyerDevKey
Descripción |
Configura la clave de desarrollador de AppsFlyer para que el SDK pueda enviar datos al panel de control correcto de la aplicación. Úsala cuando inicialices el SDK. Para aprender cómo obtener tu clave de desarrollador, consulta aquí. |
Firma de método |
|
Ejemplo de uso |
|
Establecer ID de Usuario de Cliente
Descripción |
Configura el ID de usuario de cliente. Para más información, consulta la sección sobre cómo configurar el ID de usuario de cliente. |
Firma de método |
|
Ejemplo de uso |
setSharingFilter
Descripción |
Utilizado por los anunciantes para configurar algunas (una o más) redes/partners integrados para excluir de la obtención de datos. |
Firma de método |
|
Ejemplo de uso |
|
setSharingFilterForAllPartners
Descripción |
Utilizado por los anunciantes para excluir a todas las redes y partners integrados de la obtención de datos. |
Firma de método |
|
Ejemplo de uso |
|
setShouldCollectDeviceName
Descripción |
Si el SDK debe recopilar el nombre del dispositivo. El valor predeterminado es falso. |
Firma de método |
|
Ejemplo de uso |
|
setUseUninstallSandbox
Descripción |
Para probar las desinstalaciones de aplicaciones que aún están en desarrollo (aún no publicadas en la App Store de Apple), configura esta propiedad como verdadera. |
Firma de método |
|
Ejemplo de uso |
|
startWithCompletionHandler
Descripción |
Comprueba si start es exitoso o no. Puedes aplicar tu propia lógica para manejar el éxito o el fracaso del inicio del SDK. |
Firma de método |
|
Ejemplo de uso |
Consulta verificar que el SDK iniciado es exitoso. |
logEvent
Descripción |
Envía eventos in-app a AppsFlyer. Para más información, consulta la sección sobre cómo registrar eventos in-app. |
Firma de método |
|
Ejemplo de uso |
|
validateAndLogInAppPurchase
Descripción |
Configura la clave de desarrollador de AppsFlyer para que el SDK pueda enviar datos al panel de control correcto de la aplicación. Para aprender cómo obtener tu clave de desarrollador, consulta aquí. Úsalo cuando inicialices el SDK. |
Firma de método |
|
Ejemplo de uso |
Consulta Validación de compras in-app. |
disableAdvertiserIdentifier
Descripción |
A partir del SDK versión 4.8.11, el SDK de AppsFlyer carga dinámicamente el adSupport.framework de Apple. Este marco es necesario para recopilar el identificador de anunciante (IDFA) con fines de atribución. Si no deseas que AppsFlyer cargue dinámicamente este marco, configura esta propiedad como verdadera. |
Firma de método |
|
Ejemplo de uso |
[AppsFlyerLib shared].disableAdvertiserIdentifier= YES; AppsFlyerLib.shared().disableAdvertiserIdentifier = true |
waitForATTUserAuthorization
Descripción |
Se utiliza si quieres solicitar la autorización del usuario a través de una ventana emergente antes de acceder a los datos relacionados con la aplicación para registrar al usuario o al dispositivo (por ejemplo, IDFA). Si el usuario lo autoriza, se enviará el IDFA al SDK. El intervalo de tiempo de espera le da al usuario una cantidad de tiempo determinada para autorizar la recopilación del IDFA. Después de que el temporizador expira, el IDFA no se recopila. |
Firma de método |
|
Ejemplo de uso |
|
start
Descripción |
Una vez que se invoca esta API, se iniciará el SDK, se enviarán inmediatamente las sesiones y todas las transiciones de fondo en primer plano registrarán una sesión. |
Firma de método |
|
Ejemplo de uso |
|
logLocation
Descripción |
Registra manualmente la ubicación del usuario. |
Firma de método |
|
Ejemplo de uso |
|
Comentarios
Inicie sesión para dejar un comentario.