Keewano Unity SDK
Loading...
Searching...
No Matches
Ad Revenue

Overview

Ad revenue tracking allows you to monitor monetization from advertisements shown in your game. The Keewano SDK provides dedicated methods to track ad offers, revenue generated from ads, and virtual items granted as rewards (e.g., from rewarded video ads).

Note
Best Practice: Use Ad Network Callbacks
Always call ad revenue tracking methods from the revenue callbacks provided by your ad serving SDK (IronSource, Google AdMob, Unity Ads, etc.). These callbacks contain accurate revenue data from the ad network. Never estimate or hardcode revenue values.

Ad Revenue vs IAP

It's important to understand the distinction between different types of monetization in your game:

  • Ad Revenue: Revenue from displaying ads (tracked with ReportAdRevenue)
  • Ad Item Grants: Virtual items granted as rewards for watching ads (tracked with ReportAdItemsGranted)
  • In-App Purchases (IAP): Real money purchases (see In-App Purchases)

For example:

  • Player watches a rewarded video ad that generates $0.05 revenue → Ad Revenue
  • Player receives 100 Coins as reward for watching the ad → Ad Item Grant
  • Player buys "500 Crystals Pack" for $4.99 → IAP (see In-App Purchases)

Tracking Ad Offer Acceptance Rate

Use KeewanoSDK.ReportAdOffered() to track when an ad opportunity is presented to the player (e.g., "Watch ad for reward?" dialog). This allows you to measure ad acceptance rates by comparing how many players were offered an ad vs how many actually watched it.

Ad Revenue Tracking

ReportAdRevenue - Track the Ad Revenue

Use KeewanoSDK.ReportAdRevenue() to log the revenue generated from displaying an advertisement.

All revenue is stored in USD on Keewano servers. Choose one of the two exclusive options:

  • Full Precision

    Pass the revenue amount with currency code for full precision:

    // Sub-cent USD precision (e.g., $0.005 for half a cent)
    KeewanoSDK.ReportAdRevenue(placementId, 0.005f, "USD");
    // Or non-USD currency
    KeewanoSDK.ReportAdRevenue(placementId, 0.05f, "EUR");
    Definition KeewanoSDK.cs:18
    static void ReportAdRevenue(string placement, uint revenueUsdCents)
    Reports an ad revenue event.
    Definition KeewanoSDK.cs:434
    Note
    Currency codes must follow ISO 4217. Unrecognized codes are treated as USD. USD values are stored as-is without conversion.
    Warning
    For non-USD currencies, different analytics systems use different exchange rate sources and conversion timing. If you use multiple analytics tools, each may report slightly different revenue figures.
  • Quick & Simple

    Convenient shorthand when your ad network already provides revenue in whole USD cents:

    // After ad impression - pass revenue in whole USD cents
    KeewanoSDK.ReportAdRevenue(placementId, revenueInUsdCents);

When to call:

  • ONLY after receiving the revenue callback from your ad serving SDK (IronSource, AdMob, Unity Ads, etc.)
  • NEVER estimate or hardcode revenue values

Step 2: ReportAdItemsGranted - Track Rewarded Ad Items

Use KeewanoSDK.ReportAdItemsGranted() to log the virtual items or currencies granted to the player for watching an advertisement (typically rewarded video ads).

// After player watches rewarded ad and receives items
Keewano.Item[] rewardItems = { new Keewano.Item("Coins", 100) };
KeewanoSDK.ReportAdItemsGranted(placementId, rewardItems);
static void ReportAdItemsGranted(string placement, Item[] items)
Reports items granted from watching an advertisement.
Definition KeewanoSDK.cs:469
Definition KBatch.cs:6
Represents a game item with a unique identifier and a quantity.
Definition KeewanoItems.cs:11

Parameters:

  • placement - The same ad placement identifier used in ReportAdRevenue
  • items - Array of items granted (can also use ReadOnlySpan<Item> for zero-copy performance)

When to call:

  • ONLY after items are successfully granted to the player's account
  • When the player receives in-game items/currency for watching the ad

Placement Naming Best Practices

Use Game-Specific Context, Not Ad Types

Placement names should describe where in your game and why the ad was shown, not just the ad format type.

Use descriptive game-context names:

