Integrating native cross-promo ads in an Android app
The Cross-Promo SDK surface is deliberately tiny: one endpoint returns ad metadata as JSON, two endpoints record what happened. Your app owns every pixel of the rendering.
1. Fetch ads
Authenticate with your tenant credentials (from the dashboard, under Settings) and ask for ads for the current app and platform:
GET /api/v1/ads?app_id=app_a&platform=android
X-Tenant-Id: tnt_…
X-Key: sdk_…
The response is plain metadata — up to three ads, weighted-random by campaign weight:
{
"ads": [{
"campaign_id": 12,
"creative_id": 34,
"title": "Calendar Planner",
"description": "The smartest way to organize your day.",
"icon_url": "https://…/icon.png",
"image_url": "https://…/banner.png",
"cta_text": "Install Now",
"destination_url": "https://play.google.com/store/apps/details?id=…"
}]
}
Empty inventory returns {"ads": []} with a 200 — hide the placement, never error.
2. Render natively
Because the payload is raw metadata, the ad is just another composable:
@Composable
fun CrossPromoCard(ad: Ad, onClick: () -> Unit) {
Row(Modifier.clickable(onClick = onClick).padding(16.dp)) {
AsyncImage(ad.iconUrl, null, Modifier.size(48.dp).clip(RoundedCornerShape(10.dp)))
Column(Modifier.padding(start = 12.dp).weight(1f)) {
Text(ad.title, style = MaterialTheme.typography.titleSmall)
Text(ad.description, style = MaterialTheme.typography.bodySmall, maxLines = 2)
}
Button(onClick) { Text(ad.ctaText) }
}
}
3. Track, then open
Fire the impression when the view becomes visible, the click when the CTA is tapped — then open
destination_url. Both calls are fire-and-forget; never block UI on them:
POST /api/v1/track/impression { "campaign_id": 12, "creative_id": 34, "source_app_id": "app_a", "platform": "android" }
POST /api/v1/track/click { …same body… }
Send back both campaign_id and creative_id — that is what powers per-campaign CTR in the
dashboard.
Edge cases worth handling
- 401/403 — credentials are wrong or rotated; disable the placement for the session.
- 429 — you hit the rate limit; back off, do not retry in a loop.
- Null
image_url— icon-only creatives are valid; design the card for both shapes.