Request Volume
System Health
Loading health…
Launch a CPI campaign in minutes. Upload a banner creative, set a daily budget, and AiMatrix auto-delivers installs across the network — with pacing, frequency caps, and per-install bid scoring tuned for games.
Drop the Cocos2d-x SDK into your game, register your app, and start earning from house ads across the AiMatrix network. Real-time eCPM, transparent revenue share, no minimum fill — built for Android, Cocos2d-x C++ first.
AiMatrix runs both sides of the house: Ads for advertisers buying installs and Revenue for publishers monetizing their games. Pick your side below.
Launch CPI campaigns. Manual bid, Target CPI, Target ROAS, or Max installs — you pick the strategy.
Drop in the Cocos2d-x SDK (or use the native Android / Java integration), register your app, start earning per install delivered. AdMob-style floor eCPM + optimize-for controls.
No account managers, no minimum commitment. From signup to first install, under 15 minutes.
Upload a banner creative, pick a bidding strategy (Manual CPI, Target CPI, Target ROAS, or Max Installs), set a daily budget. Targeting: country, device, OS version, game genre.
The network auto-bids on every eligible impression. Pacing, frequency caps, and install-prediction scoring run in the background — you watch the dashboard.
Billed on confirmed install events only. Real-time spend tracker, transparent eCPM and CVR per campaign. Pause, resume, or reallocate budget live.
Drop the SDK, register an app, get paid per install delivered. No minimum traffic, no approval queue.
Cocos2d-x 3.17.2 / 4.0, Android Java, Kotlin, or Jetpack Compose — one-line init, per-format APIs for banner, interstitial, rewarded, native, and icon ads.
Per-app floor eCPM and optimize-for preset (Revenue / Fill / Balanced) — AdMob-style knobs. Paid Event Listener streams per-impression revenue to your server.
70% revenue share by default, tunable per-publisher by admins. Real-time Earnings dashboard, per-app daily breakdown, precision-tagged revenue attribution.
Advertiser side looks like Google Ads. Publisher side looks like AdMob. Campaigns from one serve on the other's inventory — that's the network.
App developers drop the SDK into their game (5 platforms supported), register their app, and get an App ID in < 5 minutes. Earnings start the moment the first ad serves.
Game marketers create a CPI campaign with a creative + budget. Four bidding strategies cover manual bids all the way to fully-automated Max Installs.
Every impression on a publisher app runs through install-prediction scoring; the matching campaign serves and both sides get paid. No mediation, no waterfall.
Every feature below ships live today — no coming-soons, no beta flags.
Paste any Google Play Store URL — every ad demo below updates to show exactly what your campaign would look like on-device.
Native ads blend into your game's UI — card or list-item style — so they feel like part of the experience while still showing the required AD label for Google Play.
Rendered by the SDK using fields you provide: icon, headline, body and CTA.
Full-screen ads shown at natural breaks — between levels, after a game-over, or on app resume. High-impact placement with one-tap install and a visible close button.
Full device viewport, portrait or landscape. The AD label and × button are enforced by the SDK.
Opt-in full-screen ads that reward the player with in-game currency, extra lives, or hints. Highest eCPM in the network because players choose to watch them.
You define the reward (e.g. 50 gems) and the SDK fires a callback to your game once the ad completes.
Small square tiles rendered inside your game's "More games" screen or launcher. Low-intrusion, high-retention — a single tap takes the player to the Play Store.
Just the app icon. The SDK adds the AD chip so you stay compliant.
Sub-100ms ad decisions on every impression. Auctions run per impression, not per batch — so every slot is priced fairly.
Impressions, clicks, installs and revenue update the moment events hit the tracker. No overnight batches.
Revenue share is set per publisher and visible in your dashboard at all times. No hidden deductions.
Target by country, device, Android version, game genre, and session behaviour — all configurable per campaign.
Drop-in banner SDK for Cocos2d-x C++ on Android. A few lines of code — or a single Gradle dep plus a Java call — and your game is live on the network.
Every advertiser is reviewed. Click-fraud detection runs on every request so your inventory stays clean.
Launch user-acquisition campaigns with transparent CPI pricing, freq caps, pacing, and real-time spend reporting. No account managers, no minimums — just a dashboard and a daily budget.
Already publishing apps? Visit revenue.aimatrixnetwork.com to monetize — advertiser and publisher accounts are separate.
Drop the Cocos2d-x C++ SDK (or native Android Java integration), register your app, get an App ID. House ads from the AiMatrix advertiser pool start serving immediately, with per-install revenue share paid on delivery — no minimum traffic, no approval queue.
Buying installs instead? Visit ads.aimatrixnetwork.com — advertiser accounts live on a separate portal.
Launch user-acquisition campaigns with granular bidding and creative A/B testing.
Open Ads portal →Integrate the SDK, approve campaigns, and watch revenue build up in real time.
Open Revenue portal →One email, one side — advertiser or publisher. Pick during signup and we'll route you to the right portal.
Pick the side that matches how you'll use AiMatrix. You can't be on both — one account, one portal.
Paste your Play Store link — we fetch the app title + icon, add click-tracking, and report installs automatically. No API calls, no MMP postbacks to configure.
Paste your app's Play Store URL or package name — we'll fetch the title, icon, and description automatically.
Tune how this app earns.
Ad units tell the SDK which creative format to request. Pick a format below.
Move around without leaving the keyboard. Shortcuts ignore inputs + text fields — press Esc first if focus is inside one.
Loading health…
| Campaign | Status | Bid / Budget | Cost | Impr. | Clicks | CTR | Installs | Actions |
|---|
| Campaign | Status | Impr. | Clicks | CTR | Installs | CVR | Avg CPI | Cost | |
|---|---|---|---|---|---|---|---|---|---|
Select a date range above to load reports. | |||||||||
Pick an app from the selector above.
Ad units tie your SDK integration to a specific creative format (banner, interstitial, rewarded, etc.). Each unit gets its own ID that you plug into the SDK.
| App | Package | Category | Status | App ID | Settings |
|---|
| Date | App | Impressions | Clicks | eCPM | Revenue |
|---|---|---|---|---|---|
Loading earnings… | |||||
No publisher admin list endpoint yet
Publishers register via POST /api/auth/v1/auth/register with role=publisher.
No advertiser admin list endpoint yet
Advertisers register via POST /api/auth/v1/auth/register with role=advertiser.
Install attribution runs automatically on every campaign. Paste a Play Store URL when you create a campaign and the network handles click IDs, the Google Advertising ID handshake, the Play Install Referrer decoding, and the 24-hour click-to-install attribution window for you — no pixels, no MMP postbacks, no SDK required on your side.
/api/track/impression.click_id, records the click at /api/track/click, and bounces the user to Play Store with the click ID encoded in the referrer URL param.referrer value. When the user opens the advertised app for the first time, Play Store exposes that value via the Play Install Referrer Library./api/track/install with the original click_id. If the app doesn't have our SDK, attribution falls back to the Play Console Integration (same flow, different data source).install_id, debits your campaign's budget at the bid price, and updates the Campaigns / Reports pages within ~30 seconds.Click → install: 24 hours. An install that happens more than 24h after the click isn't attributed to your campaign (and you aren't charged).
Dedup: one attributed install per (click_id, install_id) pair. Re-installs of the same app on the same device count once.
Fraud guard: server-side signature on click_id prevents a third party from firing an install event for a click you didn't serve.
We don't receive PII, email, phone number, or the contents of the installed app.
If you want the Target ROAS bidding strategy to auto-tune against post-install events (IAPs, subscriptions, level completions), you'll need our SDK inside the advertised app so it can call RevenueTracker.trackPurchase() after each monetization event.
This is only needed for Target ROAS — Maximize Installs / Manual CPI / Target CPI work on raw install counts and don't need any SDK in the advertised app.
Integration details (same SDK the publisher side uses, every Android framework supported): open the Revenue portal → SDK Integration, or visit revenue.aimatrixnetwork.com. Your JWT cookie carries across — no re-login.
Once your campaign has been serving for an hour or two:
0 for more than a day while Clicks rise, ping support — usually means the Play Install Referrer isn't reaching our tracking endpoint.aimatrix/ into your game root, then add add_subdirectory(aimatrix) and target_link_libraries(${APP_NAME} aimatrix) to your CMakeLists.txt.
Cocos2d-x 3.17.2 uses ndk-build. Place aimatrix.a + headers under cocos2d/external/aimatrix/, then add LOCAL_WHOLE_STATIC_LIBRARIES += aimatrix_static to proj.android/app/jni/Android.mk.
Add the Maven dep: implementation 'com.aimatrixnetwork:sdk:1.0.0' in your app/build.gradle. Minimum SDK 21.
Same Maven dep as Java: implementation 'com.aimatrixnetwork:sdk:1.0.0'. Kotlin extensions are bundled — no extra artifact needed.
Same Maven dep plus the Compose artifact: implementation 'com.aimatrixnetwork:sdk-compose:1.0.0' exposes AiMatrixBanner, AiMatrixNativeAd, etc. as Composables.
#include "aimatrix/AiMatrix.h" // Once on app boot, e.g. in AppDelegate::applicationDidFinishLaunching. aimatrix::AiMatrix::init("YOUR_APP_ID"); // Size: BannerSize::BANNER_320_50 | MEDIUM_RECTANGLE | LEADERBOARD | SMART auto banner = aimatrix::AiMatrix::showBanner({ .size = aimatrix::BannerSize::SMART, .placement = "MainMenu_Bottom", .anchor = aimatrix::Anchor::Bottom, }); banner->onClick([]{ CCLOG("banner clicked"); });
#include "aimatrix/AiMatrix.h" // 3.17.2 calls look identical to 4.0 — the SDK API is the same. // Only the build glue differs: add to proj.android/app/jni/Android.mk: // LOCAL_WHOLE_STATIC_LIBRARIES += aimatrix_static // Once on app boot, e.g. in AppDelegate::applicationDidFinishLaunching. aimatrix::AiMatrix::init("YOUR_APP_ID"); aimatrix::Banner* banner = aimatrix::AiMatrix::showBanner({ aimatrix::BannerSize::SMART, "MainMenu_Bottom", aimatrix::Anchor::Bottom, }); banner->onClick([]{ CCLOG("banner clicked"); });
import com.aimatrixnetwork.sdk.AiMatrix; import com.aimatrixnetwork.sdk.Banner; import com.aimatrixnetwork.sdk.BannerSize; // In your Application.onCreate(): AiMatrix.init(this, "YOUR_APP_ID"); // Anywhere after: attach the banner to your Activity's root view. Banner banner = AiMatrix.showBanner(this, new Banner.Request() .size(BannerSize.SMART) .placement("MainMenu_Bottom") .anchor(Banner.Anchor.BOTTOM)); banner.setOnClickListener(() -> Log.d("AiMatrix", "banner clicked"));
import com.aimatrixnetwork.sdk.AiMatrix import com.aimatrixnetwork.sdk.BannerSize // In your Application.onCreate(): AiMatrix.init(this, "YOUR_APP_ID") // Anywhere after: attach the banner to your Activity's root view. val banner = AiMatrix.showBanner(this) { size = BannerSize.SMART placement = "MainMenu_Bottom" anchor = Banner.Anchor.BOTTOM } banner.onClick { Log.d("AiMatrix", "banner clicked") }
import com.aimatrixnetwork.sdk.compose.AiMatrixBanner import com.aimatrixnetwork.sdk.BannerSize // Drop the composable anywhere in your UI tree. The SDK handles // lifecycle + refresh internally; `AiMatrix.init()` should still // be called once in your Application.onCreate(). @Composable fun MainMenuScreen() { Column(Modifier.fillMaxSize()) { // ... your menu content ... Spacer(Modifier.weight(1f)) AiMatrixBanner( placement = "MainMenu_Bottom", size = BannerSize.SMART, onClick = { Log.d("AiMatrix", "banner clicked") }, ) } }
#include "aimatrix/AiMatrix.h" aimatrix::AiMatrix::loadNative({ .placement = "Feed_Card" }, [this](const aimatrix::NativeAd& ad) { // Render the ad inside your own Cocos2d-x UI nodes. auto sprite = Sprite::create(ad.iconPath); myCard.icon->setSpriteFrame(sprite->getSpriteFrame()); myCard.title->setString(ad.headline); myCard.body->setString(ad.description); myCard.cta->setString("Install"); ad.bindClick(myCard.node); });
#include "aimatrix/AiMatrix.h" // Same API as 4.0 — the SDK targets the older std::function+lambda // syntax too, so your 3.17.2 compiler (clang / gcc-4.9+) is fine. aimatrix::AiMatrix::loadNative( aimatrix::NativeRequest("Feed_Card"), [this](const aimatrix::NativeAd& ad) { auto sprite = Sprite::create(ad.iconPath); myCard.icon->setSpriteFrame(sprite->getSpriteFrame()); myCard.title->setString(ad.headline); myCard.body->setString(ad.description); myCard.cta->setString("Install"); ad.bindClick(myCard.node); });
import com.aimatrixnetwork.sdk.AiMatrix; import com.aimatrixnetwork.sdk.NativeAd; AiMatrix.loadNative(this, "Feed_Card", new NativeAd.Listener() { @Override public void onAdLoaded(NativeAd ad) { // Render inside your own view. The SDK returns assets only — // you're in full control of the layout + click surface. Glide.with(iconView).load(ad.getIconUrl()).into(iconView); titleView.setText(ad.getHeadline()); bodyView.setText(ad.getDescription()); ctaView.setText("Install"); rootView.setOnClickListener(v -> ad.onClick()); } @Override public void onAdFailed(String error) { Log.w("AiMatrix", error); } });
import com.aimatrixnetwork.sdk.AiMatrix import com.aimatrixnetwork.sdk.NativeAd AiMatrix.loadNative(this, "Feed_Card") { result -> result.onSuccess { ad: NativeAd -> Glide.with(iconView).load(ad.iconUrl).into(iconView) titleView.text = ad.headline bodyView.text = ad.description ctaView.text = "Install" rootView.setOnClickListener { ad.onClick() } }.onFailure { Log.w("AiMatrix", it.message.orEmpty()) } }
import com.aimatrixnetwork.sdk.compose.AiMatrixNativeAd // The Composable handles loading + rendering. Supply the layout // through the `content` lambda — the SDK exposes the loaded ad as // a receiver so you reference fields directly. @Composable fun FeedCard() { AiMatrixNativeAd(placement = "Feed_Card") { ad -> Row(Modifier.clickable { ad.onClick() }.padding(12.dp)) { AsyncImage(model = ad.iconUrl, contentDescription = null, modifier = Modifier.size(48.dp).clip(RoundedCornerShape(10.dp))) Column(Modifier.padding(start = 12.dp)) { Text(ad.headline, fontWeight = FontWeight.Bold) Text(ad.description, style = MaterialTheme.typography.bodySmall) } } } }
#include "aimatrix/AiMatrix.h" // Preload at level-start so there is zero delay when shown. aimatrix::AiMatrix::preloadInterstitial({ .placement = "LevelComplete" }); // Show when the level ends. if (aimatrix::AiMatrix::isInterstitialReady("LevelComplete")) { aimatrix::AiMatrix::showInterstitial("LevelComplete", [](aimatrix::AdResult r){ CCLOG("interstitial closed: %d", (int)r); }); }
#include "aimatrix/AiMatrix.h" // API identical to 4.0 — preload early, show when ready. aimatrix::AiMatrix::preloadInterstitial( aimatrix::InterstitialRequest("LevelComplete")); if (aimatrix::AiMatrix::isInterstitialReady("LevelComplete")) { aimatrix::AiMatrix::showInterstitial("LevelComplete", [](aimatrix::AdResult r) { CCLOG("interstitial closed: %d", (int)r); }); }
import com.aimatrixnetwork.sdk.AiMatrix; import com.aimatrixnetwork.sdk.Interstitial; // Preload at level-start so there is zero delay when shown. AiMatrix.preloadInterstitial(this, "LevelComplete"); // Show when the level ends. if (AiMatrix.isInterstitialReady("LevelComplete")) { AiMatrix.showInterstitial(this, "LevelComplete", new Interstitial.Listener() { @Override public void onClosed(Interstitial.Result r) { Log.d("AiMatrix", "interstitial closed: " + r); } }); }
import com.aimatrixnetwork.sdk.AiMatrix import com.aimatrixnetwork.sdk.Interstitial // Preload at level-start so there is zero delay when shown. AiMatrix.preloadInterstitial(this, "LevelComplete") // Show when the level ends. if (AiMatrix.isInterstitialReady("LevelComplete")) { AiMatrix.showInterstitial(this, "LevelComplete") { r: Interstitial.Result -> Log.d("AiMatrix", "interstitial closed: $r") } }
import com.aimatrixnetwork.sdk.compose.rememberAiMatrixInterstitial // rememberAiMatrixInterstitial preloads when the Composable enters // composition + disposes cleanly when it leaves. Call .show() when // you want to display (e.g. after a level-complete state flip). @Composable fun LevelScreen(state: LevelState) { val inter = rememberAiMatrixInterstitial(placement = "LevelComplete") LaunchedEffect(state.completed) { if (state.completed && inter.isReady) { inter.show() } } // ... your level UI ... }
#include "aimatrix/AiMatrix.h" aimatrix::AiMatrix::preloadRewarded({ .placement = "ExtraLife", .reward = { "gems", 50 }, }); // Show when the player taps "Watch ad for reward". aimatrix::AiMatrix::showRewarded("ExtraLife", [this](const aimatrix::RewardResult& r) { if (r.completed) { player->addGems(r.reward.amount); } });
#include "aimatrix/AiMatrix.h" aimatrix::RewardedRequest req("ExtraLife"); req.reward = aimatrix::Reward("gems", 50); aimatrix::AiMatrix::preloadRewarded(req); // Show when the player taps "Watch ad for reward". aimatrix::AiMatrix::showRewarded("ExtraLife", [this](const aimatrix::RewardResult& r) { if (r.completed) { player->addGems(r.reward.amount); } });
import com.aimatrixnetwork.sdk.AiMatrix; import com.aimatrixnetwork.sdk.Rewarded; import com.aimatrixnetwork.sdk.Reward; AiMatrix.preloadRewarded(this, new Rewarded.Request() .placement("ExtraLife") .reward(new Reward("gems", 50))); // Show when the player taps "Watch ad for reward". AiMatrix.showRewarded(this, "ExtraLife", new Rewarded.Listener() { @Override public void onRewarded(Reward r) { player.addGems(r.getAmount()); } @Override public void onClosed(boolean earned) { /* track */ } });
import com.aimatrixnetwork.sdk.AiMatrix import com.aimatrixnetwork.sdk.Reward AiMatrix.preloadRewarded(this) { placement = "ExtraLife" reward = Reward("gems", 50) } // Show when the player taps "Watch ad for reward". AiMatrix.showRewarded(this, "ExtraLife") { result -> if (result.completed) { player.addGems(result.reward.amount) } }
import com.aimatrixnetwork.sdk.compose.rememberAiMatrixRewarded import com.aimatrixnetwork.sdk.Reward @Composable fun ExtraLifeButton(onRewarded: (Reward) -> Unit) { val rewarded = rememberAiMatrixRewarded( placement = "ExtraLife", reward = Reward("gems", 50), ) Button( enabled = rewarded.isReady, onClick = { rewarded.show { r -> if (r.completed) onRewarded(r.reward) } }, ) { Text("Watch ad · earn 50 gems") } }
#include "aimatrix/AiMatrix.h" // Returns up to N icon ads for a "More games" grid. aimatrix::AiMatrix::loadIconAds({ .placement = "MoreGames", .count = 3, }, [this](const std::vector<aimatrix::IconAd>& ads) { for (size_t i = 0; i < ads.size(); ++i) { // Icon-only — no text, just the tile sprite. auto sprite = Sprite::create(ads[i].iconPath); grid.tiles[i].icon->setSpriteFrame(sprite->getSpriteFrame()); ads[i].bindClick(grid.tiles[i].node); } });
#include "aimatrix/AiMatrix.h" aimatrix::IconRequest req("MoreGames", 3); aimatrix::AiMatrix::loadIconAds(req, [this](const std::vector<aimatrix::IconAd>& ads) { for (size_t i = 0; i < ads.size(); ++i) { auto sprite = Sprite::create(ads[i].iconPath); grid.tiles[i].icon->setSpriteFrame(sprite->getSpriteFrame()); ads[i].bindClick(grid.tiles[i].node); } });
import com.aimatrixnetwork.sdk.AiMatrix; import com.aimatrixnetwork.sdk.IconAd; import java.util.List; AiMatrix.loadIconAds(this, "MoreGames", 3, new IconAd.Listener() { @Override public void onAdsLoaded(List<IconAd> ads) { for (int i = 0; i < ads.size(); i++) { IconAd ad = ads.get(i); Glide.with(tileIcons[i]).load(ad.getIconUrl()).into(tileIcons[i]); tileIcons[i].setOnClickListener(v -> ad.onClick()); } } });
import com.aimatrixnetwork.sdk.AiMatrix import com.aimatrixnetwork.sdk.IconAd AiMatrix.loadIconAds(this, placement = "MoreGames", count = 3) { ads: List<IconAd> -> ads.forEachIndexed { i, ad -> Glide.with(tileIcons[i]).load(ad.iconUrl).into(tileIcons[i]) tileIcons[i].setOnClickListener { ad.onClick() } } }
import com.aimatrixnetwork.sdk.compose.AiMatrixIconGrid @Composable fun MoreGamesGrid() { AiMatrixIconGrid(placement = "MoreGames", count = 3) { ads -> LazyRow(horizontalArrangement = Arrangement.spacedBy(10.dp)) { items(ads) { ad -> AsyncImage( model = ad.iconUrl, contentDescription = null, modifier = Modifier.size(72.dp) .clip(RoundedCornerShape(16.dp)) .clickable { ad.onClick() }, ) } } } }
#include "aimatrix/AiMatrix.h" // Fires once per revenue-earning impression. Mirrors AdMob's // OnPaidEventListener: currency, value, precision, ad source + // format. SDK auto-POSTs to /track/paid-event; this callback // lets you mirror the event locally (MMP, analytics, ...). aimatrix::AiMatrix::setPaidEventListener( [](const aimatrix::PaidEvent& evt) { CCLOG("paid: impression=%s value=%.4f %s precision=%d fmt=%s", evt.impressionId.c_str(), evt.value, evt.currency.c_str(), evt.precision, evt.adFormat.c_str()); // Optional: forward to AppsFlyer / Adjust via their JNI bridges. aimatrix::AiMatrix::forwardToMMP("appsflyer", evt); });
#include "aimatrix/AiMatrix.h" // Same API as 4.0 — std::function callback. aimatrix::AiMatrix::setPaidEventListener( [](const aimatrix::PaidEvent& evt) { CCLOG("paid: %s %.4f %s", evt.impressionId.c_str(), evt.value, evt.currency.c_str()); aimatrix::AiMatrix::forwardToMMP("appsflyer", evt); });
import com.aimatrixnetwork.sdk.AiMatrix; import com.aimatrixnetwork.sdk.PaidEvent; // Register once, typically in Application.onCreate() after init(). // SDK auto-POSTs the event server-side; this callback mirrors it // locally so you can forward to AppsFlyer / Adjust / Branch. AiMatrix.setPaidEventListener(new PaidEvent.Listener() { @Override public void onPaidEvent(PaidEvent evt) { Log.d("AiMatrix", String.format( "paid: impression=%s value=%.4f %s precision=%d fmt=%s", evt.getImpressionId(), evt.getValue(), evt.getCurrency(), evt.getPrecision(), evt.getAdFormat())); AiMatrix.forwardToMMP("appsflyer", evt); } });
import com.aimatrixnetwork.sdk.AiMatrix import com.aimatrixnetwork.sdk.PaidEvent // Called once per revenue-earning impression. SDK auto-POSTs // the event to /track/paid-event; this listener mirrors it // locally so you can forward to AppsFlyer / Adjust / Branch. AiMatrix.setPaidEventListener { evt: PaidEvent -> Log.d("AiMatrix", "paid: impression=${evt.impressionId} " + "value=${evt.value} ${evt.currency} " + "precision=${evt.precision} fmt=${evt.adFormat}") AiMatrix.forwardToMMP("appsflyer", evt) }
import com.aimatrixnetwork.sdk.compose.rememberAiMatrixPaidEvents import androidx.compose.runtime.collectAsState // rememberAiMatrixPaidEvents exposes the paid-event stream as a // Compose State<PaidEvent?>. Useful for showing a "you earned // ₹X" toast, a running revenue counter, or whatever your UI needs. // The server-side POST still happens automatically inside the SDK. @Composable fun RevenueBadge() { val last by rememberAiMatrixPaidEvents() last?.let { evt -> Text( text = "+${evt.currency} %.4f".format(evt.value), style = MaterialTheme.typography.labelSmall, ) } }