// Describes WHERE and WHY the ad was shown
KeewanoSDK.ReportAdRevenue("OutOfEnergyPrompt_WatchForRefill", 15);
KeewanoSDK.ReportAdRevenue("LevelFailed_WatchFor5Moves", 12);
KeewanoSDK.ReportAdRevenue("MainMenu_DailyBonusOffer", 10);
KeewanoSDK.ReportAdRevenue("LevelComplete_NextLevelTransition", 8);

Avoid generic ad-type names:

KeewanoSDK.ReportAdRevenue("rewarded_video", 15); // ❌ Too generic
KeewanoSDK.ReportAdRevenue("interstitial", 8); // ❌ No context
KeewanoSDK.ReportAdRevenue("banner", 3); // ❌ Unclear purpose

Placement Naming Examples

Game Context Bad Name Good Name
Out of energy popup offering ad to refill "rewarded_video" "OutOfEnergyPrompt_WatchForRefill"
Level failed, offering 5 more moves "rewarded" "LevelFailed_WatchFor5Moves"
Level failed, offering continue from checkpoint "video_ad" "LevelFailed_ContinueFromCheckpoint"
Ad shown between levels "interstitial" "LevelComplete_Transition"
Daily bonus popup offering double rewards "rewarded_video_2" "DailyBonus_DoubleReward"
Shop popup offering free coins "ad_1" "Shop_WatchForFreeCoins"
Main menu banner "banner" "MainMenu_TopBanner"
Pause menu offering revive "pause_ad" "PauseMenu_ReviveOffer"

Keep Placement Names Static

Important: Don't include dynamic values like level numbers, player IDs, or timestamps in placement names.

Don't do this:

// BAD: Including level number in placement name
KeewanoSDK.ReportAdRevenue($"Level_{levelNumber}_Failed_Watch5Moves", revenue);
KeewanoSDK.ReportAdRevenue($"LevelComplete_{levelNumber}_Transition", revenue);

Do this instead:

// GOOD: Static placement name with context from custom events
KeewanoSDK.ReportLevelStart(5); // Custom event - establishes level context
// ... gameplay ...
// Player runs out of moves, watches ad for 5 more moves
KeewanoSDK.ReportAdRevenue("LevelFailed_Watch5Moves", revenue); // Static name
Keewano.Item[] moves = { new Keewano.Item("Moves", 5) };
KeewanoSDK.ReportAdItemsGranted("LevelFailed_Watch5Moves", moves); // Grant the moves
// ... player continues with extra moves ...
KeewanoSDK.ReportLevelEnd(5); // Custom event - marks level completion

Why? The Keewano SDK maintains an ordered event stream for each player. When you report ReportLevelStart(5), the AI Agents know the player is in level 5. Any events that follow (including ad views) are automatically associated with level 5 until you report ReportLevelEnd(5). There's no need to repeat the level number in every event.

This "context-first" approach means:

  • Report game state changes with custom events (level start/end, entering shop, etc.)
  • Use static placement names that describe the UI location and purpose
  • Let the Keewano AI automatically correlate ad views with the surrounding game context
See also
Custom Events for information on defining custom events like ReportLevelStart, ReportLevelEnd, etc.

Why Context Matters

Using game-specific placement names allows the Keewano AI Agents to:

  • Understand which ad placements perform best in specific game contexts
  • Identify which player actions lead to ad views
  • Analyze the relationship between ad placements and player progression
  • Correlate ad viewing behavior with churn, retention, and monetization

For example, seeing that "LevelFailed_Watch5Moves" has high engagement but "LevelComplete_Transition" has low engagement tells you meaningful information about your game design and player motivation.

Why Are Revenue and Item Grants Separate?

ReportAdRevenue and ReportAdItemsGranted are separate because not all ads grant items:

  1. Interstitial Ads Between Levels: Generate revenue but don't grant items
  2. Banner Ads: Generate revenue but don't grant items
  3. Ads With Rewards: Generate revenue AND grant items - call both methods
  4. Asynchronous Rewards: Ad completes → revenue tracked → items granted later by server

Common Scenarios

Scenario 1: Interstitial Ad Between Levels (No Reward)

Very common in casual games - ads shown during level transitions that generate revenue but don't reward the player.

