Atribución de ingresos por publicidad
Rastrea los ingresos por publicidad provenientes de plataformas de mediación y atribúyelos a las campañas de marketing que adquirieron a tus usuarios, brindando visibilidad completa del ROI sobre los costos de campaña, las compras dentro de la aplicación y la monetización publicitaria.
Resumen
Qué es la atribución de ingresos por publicidad
La atribución de ingresos por publicidad conecta los ingresos por publicidad de las aplicaciones móviles con las campañas de adquisición de usuarios que generaron las instalaciones, lo que te permite medir la verdadera rentabilidad de las campañas incluyendo la monetización publicitaria.
Beneficios principales:
- Vista de ROI unificada: Consulta los costos de campaña, los ingresos in-app y los ingresos por publicidad en un solo dashboard
- Optimización de campañas: Envía los datos de ingresos por publicidad a las redes publicitarias para mejorar la puja y la segmentación
- Medición de LTV: Calcula el valor de vida completo del usuario incluyendo la monetización publicitaria
Fuentes de datos: Los datos de ingresos por publicidad normalmente provienen de tu plataforma de mediación (por ejemplo, AdMob, AppLovin MAX, IronSource), ya sea a nivel de usuario o a nivel de impresión. Singular soporta múltiples métodos de integración para recibir estos datos.
Más información: Consulta las Preguntas frecuentes sobre la atribución de ingresos por publicidad para conocer los detalles completos sobre configuración, reportes y resolución de problemas.
Requisitos de implementación
Directrices críticas
Parámetros requeridos de SingularAdData:
Los argumentos del constructor
adPlatform
,
currency
, y
revenue
son todos requeridos. Si alguno está ausente, vacío o no es válido, el SDK descarta silenciosamente la llamada a
Singular.adRevenue()
sin lanzar una excepción ni devolver un error.
Singular.adRevenue()
tampoco realiza ninguna acción cuando el SDK aún no ha sido inicializado: confirma siempre que
Singular.init()
se haya ejecutado antes de llamarlo.
La precisión de los datos es fundamental:
- Códigos de moneda: Usa códigos de moneda ISO 4217 de tres letras (por ejemplo, USD, EUR, INR). Muchas plataformas de mediación reportan en USD; verifica la moneda de tu plataforma antes de la implementación.
-
Validar antes de enviar:
Valida siempre los datos de ingresos y moneda antes de llamar a
Singular.adRevenue(). Los datos incorrectos no pueden corregirse después del envío. - Diferencias entre plataformas: Algunos SDK reportan los ingresos en micros (divide entre 1.000.000), mientras que otros reportan en unidades de moneda estándar. Consulta la documentación de tu plataforma.
Pasos de configuración
Sigue estos pasos para implementar la atribución de ingresos por publicidad:
- Actualiza el SDK: Asegúrate de utilizar la última versión del SDK de Singular.
- Elige la integración: Selecciona a continuación la integración de plataforma de mediación que coincida con tu configuración.
- Implementa los callbacks: Agrega listeners de eventos pagados específicos de la plataforma para capturar los datos de ingresos.
- Valida los datos: Prueba el reporte de ingresos y verifica que los datos aparezcan en el dashboard de Singular.
Integraciones de plataformas
Integración con AdMob
Rastrea los ingresos por publicidad de Google AdMob usando el listener de eventos pagados para el reporte de ingresos a nivel de impresión.
Requisitos:
- Habilita el seguimiento de eventos pagados en tu cuenta de AdMob (consulta Soporte de AdMob )
- Implementa el SDK de Google Mobile Ads para Android (consulta Guía de inicio )
Reporte de ingresos por plataforma:
AdMob reporta los ingresos de manera diferente según la plataforma. Android devuelve los ingresos en micros (por ejemplo, $0,005 = 5000). Divide
adValue.valueMicros
entre 1.000.000 para convertir a unidades de moneda estándar antes de enviar a Singular.
Implementación
Establece un listener de eventos pagados al cargar los anuncios para capturar los datos de ingresos y enviarlos a Singular.
import com.singular.sdk.Singular
import com.singular.sdk.SingularAdData
import com.google.android.gms.ads.AdRequest
import com.google.android.gms.ads.rewarded.RewardedAd
import com.google.android.gms.ads.rewarded.RewardedAdLoadCallback
private const val AD_UNIT_ID = "YOUR_AD_UNIT_ID"
class AdManager(private val context: Context) {
private var rewardedAd: RewardedAd? = null
fun loadRewardedAd() {
val adRequest = AdRequest.Builder().build()
RewardedAd.load(context, AD_UNIT_ID, adRequest,
object : RewardedAdLoadCallback() {
override fun onAdLoaded(ad: RewardedAd) {
rewardedAd = ad
// Set full screen content callback
rewardedAd?.fullScreenContentCallback =
object : FullScreenContentCallback() {
override fun onAdShowedFullScreenContent() {
Log.d("AdManager", "Rewarded ad displayed")
}
override fun onAdDismissedFullScreenContent() {
Log.d("AdManager", "Rewarded ad dismissed")
}
}
// Set paid event listener for revenue tracking
rewardedAd?.setOnPaidEventListener { adValue ->
// Convert revenue from micros to standard units
val revenue = adValue.valueMicros / 1_000_000.0
val currency = adValue.currencyCode
// Validate revenue data before sending
if (revenue > 0 && !currency.isNullOrEmpty()) {
val data = SingularAdData(
"AdMob",
currency,
revenue
)
Singular.adRevenue(data)
Log.d("AdManager", "Ad revenue sent: $revenue $currency")
} else {
Log.w("AdManager", "Invalid revenue: $revenue $currency")
}
}
}
override fun onAdFailedToLoad(error: LoadAdError) {
Log.e("AdManager", "Ad failed to load: ${error.message}")
}
})
}
}
import com.singular.sdk.Singular;
import com.singular.sdk.SingularAdData;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.rewarded.RewardedAd;
import com.google.android.gms.ads.rewarded.RewardedAdLoadCallback;
private static final String AD_UNIT_ID = "YOUR_AD_UNIT_ID";
public class AdManager {
private RewardedAd rewardedAd;
private Context context;
public AdManager(Context context) {
this.context = context;
}
public void loadRewardedAd() {
AdRequest adRequest = new AdRequest.Builder().build();
RewardedAd.load(context, AD_UNIT_ID, adRequest,
new RewardedAdLoadCallback() {
@Override
public void onAdLoaded(RewardedAd ad) {
rewardedAd = ad;
// Set full screen content callback
rewardedAd.setFullScreenContentCallback(
new FullScreenContentCallback() {
@Override
public void onAdShowedFullScreenContent() {
Log.d("AdManager", "Rewarded ad displayed");
}
@Override
public void onAdDismissedFullScreenContent() {
Log.d("AdManager", "Rewarded ad dismissed");
}
});
// Set paid event listener for revenue tracking
rewardedAd.setOnPaidEventListener(new OnPaidEventListener() {
@Override
public void onPaidEvent(AdValue adValue) {
// Convert revenue from micros to standard units
double revenue = adValue.getValueMicros() / 1_000_000.0;
String currency = adValue.getCurrencyCode();
// Validate revenue data before sending
if (revenue > 0 && currency != null && !currency.isEmpty()) {
SingularAdData data = new SingularAdData(
"AdMob",
currency,
revenue
);
Singular.adRevenue(data);
Log.d("AdManager", "Ad revenue sent: " + revenue + " " + currency);
} else {
Log.w("AdManager", "Invalid revenue: " + revenue + " " + currency);
}
}
});
}
@Override
public void onAdFailedToLoad(LoadAdError error) {
Log.e("AdManager", "Ad failed to load: " + error.getMessage());
}
});
}
}
Integración con AppLovin MAX
Comparte los ingresos por publicidad a nivel de impresión usando la AppLovin Impression-Level User Revenue API.
Requisitos:
- Implementa el SDK de AppLovin MAX (consulta Guía de la API de ingresos a nivel de impresión )
-
Suscríbete al topic
max_revenue_eventsmediante AppLovin Communicator
Implementación
Procesa los mensajes de ingresos a través del callback de AppLovin Communicator.
import com.singular.sdk.Singular
import com.singular.sdk.SingularAdData
import com.applovin.communicator.AppLovinCommunicatorMessage
override fun onMessageReceived(message: AppLovinCommunicatorMessage) {
// Check for revenue events topic
if (message.topic == "max_revenue_events") {
val adData: Bundle? = message.messageData
// Extract and validate revenue value
val revenueValue = adData?.getDouble("revenue", 0.0) ?: 0.0
if (revenueValue > 0) {
val data = SingularAdData(
"AppLovin",
"USD", // AppLovin typically reports in USD
revenueValue
)
Singular.adRevenue(data)
Log.d("AppLovin", "Ad revenue sent: $revenueValue USD")
} else {
Log.w("AppLovin", "Invalid revenue value: $revenueValue")
}
}
}
import com.singular.sdk.Singular;
import com.singular.sdk.SingularAdData;
import com.applovin.communicator.AppLovinCommunicatorMessage;
@Override
public void onMessageReceived(AppLovinCommunicatorMessage message) {
// Check for revenue events topic
if ("max_revenue_events".equals(message.getTopic())) {
Bundle adData = message.getMessageData();
// Extract and validate revenue value
double revenueValue = (adData != null) ?
adData.getDouble("revenue", 0.0) : 0.0;
if (revenueValue > 0) {
SingularAdData data = new SingularAdData(
"AppLovin",
"USD", // AppLovin typically reports in USD
revenueValue
);
Singular.adRevenue(data);
Log.d("AppLovin", "Ad revenue sent: " + revenueValue + " USD");
} else {
Log.w("AppLovin", "Invalid revenue value: " + revenueValue);
}
}
}
Integración con Unity LevelPlay (IronSource)
Rastrea los ingresos a nivel de impresión de ironSource y de las redes mediadas usando el SDK de IronSource.
Requisitos:
- Implementa el SDK de ironSource (consulta Guía de inicio )
- Habilita la opción ARM SDK Postbacks en tu dashboard de IronSource
- Configura el listener de datos de impresión para recibir los callbacks de ingresos
Más información: Consulta la Documentación de ingresos por publicidad de IronSource para obtener los detalles completos de configuración.
Implementación
Implementa el callback de éxito de datos de impresión para capturar y enviar los ingresos.
import com.singular.sdk.Singular
import com.singular.sdk.SingularAdData
import com.ironsource.mediationsdk.impressionData.ImpressionData
fun onImpressionDataSuccess(impressionData: ImpressionData?) {
// Validate impression data
if (impressionData == null) {
Log.d("IronSource", "No impression data available")
return
}
// Extract and validate revenue
val revenue = impressionData.revenue?.toDouble() ?: 0.0
if (revenue <= 0) {
Log.w("IronSource", "Invalid revenue: $revenue")
return
}
// Create and send ad revenue data
val data = SingularAdData(
"IronSource",
"USD", // IronSource typically reports in USD
revenue
)
Singular.adRevenue(data)
Log.d("IronSource", "Ad revenue sent: $revenue USD")
}
import com.singular.sdk.Singular;
import com.singular.sdk.SingularAdData;
import com.ironsource.mediationsdk.impressionData.ImpressionData;
public void onImpressionDataSuccess(ImpressionData impressionData) {
// Validate impression data
if (impressionData == null) {
Log.d("IronSource", "No impression data available");
return;
}
// Extract and validate revenue
double revenue = (impressionData.getRevenue() != null) ?
impressionData.getRevenue().doubleValue() : 0.0;
if (revenue <= 0) {
Log.w("IronSource", "Invalid revenue: " + revenue);
return;
}
// Create and send ad revenue data
SingularAdData data = new SingularAdData(
"IronSource",
"USD", // IronSource typically reports in USD
revenue
);
Singular.adRevenue(data);
Log.d("IronSource", "Ad revenue sent: " + revenue + " USD");
}
Integración con TradPlus
Captura los ingresos por publicidad de la mediación de TradPlus usando el listener global de impresiones.
Requisitos:
-
Configura el listener global de impresiones mediante
TradPlusSdk.setGlobalImpressionListener() -
Maneja el callback
onImpressionSuccesspara recibir los datos de ingresos - Convierte el eCPM de miliunidades a moneda estándar (divide entre 1000)
Implementación
Registra un listener global de impresiones para rastrear todas las impresiones de anuncios y los ingresos.
import com.singular.sdk.Singular
import com.singular.sdk.SingularAdData
import com.tradplus.ads.mgr.GlobalImpressionManager
import com.tradplus.ads.base.bean.TPAdInfo
// Set global impression listener
TradPlusSdk.setGlobalImpressionListener(
object : GlobalImpressionManager.GlobalImpressionListener {
override fun onImpressionSuccess(tpAdInfo: TPAdInfo?) {
// Validate ad info
if (tpAdInfo == null) {
Log.w("TradPlus", "AdInfo is null")
return
}
// Convert eCPM from milli-units to dollars
val ecpm = tpAdInfo.ecpm ?: run {
Log.w("TradPlus", "eCPM is null")
return
}
val revenue = ecpm.toDouble() / 1000.0
// Validate revenue
if (revenue <= 0) {
Log.w("TradPlus", "Invalid revenue: $revenue")
return
}
// Create and send ad revenue data
val data = SingularAdData(
"TradPlus",
"USD",
revenue
)
Singular.adRevenue(data)
Log.d("TradPlus", "Ad revenue sent: $revenue USD")
}
}
)
import com.singular.sdk.Singular;
import com.singular.sdk.SingularAdData;
import com.tradplus.ads.mgr.GlobalImpressionManager;
import com.tradplus.ads.base.bean.TPAdInfo;
// Set global impression listener
TradPlusSdk.setGlobalImpressionListener(
new GlobalImpressionManager.GlobalImpressionListener() {
@Override
public void onImpressionSuccess(TPAdInfo tpAdInfo) {
// Validate ad info
if (tpAdInfo == null) {
Log.w("TradPlus", "AdInfo is null");
return;
}
// Validate eCPM is not null
if (tpAdInfo.getEcpm() == null) {
Log.w("TradPlus", "eCPM is null");
return;
}
// Convert eCPM from milli-units to dollars
double revenue = tpAdInfo.getEcpm().doubleValue() / 1000.0;
// Validate revenue
if (revenue <= 0) {
Log.w("TradPlus", "Invalid revenue: " + revenue);
return;
}
// Create and send ad revenue data
SingularAdData data = new SingularAdData(
"TradPlus",
"USD",
revenue
);
Singular.adRevenue(data);
Log.d("TradPlus", "Ad revenue sent: " + revenue + " USD");
}
}
);
Integración genérica (otras plataformas)
Integra cualquier plataforma de mediación usando la interfaz genérica
SingularAdData
.
Requisitos:
- Acceso a los datos de ingresos a nivel de impresión de tu plataforma de mediación
- Monto de ingresos en unidades de moneda estándar (no en micros)
- Código de moneda ISO 4217 (por ejemplo, USD, EUR, INR)
Precisión de los datos: Valida los datos de ingresos y moneda antes de enviar a Singular. Los datos incorrectos no pueden corregirse después del envío.
Implementación
Crea un objeto
SingularAdData
con el nombre de la plataforma, la moneda y los ingresos, y luego llama a
Singular.adRevenue()
.
import com.singular.sdk.Singular
import com.singular.sdk.SingularAdData
fun reportAdRevenue(adPlatform: String, currency: String, revenue: Double) {
// Validate revenue
if (revenue <= 0) {
Log.w("AdRevenue", "Invalid revenue: $revenue")
return
}
// Validate currency
if (currency.isEmpty()) {
Log.w("AdRevenue", "Invalid currency: $currency")
return
}
// Create ad revenue data object
val data = SingularAdData(
adPlatform,
currency,
revenue
)
// Send to Singular
Singular.adRevenue(data)
Log.d("AdRevenue", "Revenue sent: $revenue $currency from $adPlatform")
}
// Example usage
reportAdRevenue("MyMediationPlatform", "USD", 0.05)
import com.singular.sdk.Singular;
import com.singular.sdk.SingularAdData;
public void reportAdRevenue(String adPlatform, String currency, double revenue) {
// Validate revenue
if (revenue <= 0) {
Log.w("AdRevenue", "Invalid revenue: " + revenue);
return;
}
// Validate currency
if (currency == null || currency.isEmpty()) {
Log.w("AdRevenue", "Invalid currency: " + currency);
return;
}
// Create ad revenue data object
SingularAdData data = new SingularAdData(
adPlatform,
currency,
revenue
);
// Send to Singular
Singular.adRevenue(data);
Log.d("AdRevenue", "Revenue sent: " + revenue + " " + currency +
" from " + adPlatform);
}
// Example usage
reportAdRevenue("MyMediationPlatform", "USD", 0.05);
Enriquecer los datos de anuncios con atributos adicionales
SingularAdData expone setters encadenables para los metadatos a nivel de impresión. Úsalos para enriquecer el evento con detalles de placement, ad unit, agrupación de mediación y precisión cuando tu plataforma de mediación los proporcione. Los atributos establecidos mediante estos métodos se reflejan en los reportes de Singular y en los postbacks posteriores.
| Método | Descripción |
|---|---|
withNetworkName(String networkName)
|
Sobrescribe el nombre de la red (por defecto es la plataforma de anuncios pasada al constructor). Úsalo en la mediación cuando la red subyacente difiera de la plataforma de mediación. |
withAdType(String adType)
|
Formato del anuncio (por ejemplo,
"Rewarded"
,
"Interstitial"
,
"Banner"
).
|
withAdGroupType(String adGroupType)
|
Categorización del grupo de anuncios definida por tu plataforma de mediación. |
withImpressionId(String impressionId)
|
Identificador único de la impresión, utilizado para la deduplicación y conciliación. |
withAdPlacementName(String adPlacementName)
|
Nombre legible del placement (por ejemplo,
"level_complete"
).
|
withAdUnitId(String adUnitId)
|
Identificador del ad unit específico de la plataforma (por ejemplo,
"ca-app-pub-..."
para AdMob).
|
withAdUnitName(String adUnitName)
|
Nombre legible del ad unit. |
withAdGroupId(String adGroupId)
|
Identificador del grupo de anuncios de la plataforma de mediación. |
withAdGroupName(String adGroupName)
|
Nombre legible del grupo de anuncios. |
withAdGroupPriority(String adGroupPriority)
|
Prioridad asignada al grupo de anuncios en la cascada de mediación. |
withPrecision(String precision)
|
Indicador de precisión de los ingresos (por ejemplo,
"publisher_provided"
,
"estimated"
,
"exact"
) cuando la plataforma lo soporta.
|
withPlacementId(String placementId)
|
Identificador de placement específico de la plataforma. |
withLimitDataSharing(boolean shouldLimitDataSharing)
|
Sobrescribe el límite global de uso compartido de datos para este evento de anuncio en particular, por ejemplo cuando un usuario ha optado por no recibir publicidad personalizada. |
Ejemplo de uso en Kotlin:
val data = SingularAdData("AdMob", "USD", 0.05)
.withAdUnitId("ca-app-pub-123456789/1234567890")
.withAdType("Rewarded")
.withAdPlacementName("level_complete")
.withImpressionId("imp_abc123")
.withPrecision("publisher_provided")
Singular.adRevenue(data)
Ejemplo de uso en Java:
SingularAdData data = new SingularAdData("AdMob", "USD", 0.05)
.withAdUnitId("ca-app-pub-123456789/1234567890")
.withAdType("Rewarded")
.withAdPlacementName("level_complete")
.withImpressionId("imp_abc123")
.withPrecision("publisher_provided");
Singular.adRevenue(data);
Pruebas y validación
Verificar el reporte de ingresos
Prueba tu implementación de ingresos por publicidad para asegurarte de que los datos fluyan correctamente a Singular.
- Revisa los logs: Verifica que los logs del callback de ingresos aparezcan con los valores y la moneda correctos.
- Anuncios de prueba: Carga y muestra anuncios de prueba para activar los eventos de ingresos.
- Verificación en el dashboard: Confirma que los ingresos aparezcan en el dashboard de Singular dentro de las 24 horas.
- Precisión de los datos: Valida que los montos de ingresos coincidan con los reportes de tu plataforma de mediación.
Solución de problemas: Si los ingresos no aparecen en Singular, verifica que:
- La atribución de ingresos por publicidad esté habilitada en tu cuenta de Singular
- Los valores de ingresos sean mayores que 0
- Los códigos de moneda sean códigos ISO 4217 válidos
- El nombre de la plataforma coincida con el formato esperado por Singular