Visión general de SKAdNetwork
SKAdNetwork es un marco proporcionado por Apple para permitir una medición respetuosa con la privacidad de las campañas publicitarias de instalación de aplicaciones en iOS(más información). El marco ayuda a medir las tasas de conversión de las campañas de instalación de aplicaciones sin comprometer los identificadores de los usuarios.
¿Cómo funciona SKAdNetwork?
En SKAdNetwork, el proceso de atribución lo realiza la App Store a través de los servidores de Apple. A continuación, la información de atribución se desconecta de los identificadores de usuario y de la información temporal y se envía a la red.
Cuando se hace clic en un anuncio y se abre la tienda, la aplicación que lo publica y la red proporcionan información básica como el ID de la red, del editor y de la campaña. Si la aplicación del anunciante se ha lanzado y registrado en SKAdNetwork, el dispositivo enviará una notificación de conversión correcta a la red. Notificará los valores adjuntos junto con un valor de conversión que puede ser notificado por la app anunciada.
Dicha notificación se enviará al menos 24 horas después del primer lanzamiento y estará desprovista de cualquier información identificativa del dispositivo o del usuario.
Además, la App Store lleva a cabo el proceso de forma que la aplicación anunciada no tenga conocimiento del anuncio original ni del editor. De este modo, la red recibe la notificación de una instalación sin saber nada del usuario que la realiza.
¿Qué se puede esperar al utilizar SKAdNetwork?
SKAdNetwork tiene algunas ventajas importantes. Le proporciona toda la información siguiente
- Atribución del último clic que funciona sin consentimiento
- Desglose por fuente, campaña y editor
- Valores de conversión posteriores a la instalación (hasta 64 valores discretos)
- Firmas criptográficas para validar las instalaciones
Sin embargo, en su forma actual, SKAdNetwork es muy básico y requiere una cuidadosa implementación y coordinación entre múltiples entidades para garantizar su funcionamiento.
He aquí algunas de las limitaciones actuales de SKAdNetwork:
- No hay datos a nivel de usuario
- No hay atribución de visibilidad
- Gama limitada de valores deconversión:
- Un único evento de conversión por instalación/reinstalación
- Hasta 64 valores de conversión (6 bits)
- Granularidadlimitada:
- Hasta 100 valores de campaña
- Sin representación para el nivel de grupo de anuncios y creativo
- Sin LTV / cohortes largas
- Exposición al fraude:
- El valor de conversión en sí no está firmado (puede manipularse)
- Las devoluciones pueden duplicarse.
Para superar algunos de estos problemas, Singular ha lanzado un estándar público para la implementación de SKAdNetwork, así como varias entradas de blog que pueden ayudarle a navegar por SKAdNEtwork:
- SKAN: Una norma práctica parala implementación de SKAdNetwork
- SKAdNetwork 101 - ¿Qué es? ¿Qué significa para usted?
- Código SKAdNetwork: Singular libera un repositorio Github con código para redes publicitarias, editores y anunciantes
- Cómo probar SKAdNetwork: instrucciones paso a paso
- Singular anuncia el primer soporte de mercado para sustituir al IDFA
- Medición avanzada con SKAdNetwork: Desbloquear el ROAS
- SKAdNetwork 2.0 seguro: Una configuración sin fisuras para establecer la confianza
Implementación de SKAdNetwork S2S
La solución SKAdNetwork Singular consta de los siguientes componentes:
- Código del lado del cliente para implementar SKAdNetwork
- Validación y agregación postback de todas las redes
- Protección contra el fraude:
- Validación de firmas y deduplicación de ID de transacciones.
- Configuración segura con las redes para verificar los parámetros que no están firmados (valor de conversión y geodatos).
- Gestión del valor de conversión: ofrece la posibilidad de configurar dinámicamente en el panel de control de Singular qué actividad posterior a la instalación debe codificarse en el valor de conversión de SKAdNetwork.
- Generación de informes: Traducción del ID de campaña limitado de SKAdNetwork y enriquecimiento de los datos con más parámetros y granularidades de marketing.
- Postbacks de socios: Proporciona el envío de postbacks de SKAdNetwork con un valor de conversión descodificado en eventos e ingresos, lo cual es crítico para su optimización.
Para los clientes que utilizan una integración Singular de servidor a servidor, la implementación de SKAdNetwork consta de dos partes principales:
- Implementación del lado del cliente de SKAdNetwork: Esta parte es fundamental para registrar sus aplicaciones en SKAdNetwork y gestionar el valor de conversión de SKAdNetwork de forma inteligente. Esto significa que, al implementarla, podrá optimizar sus campañas basándose en las atribuciones de SKAdNetwork y sus actividades post-instalación asociadas.
- Actualización de la integración S2S (opcional): Esta parte es importante para validar y solucionar problemas de la implementación del lado del cliente. Al enriquecer los eventos y sesiones enviados hoy a SIngular a través de los endpoints de eventos y sesiones S2S de Singular con datos de SKAdNetwork (valores de conversión y marcas de tiempo de actualización), Singular puede validar que la implementación se ha realizado correctamente en el lado de su aplicación.
Implementación del lado del cliente de SKAdNetwork
Singular proporciona ejemplos de código que permiten registrarse en SKAdNetwork y gestionar el valor de conversión. Estos ejemplos de código se encargan de las siguientes partes:
- Soporte y registro de SKAdnetwork
- Gestión del valor de conversión:
- El código se comunica de forma sincrónica con un endpoint de Singular para recibir el siguiente valor de conversión basado en el modelo de conversión configurado. Informa de eventos/sesiones/ingresos y, en respuesta, obtiene el siguiente valor de conversión, que es un número codificado que representa la actividad posterior a la instalación que se configuró para la medición en el panel de control de Singular.
- El código también recopila metadatos de SKAdnetwork que se utilizan tanto para la validación como para el cálculo del valor de la siguiente conversión:
- La marca de tiempo de la primera llamada al marco SKAdNetwork subyacente.
- La fecha y hora de la última llamada al marco SKAdNetwork subyacente.
- El último valor de conversión actualizado
Actualización de la integración S2S
Obligatorio
Una vez que tenga un modelo de conversión activo, nuestros endpoints S2S empezarán a devolver un nuevo campo int llamado "conversion_value", que contendrá el siguiente valor a actualizar en el código del lado del cliente.
Opcional
Para validar la integración y solucionar posibles problemas de implementación, le recomendamos que utilice nuestros ejemplos de código para ampliar su integración S2S actual. Los puntos finales de sesión y eventos S2S de Singular ya admiten la obtención de parámetros SKAdNetwork adicionales como:
- Último valor de conversión
- Última marca de tiempo de una llamada al marco SKAdNetwork subyacente
- Primera marca de tiempo de una llamada al marco SKAdNetwork subyacente
Flujo de integración
El diagrama anterior ilustra el flujo de SKAdNetwork para un cliente S2S:
- En primer lugar, el código de la aplicación se comunica con un servidor Singular (a través de un punto final dedicado para SKAdNetwork) para obtener el último valor de conversión de forma sincrónica en función de los eventos/sesiones/eventos que se producen en la aplicación y actualizar el marco SKAdNetwork con este valor.
- En segundo lugar, la aplicación enriquece los eventos y sesiones existentes con datos de SKAdNetwork, que se utilizarán posteriormente para las validaciones.
- Cuando la aplicación termina de actualizar el marco SKAdNetwork con los nuevos valores de conversión y el temporizador SKAdNetwork expira, el postback SKAdNetwork se envía a la red.
- La red lo reenviará a Singular (a través de la configuración segura o de la configuración normal).
- Singular procesará el postback
- Validando su firma
- Decodificación del valor de conversión basado en el modelo de conversión configurado.
- Enriquecer el postback con más parámetros de marketing orientados al exterior basados en la integración con socios y el ID de campaña interno de SKAdNetwork.
- Envío de los postbacks descodificados a BI y a los socios
Una nota importante es que la información de SKAdNetwork, incluidas las instalaciones y los eventos descodificados, será accesible a través de un conjunto diferente de informes/APIs/ tablas ETL y postbacks para evitar mezclarla con sus conjuntos de datos existentes. Esto es especialmente importante durante las próximas semanas para que pueda medir y probar SKAdNetwork codo con codo con su campaña actual.
Ejemplos de código nativo iOS de SKAdNetwork
Interfaz SKAdNetwork
Esta interfaz incluye los siguientes componentes de SKAdNetwork:
Registro en SKAdNetwork:
- Este método se encarga de registrar su aplicación en SKAdNetwork. El método subyacente de la API de Apple genera una notificación si el dispositivo tiene datos de atribución para esa app, e inicia un temporizador de 24 horas.
- El dispositivo envía la notificación de instalación al punto final de postback de la red publicitaria entre 0 y 24 horas después de que expire el temporizador.
- Tenga en cuenta que si actualiza el valor de conversión con un valor mayor que el anterior, se reinicia el primer temporizador para un nuevo intervalo de 24 horas(lea más aquí).
Gestión y actualizacióndel valor de conversión:
- El valor de conversión se calcula en base a la actividad post-instalación de un dispositivo que es capturada por los métodos a continuación y un modelo de conversión seleccionado que puede ser configurado dinámicamente por el usuario.
- Los métodos de esta sección se encargan de extraer el siguiente valor de conversión del punto final de Singular en función del modelo de conversión seleccionado y de la actividad posterior a la instalación notificada (véase la documentación anterior).
- Los métodos siguientes actualizan el valor de conversión en función de las siguientes actividades posteriores a la instalación:
- Sesión: crítico para la medición de retención de un usuario con SKAdNetwork.
- Evento de conversión: crítico para la medición de eventos de conversión post-instalación con SKAdNetwork
- Evento de ingresos: crítico para la medición de ingresos con SKAdNetwork
// SKANSnippet.h
#import <Foundation/Foundation.h>
@interface
SKANSnippet : NSObject
// Regístrese para la atribución de SkAdNetwork. Debes llamar a este método lo antes posible una vez que se inicie la aplicación.
+ (void)registerAppForAdNetworkAttribution;
/* Para realizar un seguimiento de la retención y las cohortes, debe llamar a este método después de cada sesión. Informa los detalles de la sesión y actualiza el valor de conversión debido a esta sesión si es necesario. El valor de conversión se actualizará solo si el nuevo valor es mayor que el valor anterior. La devolución de llamada pasada al método es opcional; puede usarla para ejecutar código una vez que se actualice el valor de conversión.*/
+ (void)updateConversionValueAsync:(void(^)(int, NSError*))handler;
/* Para realizar un seguimiento de los eventos de conversión con SKAdNetwork, debe llamar a este método después de cada evento. Informa los detalles del evento y actualiza el valor de conversión debido a este evento si es necesario. La devolución de llamada pasada al método es opcional; puede usarla para ejecutar código una vez que se actualice el valor de conversión.*/
+ (void)updateConversionValueAsync:(NSString*)eventName
withCompletionHandler:(void(^)(int, NSError*))handler;
/* Para realizar un seguimiento de los ingresos con SKAdNetwork, debe llamar a este método antes de cada evento de ingresos. Actualizará los ingresos totales, por lo que cuando llame a 'updateConversionValueAsync', el nuevo valor de conversión se determinará según la cantidad total de ingresos.
Nota:
1. Llame a este método antes de llamar a 'updateConversionValueAsync' para asegurarse de que los ingresos estén actualizados.
2. En caso de volver a intentar un evento, evite llamar a este método para que los mismos ingresos no cuenten dos veces. */
+ (void)updateRevenue:(double)amount andCurrency:(NSString*)currency;
// Obtiene el valor de conversión actual (nulo si no hay ninguno)
+ (NSNumber *)getConversionValue;
@end
Implementación de la interfaz SKAdNetwork
// SKANSnippet.m
#import "SKANSnippet.h"
#import <StoreKit/SKAdNetwork.h>
#define SESSION_EVENT_NAME @”__SESSION__”
#define SINGULAR_API_URL @"https://sdk-api-v1.singular.net/api/v1/conversion_value"
// Claves para el almacenamiento de UserDefaults
#define CONVERSION_VALUE_KEY @"skan_conversion_value"
#define FIRST_SKAN_CALL_TIMESTAMP @"skan_first_call_to_skadnetwork_timestamp"
#define LAST_SKAN_CALL_TIMESTAMP @"skan_last_call_to_skadnetwork_timestamp"
#define TOTAL_REVENUE_BY_CURRENCY_KEY @"skan_total_revenue_by_currency"
#define SECONDS_PER_DAY 86400
@implementation
SKANSnippet
+ (void)registerAppForAdNetworkAttribution {
if ([SKANSnippet getFirstSkanCallTimestamp] != 0) {
return;
}
if (@available(iOS 11.3, *) ) {
[SKAdNetwork registerAppForAdNetworkAttribution];
[SKANSnippet setFirstSkanCallTimestamp];
[SKANSnippet setLastSkanCallTimestamp];
}
}
+ (void)updateConversionValueAsync:(void(^)(int, NSError*))handler {
[SKANSnippet updateConversionValueAsync:SESSION_EVENT_NAME withCompletionHandler:handler];
}
+ (void)updateConversionValueAsync:(NSString*)eventName withCompletionHandler:(void(^)(int, NSError*))handler {
if (@available(iOS 14, *)) {
if ([SKANSnippet isSkanUpdateWindowOver]) {
return;
}
[SKANSnippet getConversionValueFromServer:eventName withCompletionHandler:handler];
}
}
+ (void)updateRevenue:(double)amount andCurrency:(NSString*)currency {
if (@available(iOS 14, *)) {
// Update total revenues
if (amount != 0 && currency) {
NSMutableDictionary* revenues = [[SKANSnippet getTotalRevenue] mutableCopy];
NSNumber* currentRevenue = 0;
if ([revenues objectForKey:currency]) {
currentRevenue = [revenues objectForKey:currency];
}
currentRevenue = @([currentRevenue floatValue] + amount);
[revenues setObject:currentRevenue forKey:currency];
[SKANSnippet setTotalRevenue:revenues];
}
}
}
+ (NSNumber *)getConversionValue {
NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
if (![userDefaults objectForKey:CONVERSION_VALUE_KEY]) {
return nil;
}
return @([userDefaults integerForKey:CONVERSION_VALUE_KEY]);
}
+ (void)getConversionValueFromServer:(NSString*)eventName withCompletionHandler:(void(^)(int, NSError*))handler {
if (!lockObject) {
lockObject = [NSLock new];
}
// Making the lock async so it will not freeze the calling thread
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
[lockObject lock];
NSURLComponents *components = [NSURLComponents componentsWithString:SINGULAR_API_URL];
NSString* bundleIdentifier = @"";
components.queryItems = @[
[NSURLQueryItem queryItemWithName:@"a" value:@""],
[NSURLQueryItem queryItemWithName:@"i" value:bundleIdentifier],
[NSURLQueryItem queryItemWithName:@"app_v" value:@""],
[NSURLQueryItem queryItemWithName:@"n" value:eventName],
[NSURLQueryItem queryItemWithName:@"p" value:@"iOS"],
[NSURLQueryItem queryItemWithName:@"idfv" value:@""],
[NSURLQueryItem queryItemWithName:@"idfa" value:@""],
[NSURLQueryItem queryItemWithName:@"conversion_value"
value:[[SKANSnippet getConversionValue] stringValue]],
[NSURLQueryItem queryItemWithName:@"total_revenue_by_currency"
value:[SKANSnippet dictionaryToJsonString:[SKANSnippet getTotalRevenue]]],
[NSURLQueryItem queryItemWithName:@"first_call_to_skadnetwork_timestamp"
value:[NSString stringWithFormat:@"%ld", [SKANSnippet getFirstSkanCallTimestamp]]],
[NSURLQueryItem queryItemWithName:@"last_call_to_skadnetwork_timestamp"
value:[NSString stringWithFormat:@"%ld", [SKANSnippet getLastSkanCallTimestamp]]],
];
[[[NSURLSession sharedSession] dataTaskWithURL:components.URL
completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error) {
[lockObject unlock];
if (handler) {
handler(-1, error);
}
return;
}
NSDictionary* parsedResponse = [SKANSnippet jsonDataToDictionary:data];
if (!parsedResponse) {
[lockObject unlock];
if (handler) {
handler(-1, [NSError errorWithDomain:bundleIdentifier
code:0
userInfo:@{NSLocalizedDescriptionKey:@"Failed parsing server response"}]);
}
return;
}
NSNumber *conversionValue = [parsedResponse objectForKey:@"conversion_value"];
if (!conversionValue) {
[lockObject unlock];
NSString *status = [parsedResponse objectForKey:@"status"];
if (!status || ![status isEqualToString:@"ok"]) {
if (handler) {
NSString *reason = [parsedResponse objectForKey:@"reason"];
if (!reason) {
reason = @"Got error from server";
}
handler(-1, [NSError errorWithDomain:bundleIdentifier
code:0
userInfo:@{NSLocalizedDescriptionKey:reason}]);
}
}
return;
}
NSNumber* currentValue = [SKANSnippet getConversionValue];
if ([conversionValue intValue] <= [currentValue intValue]) {
[lockObject unlock];
return;
}
[SKANSnippet setConversionValue:[conversionValue intValue]];
[SKANSnippet setLastSkanCallTimestamp];
if (![SKANSnippet getFirstSkanCallTimestamp]) {
[SKANSnippet setFirstSkanCallTimestamp];
}
[lockObject unlock];
if (handler) {
handler([conversionValue intValue], error);
}
}] resume];
});
}
+ (BOOL)isSkanUpdateWindowOver {
NSInteger timeDiff = [SKANSnippet getCurrentUnixTimestamp] -
[SKANSnippet getLastSkanCallTimestamp];
return SECONDS_PER_DAY <= timeDiff;
}
Metadatos y métodos de utilidad de SKAdNetwork
Esta sección se encarga de implementar las utilidades que se utilizan en la implementación anterior. Tenga en cuenta que estas utilidades son fundamentales para mantener y almacenar los metadatos necesarios para calcular los siguientes valores de conversión.
Se implementan las siguientes utilidades:
Guardar valores en UserDefaults (y recuperarlos):
- Marca de tiempo de la primera llamada a la API SKAdNetwork subyacente.
- Fecha y hora de la última llamada a la API SKAdNetwork subyacente
- Ingresos totales por divisa
Conversión de valores entre diferentes representaciones:
- Diccionario a cadena JSON
- JSON a diccionario
+ (NSInteger)getFirstSkanCallTimestamp {
NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
return [userDefaults integerForKey:FIRST_SKAN_CALL_TIMESTAMP];
}
+ (NSInteger)getLastSkanCallTimestamp {
NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
return [userDefaults integerForKey:LAST_SKAN_CALL_TIMESTAMP];
}
+ (NSDictionary*)getTotalRevenue {
NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
if (![userDefaults objectForKey:TOTAL_REVENUE_BY_CURRENCY_KEY]) {
return [NSDictionary new];
}
return [userDefaults objectForKey:TOTAL_REVENUE_BY_CURRENCY_KEY];
}
+ (NSInteger)getCurrentUnixTimestamp {
return [[NSDate date]timeIntervalSince1970];
}
+ (void)setConversionValue:(int)value {
if (@available(iOS 14.0, *)) {
if (value <= [[SKANSnippet getConversionValue] intValue]) {
return;
}
[SKAdNetwork updateConversionValue:value];
NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setInteger:value forKey:CONVERSION_VALUE_KEY];
[userDefaults synchronize];
}
}
+ (void)setFirstSkanCallTimestamp {
NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setInteger:[SKANSnippet getCurrentUnixTimestamp]
forKey:FIRST_SKAN_CALL_TIMESTAMP];
[userDefaults synchronize];
}
+ (void)setLastSkanCallTimestamp {
NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setInteger:[SKANSnippet getCurrentUnixTimestamp]
forKey:LAST_SKAN_CALL_TIMESTAMP];
[userDefaults synchronize];
}
+ (void)setTotalRevenue:(NSDictionary *)values {
NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setObject:values forKey:TOTAL_REVENUE_BY_CURRENCY_KEY];
[userDefaults synchronize];
}
+ (NSString*)dictionaryToJSONString:(NSDictionary*)dictionary {
if (!dictionary || [dictionary count] == 0){
return @"{}";
}
NSError *error;
NSData *JSONData = [NSJSONSerialization dataWithJSONObject:dictionary
options:0
error:&error];
if (error || !JSONData) {
return @"{}";
}
return [[NSString alloc] initWithData:JSONData
encoding:NSUTF8StringEncoding];
}
+ (NSDictionary*)JSONDataToDictionary:(NSData*)JSONData {
if (!JSONData) {
return nil;
}
NSError * error;
NSDictionary * parsedData = [NSJSONSerialization
JSONObjectWithData:JSONData
options:kNilOptions error:&error];
if (error || !parsedData) {
return nil;
}
return parsedData;
}
@end
Actualización de la integración S2S - Implementación (opcional)
Actualice su integración S2S con los siguientes metadatos de SKAdNetwork (estos metadatos deben enviarse en cada sesión y evento comunicado a Singular para la validación de la implementación de SKAdNetwork):
- skan_conversion_value - El último valor de conversión
- skan_first_call_timestamp - Sello de tiempo Unix de la primera llamada a la API SkAdNetwork subyacente.
- skan_last_call_timestamp - Unix timestamp de la última llamada a la API SkAdNetwork subyacente
El siguiente fragmento de código muestra cómo extraer estos valores:
NSDictionary *values = @{
@"skan_conversion_value":
[[SKANSnippet getConversionValue] stringValue]],
@"skan_first_call_timestamp":
[NSString stringWithFormat:@"%ld", [SKANSnippet getFirstSkanCallTimestamp]],
@"skan_last_call_timestamp":
[NSString stringWithFormat:@"%ld", [SKANSnippet getLastSkanCallTimestamp]]
};
Ahora, una vez que envíe estos parámetros a su servidor, puede reenviarlos a través de nuestros puntos finales de API de servidor a servidor. Para obtener más información, busque estos parámetros en nuestra referencia de API de servidor a servidor.
Ejemplo de flujo del ciclo de vida de la aplicación
// Al iniciar la aplicación
[SKANSnippet registerAppForAdNetworkAttribution];
// Después de cada sesión se maneja
[SKANSnippet updateConversionValueAsync:handler];
// Después de manejar eventos que no generan ingresos
[SKANSnippet updateConversionValueAsync:@"event_name"
withCompletionHandler:handler];
// Después de manejar eventos de ingresos
[SKANSnippet updateRevenue:15.53 andCurrency:@"KRW"];
[SKANSnippet updateConversionValueAsync:@"revenue_event_name" withCompletionHandler:handler];
Registro de cambios de código
- 1 de octubre de 2020
- Corrección [IMPORTANTE]:el mecanismo de bloqueo de `getConversionValueFromServer`no se iniciaba correctamente.
- Mejorado: devolver la razón de fallo de la respuesta de nuestro servidor
- 23 Sep 2020
- Corrección [IMPORTANTE]:`setConversionValue` ahora llama a `updateConversionValue`.
- Mejorado : gestión de errores al recuperar el último valor de conversión del servidor
- 15 sep 2020
- Cambiado [IMPORTANTE]: Si no se establece el valor de conversión, el valor por defecto devuelto por `getConversionValue` es 0 en lugar de null
- Mejorado: Informes y gestión de ingresos
- Mejorado: Recuperación del siguiente valor de conversión de forma asíncrona
Probar la implantación
Gestión de conversiones
Para simular el flujo de su aplicación y probar su implementación, sustituya el punto final de producción de la gestión de conversiones(SINGULAR_API_URL) por el siguiente punto final de prueba
-
- https://skadnetwork-testing.singular.net/api/v1/conversion_value
- No se requiere clave API
Flujo de prueba sugerido:
- Genere 3 eventos diferentes dentro de su aplicación.
-
- Si todo se implementa correctamente
- Después de cada evento updateConversionValueAsync se supone que debe ser llamado (asegúrese de que su valor de conversión por defecto se inicializa a 0).
- El endpoint de prueba recibe el valor de conversión actual de la aplicación y devuelve el siguiente valor.
- Si todo se implementa correctamente
- Registra el valor de conversión devuelto para ver que todo funciona como se espera.
- El endpoint de prueba está implementado para devolver valores entre 0-2.
- Por lo tanto, después de la tercera llamada, devolverá una cadena vacía, y el último valor se utilizará como valor de conversión final de SKAdNetwork.
-