const string PLACEMENT = "LevelComplete_Transition";
void OnLevelComplete(int levelNumber)
{
// Track that we're about to show an interstitial
KeewanoSDK.ReportAdOffered(PLACEMENT, Keewano.AdType.Interstitial);
// Player completed level, show interstitial ad before next level
ShowInterstitialAd();
}
// Ad network callback
void OnInterstitialAdShown(float revenueUsd)
{
// Only report revenue - player gets nothing for watching
KeewanoSDK.ReportAdRevenue(PLACEMENT, revenueUsd, "USD");
// NO ReportAdItemsGranted call - this ad doesn't reward anything
}
static void ReportAdOffered(string placement, Keewano.AdType adType)
Reports that an ad opportunity was offered to the user.
Definition KeewanoSDK.cs:417

Scenario 2: Out of Energy - Watch to Refill

Player runs out of energy, popup offers to watch ad to refill. This example shows the full funnel: Offered → Watched → Items Granted.

// Use the same placement string across all methods to link them together
const string PLACEMENT = "OutOfEnergy_WatchForRefill";
void OnOutOfEnergy()
{
// Track that we offered the ad
KeewanoSDK.ReportAdOffered(PLACEMENT, Keewano.AdType.Rewarded);
// Show popup: "Out of energy! Watch ad to refill?"
ShowRewardedAdOffer();
}
// Ad network callback - only called if player watched the ad
void OnOutOfEnergyAdCompleted(float revenueUsd)
{
// Report revenue - use local currency for sub-cent precision
KeewanoSDK.ReportAdRevenue(PLACEMENT, revenueUsd, "USD");
// Grant energy to the player
Keewano.Item[] rewardItems = { new Keewano.Item("Energy", 5) };
KeewanoSDK.ReportAdItemsGranted(PLACEMENT, rewardItems);
}

Scenario 3: Level Failed - Watch for Extra Moves

Common in Match-3 games - player fails level, offered extra moves to continue.

const string PLACEMENT = "LevelFailed_WatchFor5Moves";
void OnLevelFailed(int levelNumber)
{
// Track that we offered the ad
KeewanoSDK.ReportAdOffered(PLACEMENT, Keewano.AdType.Rewarded);
// Show popup: "Level failed! Watch ad for 5 more moves?"
ShowRewardedAdOffer();
}
// Ad network callback
void OnLevelFailedAdCompleted(float revenueUsd)
{
// Report revenue
KeewanoSDK.ReportAdRevenue(PLACEMENT, revenueUsd, "USD");
// Grant 5 moves and let player continue
Keewano.Item[] moves = { new Keewano.Item("Moves", 5) };
KeewanoSDK.ReportAdItemsGranted(PLACEMENT, moves);
}

Scenario 4: Daily Bonus - Watch to Double Reward

Player opens daily bonus, can watch ad to double the reward.

const string PLACEMENT = "DailyBonus_DoubleReward";
void OnDailyBonusPopup()
{
// Track that we offered the ad
KeewanoSDK.ReportAdOffered(PLACEMENT, Keewano.AdType.Rewarded);
// Show popup: "Daily bonus: 50 coins. Watch ad to double it!"
ShowRewardedAdOffer();
}
// Ad network callback
void OnDailyBonusAdCompleted(float revenueUsd)
{
// Report revenue
KeewanoSDK.ReportAdRevenue(PLACEMENT, revenueUsd, "USD");
// Grant doubled reward
Keewano.Item[] doubledReward = { new Keewano.Item("Coins", 100) }; // 50 * 2
KeewanoSDK.ReportAdItemsGranted(PLACEMENT, doubledReward);
}

Scenario 5: Main Menu Banner (No Reward)

Banner ad shown in main menu that generates revenue but doesn't grant anything.

const string PLACEMENT = "MainMenu_TopBanner";
void OnMainMenuShown()
{
// Track that we're showing a banner
KeewanoSDK.ReportAdOffered(PLACEMENT, Keewano.AdType.Banner);
ShowBannerAd();
}
// Ad network callback
void OnBannerAdImpression(float revenueUsd)
{
// Only report revenue - banners don't grant items
KeewanoSDK.ReportAdRevenue(PLACEMENT, revenueUsd, "USD");
}

Scenario 6: Shop - Watch for Free Coins

Player in shop, can watch ad to get free coins.

const string PLACEMENT = "Shop_WatchForFreeCoins";
void OnShopOpened()
{
// Track that we offered the ad (button is now visible)
KeewanoSDK.ReportAdOffered(PLACEMENT, Keewano.AdType.Rewarded);
}
void OnWatchForCoinsButtonClicked()
{
ShowRewardedAd();
}
// Ad network callback
void OnShopAdCompleted(float revenueUsd)
{
KeewanoSDK.ReportAdRevenue(PLACEMENT, revenueUsd, "USD");
Keewano.Item[] freeCoins = { new Keewano.Item("Coins", 50) };
KeewanoSDK.ReportAdItemsGranted(PLACEMENT, freeCoins);
}
static void ReportWindowOpen(string windowName)
Reports a window/popup open event.
Definition KeewanoSDK.cs:309

Scenario 7: Multiple Item Rewards

When a rewarded ad grants multiple different items.

const string PLACEMENT = "SpecialOffer_BonusReward";
void OnSpecialOfferPopup()
{
// Track that we offered the ad
KeewanoSDK.ReportAdOffered(PLACEMENT, Keewano.AdType.Rewarded);
ShowRewardedAdOffer();
}
// Ad network callback
void OnSpecialOfferAdCompleted(float revenueUsd)
{
KeewanoSDK.ReportAdRevenue(PLACEMENT, revenueUsd, "USD");
// Grant multiple rewards
Keewano.Item[] bonusRewards = {
new Keewano.Item("Coins", 200),
new Keewano.Item("Energy", 10),
new Keewano.Item("Booster_Hammer", 1)
};
KeewanoSDK.ReportAdItemsGranted(PLACEMENT, bonusRewards);
}

Best Practices

Always Use Ad Network Callbacks

NEVER do this:

// BAD: Hardcoding revenue estimates
void OnAdShown()
{
// This is inaccurate and will corrupt your revenue analytics!
KeewanoSDK.ReportAdRevenue("LevelComplete_Transition", 10); // ❌ Hardcoded estimate
}

ALWAYS do this:

// GOOD: Using actual revenue from your ad network's callback
void OnAdImpressionCallback(float revenueUsd)
{
const string PLACEMENT = "LevelComplete_Transition";
// Use the actual revenue provided by the ad network
KeewanoSDK.ReportAdRevenue(PLACEMENT, revenueUsd, "USD");
}

Only Call ReportAdItemsGranted When Items Are Granted

Not all ads grant items to the player - it depends on your game logic:

// ✅ CORRECT: Ad with no reward
void OnAdCompleted(float revenueUsd)
{
KeewanoSDK.ReportAdRevenue("LevelComplete_Transition", revenueUsd, "USD");
// NO ReportAdItemsGranted - player gets nothing for this ad
}
// ✅ CORRECT: Ad that grants items
void OnAdWithRewardCompleted(float revenueUsd)
{
const string PLACEMENT = "LevelFailed_Watch5Moves";
KeewanoSDK.ReportAdRevenue(PLACEMENT, revenueUsd, "USD");
Keewano.Item[] items = { new Keewano.Item("Moves", 5) };
KeewanoSDK.ReportAdItemsGranted(PLACEMENT, items); // Player gets reward
}

Use Consistent Placement Names

Use the same placement name for all methods:

void OnAdCompleted(float revenueUsd)
{
const string PLACEMENT = "LevelFailed_WatchFor5Moves";
KeewanoSDK.ReportAdRevenue(PLACEMENT, revenueUsd, "USD");
Keewano.Item[] items = { new Keewano.Item("Moves", 5) };
KeewanoSDK.ReportAdItemsGranted(PLACEMENT, items); // Same placement
}

Only Report Actually Granted Items

Only call ReportAdItemsGranted() when items are successfully added to the player's account:

void OnAdCompleted(float revenueUsd)
{
const string PLACEMENT = "LevelFailed_Watch5Moves";
KeewanoSDK.ReportAdRevenue(PLACEMENT, revenueUsd, "USD");
Keewano.Item[] items = { new Keewano.Item("Moves", 5) };
bool itemsGranted = AddRewardToPlayerInventory(items);
if (itemsGranted)
{
// Only report if grant succeeded
KeewanoSDK.ReportAdItemsGranted(PLACEMENT, items);
}
}

String Parameter Limits

Placement IDs and item names are limited to 255 characters and will be trimmed if longer. Empty or null strings will skip the event.

See Also