Unity SDK
Overview
The Metica Unity SDK offers a straightforward interface for interacting with the Metica backend API from your Unity game directly. The SDK provides simplified methods to fetch offers and smart configs (abbreviated as configs), and to log user actions within your app or game as events. The Metica Unity SDK takes care of networking nuance, caching and much more so you don't have to.
Terminology
Application Your application or game that uses the Metica services.
User A user or player of the application. Player and user are used interchangeably.
Event An
event
refers to a user's action within the context of the application. For example, clicking a button, logging in, clicking an ad, etc. The properties (or attributes) associated with these events vary based on the type of the event; e.g., the propertytotalAmount
must be set when logging an in-app offerpurchase
event.User Properties Sometimes (and formerly) called User Attributes, user properties consist of general information about the user that best characterises them in your application. For example you could define your user properties to include game progression, demographics, user preferences, player's level, etc.
What you need
To use the Metica Unity SDK you need:
An
API key
, obtainable in the Metica platformAn
appId
, obtainable in the Metica platform.
Installation
In Unity, open the Package Manager (Window > Package Manager) and click on the '+' button in the top left corner. Select "Add package from git URL..." and enter the following:
https://github.com/meticalabs/metica-unity-sdk.git
How to use the Metica SDK
The recommended way to use the SDK is through MeticaSdk
which offers async
/await
methods alongside coroutine
ones.
For backwards compatibility the old deprecated mechanism is still available which has only the coroutine approach: MeticaAPI
You can retrieve an instance of IMeticaSdk
with
private IMeticaSdk _sdk = MeticaSdk.SDK;
If you do so, you can now take advantage of the asynchronous calls. Example:
configResult = await _sdk.GetConfigsAsync(new List<string> { "dynamic_difficulty" });
Setup
In Unity's Hierarchy View, right click (on an empty area) and select
Metica > Add SDK
. This will add a prefab with the MeticaUnitySdk component attached (if not already in scene). Alternatively you can manually drag and drop the prefab fromPackages/Metica Unity Sdk/Runtime/Unity/Prefabs/
.Select the prefab and click the
Create Configuration
button to create and save it in the folder you select.*Select the configuration file and fill the fields (see SDK Configuration)
If needed, add the file to the MeticaSdk prefab. When you use the Create Configuration button the configuration should be automatically linked.
*: Alternatively, create a configuration asset by right-clicking a folder in the Project View and selecting Create > Metica > SDK > New SDK Configuration
. This can also be found in the main menu under Assets > Create > Metica
but it will create the asset in the Assets' root.
SDK Configuration
The SDK configuration exposes the following parameters:
apiKey
Your API key
appId
The application identifier accessible from Metica's dashboard.
initialUserId
A string that identifies a user. This can change during the lifetime of your app/game so, for example and depending on your needs, this could be a temporary id like "guest" that later becomes a specific userId, or it can be the current user's id if it's already identified.
Base Endpoint
Base metica endpoint : https://api-gateway.prod-eu.metica.com
Events Log Dispatch Cadence
The cadence, in seconds, that triggers an events dispatch.
displayLogFlushCadence
The number of stored events above which they are dispecthed (actually sent to Metica). Events in fact don't get always sent immediately, they accumulate and get sent in bulks.
Events Log Dispatch Cadence
The cadence, in seconds, by which the logged events will be sent to the ingestion service.
Events Log Dispatch Max Queue Size
The maximum number of pending logged events before they are sent to the ingestion service. When this value is reached, oldest accumulated events will be dropped to accommodate most recent ones.
Http Cache TTL Seconds
The time-to-live, in seconds, for the http-level cache.
Http Request Timeout
The network timeout, in seconds, for the calls to any Metica endpoint.
Log Level
The level of the SDK's logs. Do not confuse this with the meaning Log in the context of event logging. The valid values are provided by the enumeration Metica.SDK.LogLevel
and determine the verbosity of the logs with Info
being the most verbose and Debug
being the least verbose. Off
suppresses all logging.
Offers
Asynchronously fetches offers for specified (or all) placements from the Metica API. The result consists of a dictionary of placements with their respective offers.
A dictionary of user attributes can be passed to the method to personalize the offers. If not, then the last known user attributes are used.
Also, a DeviceInfo
object (see Device Info) can be passed to the method to provide device information. If not, then the device information is automatically collected.
Signature
Task<OfferResult> GetOffersAsync(string[] placements, Dictionary<string, object> userData = null, DeviceInfo deviceInfo = null);
Example
var offers = await _sdk.GetOffersAsync(
configKeys: new string[] { "placement1", "placement2" },
userProperties: {
{ "someAttribute", true },
{ "another", "someValue" }
},
deviceInfo: new DeviceInfo()
{
appVersion = "1.0.0",
timezone = "UTC",
locale = "en_US",
store = "AppStore"
});
);
Log.Debug(() => $"Offers: {offersResult}");
Smart Configs
The GetConfig
method can be used to retrieve the Smart Configs.
Similar to the GetOffers
method, the operation is performed asynchronously.
Because the result is specific to each application, the SDK represents it in a generic manner, through an Dictionary<string, object>
instance.
Each entry in the dictionary represents a configuration key and its value. The latter is expected to be valid json.
Also, again similar to the GetOffers
method, the operation can be passed a dictionary of user properties and the device details, as a DeviceInfo
instance (see Device Info), in order to personalise the returned configuration. The personalisation happens on the server side, based on the configured variations and experimentation setup.
Signature
Task<ConfigResult> GetConfigsAsync(List<string> configKeys = null, Dictionary<string, object> userData = null, DeviceInfo deviceInfo = null);
Example
var configResult = await _sdk.GetConfig(
configKeys: new string[] { "key1", "key2" },
responseCallback: result => {
if (result.Error == null)
{
Debug.Log(result.Result.Configs["key1"]);
} else
{
Debug.Log("Failed to get offers: " + result.Error);
}
},
userProperties: {
{ "someAttribute", true },
{ "another", "someValue" }
},
deviceInfo: new DeviceInfo()
{
appVersion = "1.0.0",
timezone = "UTC",
locale = "en_US",
store = "AppStore"
});
Log.Debug(() => $"Configs: {configResult}");
If the configKeys
argument is null
or empty, then all the configured keys will be returned.
Note that the server side response for this call is going to be cached according to the cache control directives returned by the server.
Device Info
The DeviceInfo
stores information regarding the host device, and it can differ across different devices of the same user.
Note that leaving this variable to null
is perfectly fine as it will trigger a device detector that is internal to the SDK
An overview of the role of each DeviceInfo
property:
store
string
Identifies the app store related to the in-game offers. Possible values:
- GooglePlayStore
, the Google store
- AppStore
, the Apple store
GooglePlayStore
locale
string
Locale expressed as a combination of language (ISO 639) and country (ISO 3166) JDK 8 standard reference.
en-US
Events Ingestion
This section explains how to ingest events from the game into Metica. Here is a list of methods that deliver these events to Metica, and following their signatures should be sufficient for an SDK developer. Additional details about them can also be found here.
Offer Lifecycle Events
Logs offer related events like offer display, offer purchase, and offer interaction.
All these events have two signatures: one with and one without productId
. If the offer linked to the event was generated by Metica, the method without ProductId
should be used. Conversely, if the offer is a game offer created internally within the game, the method with ProductId
must be used, passing the relevant productId (any internal string representing it) in the method.
Examples:
void LogOfferImpressionEvent(string placementId, string offerId, Dictionary<string, object> customPayload = null);
void LogOfferImpressionEventWithProductId(string productId, Dictionary<string, object> customPayload = null);
void LogOfferInteractionEvent(string placementId, string offerId, string interactionType, Dictionary<string, object> customPayload = null);
void LogOfferInteractionEventWithProductId(string productId, string interactionType, Dictionary<string, object> customPayload = null);
void LogOfferPurchaseEvent(string placementId, string offerId, string currencyCode, double totalAmount, Dictionary<string, object> customPayload = null);
void LogOfferPurchaseEventWithProductId(string productId, string currencyCode, double totalAmount, Dictionary<string, object> customPayload = null);
Full State Update
LogFullStateUpdate
sends a complete snapshot of the user's state to the server, replacing any previously stored data.
Please note that this method fully resets the user's state on the server and expects all relevant state information to be included in the request.
Any user attributes that are currently stored in the server with the given userId
but are not sent with this update, will be erased.
Dictionary<string, object> userAttributes = new Dictionary<string, object> { { "level", 25 }, { "favoriteItem", "shield" } };
_sdk.LogFullStateUserUpdateEvent(userAttributes);
Partial State Update
LogPartialStateUpdate
sends a partial update of the user's state to the server,
modifying or adding only the provided fields while preserving those that are currently stored on the server.
This method cannot erase existing fields (like LogFullStateUpdate
does); it can only overwrite values or introduce new ones.
Dictionary<string, object> userAttributes = new Dictionary<string, object> { { "level", 26 } };
_sdk.LogPartialStateUserUpdateEvent(userAttributes)
Custom Event Logging
LogCustomEvent
logs custom application events. The only required field in this dictionary is eventType
, which Metica uses to classify the different types of events your application sends.
Dictionary<string, object> customUserEvent = new Dictionary<string, object> { { "eventType", "completed_level" }, { "eventDetails", "level 5" } };
_sdk.LogCustomEvent(userEvent);
Note: The final event that is submitted to the Metica backend is enriched with additional information that's gathered by the SDK. See Base Fields for further information. In a scenario where you weren't using Metica SDK you'd have to code your game/app so these fields are always included.
// this will avoid the extra allocation but will mutate the passed userEvent
_sdk.LogCustomEvent(customEventType, true);
Custom Payloads
All events, except fullStateUpdate
, partialStateUpdate
and CustomEvent
, support a custom payload that can include any information.
It's passed as a Dictionary<string, object>
to the logging methods. To avoid confusion with other fields, it is recommended to pass the parameter by name, i.g. LogInstall(customPayload: playerExtraParams)
rather than just LogInstall(playerExtraParams)
.
Example
Dictionary<string, object> myCustomPayload {
{ "set", "Intense Stare Magic Mastery" },
{ "cosmetic", "flamingo shades" },
};
_sdk.LogOfferImpressionEvent(somePlacementId, someOfferId, myCustomPayload);
_sdk.LogOfferPurchaseEvent(somePlacementId, someOfferId, "USD", 2.49, customPayload: myCustomPayload);
Event Dispatch (Flushing)
When you log an event (both with static calling or using async), it isn't guaranteed to be sent immediately as events are sent in bulks.
If you need to make sure events are immediately sent to the ingestion endpoint, you can use the RequestDispatchEvents
call but don't overuse it as the default behaviour helps aggregating events for lower network load.
Ads Integration
This section explains how to integrate Metica's interstitial ads into your Unity project. Metica's streamlined API simplifies ad integration by automatically handling ad unit IDs and optimizing ad selection.
This guide assumes that the AppLovin SDK has already been configured. Otherwise please follow this guide. MeticaAds requires AppLovin SDK version ≥ 13.

Initialization
The IsMeticaAdsEnabled
flag is a boolean variable that determines whether a specific user will receive ads optimized by Metica's AI or will be part of a holdout group receiving ads directly through the standard AppLovin MAX SDK. This flag is set during the SDK initialization and is used to A/B test the revenue performance of Metica's ad optimization against the baseline performance of the MAX SDK.
Important: MeticaAds.InitializeAsync()
must be called BEFORE initializing the AppLovin MAX SDK to ensure proper integration.
/// <summary>
/// Complete initialization flow for MeticaAds and MAX SDK integration
/// This method demonstrates the proper order and setup required for ad functionality
/// Call this method early in your app lifecycle, typically in Start() or Awake()
/// </summary>
public async void InitializeAds()
{
// Step 1: Set User Identification (Critical Requirement)
// Important: UserId must be set for the current user before any MeticaAds initialization
// This unique identifier is used for:
// - User analytics and behavior tracking
// - A/B testing and holdout group management
// - Revenue attribution and reporting
// - Personalized ad targeting and optimization
MeticaSdk.CurrentUserId = "your_unique_user_id";
// Step 2: Configure MeticaAds initialization
// Create the configuration object that will be passed to the MeticaAds SDK
var meticaConfiguration = new MeticaConfiguration();
// Step 3: Initialize MeticaAds SDK (Asynchronous Operation)
// This call performs the core MeticaAds setup including:
// - SDK authentication and configuration validation
// - Network connectivity and endpoint verification
// - Platform-specific delegate initialization
// - Ad callback registration and event system setup
// Returns true if Metica should be used, false otherwise
IsMeticaAdsEnabled = await MeticaAds.InitializeAsync(meticaConfiguration);
// Step 4: Initialize AppLovin MAX SDK (Traditional Synchronous Setup)
// Set the SDK key that identifies your app in the AppLovin dashboard
// This key is essential for ad serving, reporting, and revenue tracking
MaxSdk.SetSdkKey("YOUR_MAX_SDK_KEY"); // Replace with your actual MAX SDK key
// Set MAX initialization callback
MaxSdkCallbacks.OnSdkInitializedEvent += sdkConfiguration =>
{
// AppLovin SDK is initialized, now start loading ads
Debug.Log("MAX SDK Initialized");
InitializeInterstitialAds();
InitializeRewardedAds();
};
// Initialize the MAX SDK - this sets up the underlying ad infrastructure
// Must be called after MeticaAds initialization to ensure proper integration
MaxSdk.InitializeSdk();
}
MeticaAdExtensions
The MeticaAdExtensions
class provides extension methods to convert MeticaAd objects to MaxSdkBase.AdInfo objects, enabling seamless integration between MeticaAds callbacks and existing MAX SDK callback signatures. This allows you to use the same callback methods for both MeticaAds and standard MAX SDK implementations.
Purpose: Converts MeticaAd objects to MaxSdkBase.AdInfo format so existing MAX SDK callback handlers can work with MeticaAds without modification.
Usage: The extension method ToAdInfo()
is automatically available on MeticaAd objects and is used in callback registrations as shown in the interstitial ads example.
// MeticaAdExtensions.cs
using System.Collections.Generic;
namespace Metica.ADS
{
public static class MeticaAdExtensions
{
/// <summary>
/// Converts a MeticaAd object to MaxSdkBase.AdInfo format for compatibility with MAX SDK callbacks
/// </summary>
/// <param name="meticaAd">The MeticaAd object to convert</param>
/// <returns>MaxSdkBase.AdInfo object with mapped values</returns>
public static MaxSdkBase.AdInfo ToAdInfo(this MeticaAd meticaAd)
{
// Create a dictionary with available MeticaAd values
var adInfoDictionary = new Dictionary<string, object>
{
["adUnitId"] = meticaAd.adUnitId ?? string.Empty,
["adFormat"] = meticaAd.adFormat ?? string.Empty,
["networkName"] = meticaAd.networkName ?? string.Empty,
["placement"] = meticaAd.placementTag ?? string.Empty,
["revenue"] = meticaAd.revenue,
// Set defaults for unavailable fields
["networkPlacement"] = string.Empty,
["creativeId"] = string.Empty,
["revenuePrecision"] = string.Empty,
["waterfallInfo"] = new Dictionary<string, object>(),
["latencyMillis"] = 0L,
["dspName"] = string.Empty
};
return new MaxSdkBase.AdInfo(adInfoDictionary);
}
}
}
Integration Notes:
Create this file in your project's Scripts folder alongside other MeticaAds integration files
The extension method enables callback compatibility as seen in:
meticaAd.ToAdInfo()
This allows unified callback handling regardless of whether MeticaAds or standard MAX SDK is active
Interstitial ads
Interstitial ads are full-screen or full-page ads that temporarily cover an app’s interface. They’re typically shown at natural pauses or transition points, such as after completing a level in a game or when navigating between major views.
The following sections show you how to load and then show an interstitial ad.
Loading an Interstitial Ad
The following code shows you how to attach listeners and load the first interstitial ad:
private void InitializeInterstitialAds()
{
// Attach callbacks based on whether MeticaAds is enabled
if (IsMeticaAdsEnabled)
{
// Use MeticaAds callbacks with extension methods to convert to MAX callback signatures
MeticaAdsCallbacks.Interstitial.OnAdLoadSuccess += (meticaAd) => OnInterstitialLoadedEvent(meticaAd.adUnitId, meticaAd.ToAdInfo());
MeticaAdsCallbacks.Interstitial.OnAdLoadFailed += (error) => OnInterstitialFailedEvent("", error);
MeticaAdsCallbacks.Interstitial.OnAdShowSuccess += (meticaAd) => OnInterstitialDisplayedEvent(meticaAd.adUnitId, meticaAd.ToAdInfo());
MeticaAdsCallbacks.Interstitial.OnAdShowFailed += (meticaAd, error) => InterstitialFailedToDisplayEvent(meticaAd.adUnitId, error);
MeticaAdsCallbacks.Interstitial.OnAdClicked += (meticaAd) => OnInterstitialClickedEvent(meticaAd.adUnitId, meticaAd.ToAdInfo());
MeticaAdsCallbacks.Interstitial.OnAdHidden += (meticaAd) => OnInterstitialDismissedEvent(meticaAd.adUnitId, meticaAd.ToAdInfo());
MeticaAdsCallbacks.Interstitial.OnAdRevenuePaid += (meticaAd) => OnInterstitialRevenuePaidEvent(meticaAd.adUnitId, meticaAd.ToAdInfo());
}
else
{
// Use standard MAX SDK callbacks
MaxSdkCallbacks.Interstitial.OnAdLoadedEvent += OnInterstitialLoadedEvent;
MaxSdkCallbacks.Interstitial.OnAdLoadFailedEvent += (adUnitId, adInfo) => OnInterstitialFailedEvent(adUnitId, adInfo.Message);
MaxSdkCallbacks.Interstitial.OnAdDisplayedEvent += OnInterstitialDisplayedEvent;
MaxSdkCallbacks.Interstitial.OnAdDisplayFailedEvent += (adUnitId, errorInfo, adInfo) => InterstitialFailedToDisplayEvent(adUnitId, errorInfo.Message);
MaxSdkCallbacks.Interstitial.OnAdClickedEvent += OnInterstitialClickedEvent;
MaxSdkCallbacks.Interstitial.OnAdHiddenEvent += OnInterstitialDismissedEvent;
MaxSdkCallbacks.Interstitial.OnAdRevenuePaidEvent += OnInterstitialRevenuePaidEvent;
}
// Load the first interstitial
LoadInterstitial();
}
void LoadInterstitial()
{
interstitialStatusText.text = "Loading...";
if (IsMeticaAdsEnabled)
{
MeticaAds.LoadInterstitial();
}
else
{
MaxSdk.LoadInterstitial(InterstitialAdUnitId);
}
}
private void OnInterstitialLoadedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
{
// Interstitial ad is ready to be shown
interstitialStatusText.text = $"Loaded {adUnitId}";
Debug.Log("Interstitial loaded");
// Reset retry attempt
interstitialRetryAttempt = 0;
}
private void OnInterstitialFailedEvent(string adUnitId, string error)
{
// Interstitial ad failed to load. Retry with exponentially higher delays up to a maximum delay
interstitialRetryAttempt++;
double retryDelay = Math.Pow(2, Math.Min(6, interstitialRetryAttempt));
interstitialStatusText.text = $"Load failed {adUnitId}: " + error + "\nRetrying in " + retryDelay + "s...";
Debug.Log("Interstitial failed to load with error: " + error);
Invoke("LoadInterstitial", (float)retryDelay);
}
private void OnInterstitialDisplayedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
{
Debug.Log($"Interstitial shown {adUnitId}");
}
private void InterstitialFailedToDisplayEvent(string adUnitId, string error)
{
// Interstitial ad failed to display. Load the next ad
Debug.Log("Interstitial failed to display: " + error);
LoadInterstitial();
}
private void OnInterstitialClickedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
{
Debug.Log($"Interstitial clicked {adUnitId}");
}
private void OnInterstitialDismissedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
{
// Interstitial ad is hidden. Pre-load the next ad
Debug.Log("Interstitial dismissed");
LoadInterstitial();
}
private void OnInterstitialRevenuePaidEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
{
// Interstitial ad revenue paid. Use this callback to track user revenue
double revenue = adInfo.Revenue;
string countryCode = MaxSdk.GetSdkConfiguration().CountryCode;
string networkName = adInfo.NetworkName;
string adUnitIdentifier = adInfo.AdUnitIdentifier;
string placement = adInfo.Placement;
Debug.Log($"Interstitial revenue paid - AdUnit: {adUnitIdentifier}, Revenue: {revenue}, Network: {networkName}, Country: {countryCode}, Placement: {placement}");
}
Showing an Interstitial Ad
To show an interstitial ad, call ShowInterstitial()
:
void ShowInterstitial()
{
if (IsMeticaAdsEnabled) {
if (MeticaAds.IsInterstitialReady())
{
MeticaAds.ShowInterstitial();
}
else
{
interstitialStatusText.text = "Ad not ready";
}
}
else
{
if (MaxSdk.IsInterstitialReady(InterstitialAdUnitId))
{
intersitialStatusText.text = "Showing";
MaxSdk.ShowInterstitial(InterstitiaAdUnitId);
}
else
{
interstitialStatusText.text = "Ad not ready";
}
}
}
Rewarded Ads
Rewarded ads are video ads that users can choose to watch in exchange for in-app rewards.
Loading a Rewarded Ad
The InitializeRewardedAds
method attaches listeners for both Metica and MAX SDK rewarded ad callbacks and then loads the first rewarded ad.
private void InitializeRewardedAds()
{
// Attach callbacks based on whether MeticaAds is enabled
if (IsMeticaAdsEnabled)
{
// Use MeticaAds callbacks with extension methods to convert to MAX callback signatures
MeticaAdsCallbacks.Rewarded.OnAdLoadSuccess += (meticaAd) => OnRewardedAdLoadedEvent(meticaAd.adUnitId, meticaAd.ToAdInfo());
MeticaAdsCallbacks.Rewarded.OnAdLoadFailed += (error) => OnRewardedAdFailedEvent("", error);
MeticaAdsCallbacks.Rewarded.OnAdShowSuccess += (meticaAd) => OnRewardedAdDisplayedEvent(meticaAd.adUnitId, meticaAd.ToAdInfo());
MeticaAdsCallbacks.Rewarded.OnAdShowFailed += (meticaAd, error) => OnRewardedAdFailedToDisplayEvent(meticaAd.adUnitId, error);
MeticaAdsCallbacks.Rewarded.OnAdClicked += (meticaAd) => OnRewardedAdClickedEvent(meticaAd.adUnitId, meticaAd.ToAdInfo());
MeticaAdsCallbacks.Rewarded.OnAdHidden += (meticaAd) => OnRewardedAdDismissedEvent(meticaAd.adUnitId, meticaAd.ToAdInfo());
MeticaAdsCallbacks.Rewarded.OnAdRewarded += (meticaAd) => OnRewardedAdReceivedRewardEvent
(
meticaAd.adUnitId,
new MaxSdkBase.Reward { Label = "Coin", Amount = 1 },
meticaAd.ToAdInfo()
);
MeticaAdsCallbacks.Rewarded.OnAdRevenuePaid += (meticaAd) => OnRewardedAdRevenuePaidEvent(meticaAd.adUnitId, meticaAd.ToAdInfo());
}
else
{
// Use standard MAX SDK callbacks
MaxSdkCallbacks.Rewarded.OnAdLoadedEvent += OnRewardedAdLoadedEvent;
MaxSdkCallbacks.Rewarded.OnAdLoadFailedEvent += (adUnitId, errorInfo) => OnRewardedAdFailedEvent(adUnitId, errorInfo.Message);
MaxSdkCallbacks.Rewarded.OnAdDisplayedEvent += OnRewardedAdDisplayedEvent;
MaxSdkCallbacks.Rewarded.OnAdDisplayFailedEvent += (adUnitId, errorInfo, adInfo) => OnRewardedAdFailedToDisplayEvent(adUnitId, errorInfo.Message);
MaxSdkCallbacks.Rewarded.OnAdClickedEvent += OnRewardedAdClickedEvent;
MaxSdkCallbacks.Rewarded.OnAdHiddenEvent += OnRewardedAdDismissedEvent;
MaxSdkCallbacks.Rewarded.OnAdReceivedRewardEvent += OnRewardedAdReceivedRewardEvent;
MaxSdkCallbacks.Rewarded.OnAdRevenuePaidEvent += OnRewardedAdRevenuePaidEvent;
}
// Load the first rewarded ad
LoadRewardedAd();
}
private void LoadRewardedAd()
{
rewardedStatusText.text = "Loading...";
if (IsMeticaAdsEnabled)
{
MeticaAds.LoadRewarded();
}
else
{
MaxSdk.LoadRewardedAd(RewardedAdUnitId);
}
}
private void OnRewardedAdLoadedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
{
// Rewarded ad is ready to be shown
rewardedStatusText.text = $"Loaded {adUnitId}";
Debug.Log("Rewarded ad loaded");
// Reset retry attempt
rewardedRetryAttempt = 0;
}
private void OnRewardedAdFailedEvent(string adUnitId, string error)
{
// Rewarded ad failed to load. Retry with exponentially higher delays up to a maximum delay
rewardedRetryAttempt++;
double retryDelay = Math.Pow(2, Math.Min(6, rewardedRetryAttempt));
rewardedStatusText.text = $"Load failed {adUnitId}: " + error + "\nRetrying in " + retryDelay + "s...";
Debug.Log("Rewarded ad failed to load with error: " + error);
Invoke("LoadRewardedAd", (float)retryDelay);
}
private void OnRewardedAdDisplayedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
{
Debug.Log($"Rewarded ad displayed {adUnitId}");
}
private void OnRewardedAdFailedToDisplayEvent(string adUnitId, string error)
{
// Rewarded ad failed to display. Load the next ad
Debug.Log("Rewarded ad failed to display: " + error);
LoadRewardedAd();
}
private void OnRewardedAdClickedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
{
Debug.Log($"Rewarded ad clicked {adUnitId}");
}
private void OnRewardedAdDismissedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
{
// Rewarded ad is hidden. Pre-load the next ad
Debug.Log("Rewarded ad dismissed");
LoadRewardedAd();
}
private void OnRewardedAdReceivedRewardEvent(string adUnitId, MaxSdk.Reward reward, MaxSdkBase.AdInfo adInfo)
{
// Rewarded ad was displayed and user should receive the reward
Debug.Log("Rewarded ad received reward");
// Implement your reward logic here
}
private void OnRewardedAdRevenuePaidEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
{
// Rewarded ad revenue paid. Use this callback to track user revenue
double revenue = adInfo.Revenue;
string countryCode = MaxSdk.GetSdkConfiguration().CountryCode;
string networkName = adInfo.NetworkName;
string adUnitIdentifier = adInfo.AdUnitIdentifier;
string placement = adInfo.Placement;
Debug.Log($"Rewarded ad revenue paid - AdUnit: {adUnitIdentifier}, Revenue: {revenue}, Network: {networkName}, Country: {countryCode}, Placement: {placement}");
}
Showing a Rewarded Ad
To show an interstitial ad, call ShowRewarded()
:
void ShowRewardedAd()
{
if (IsMeticaAdsEnabled)
{
if (MeticaAds.IsRewardedReady())
{
rewardedStatusText.text = "Showing";
MeticaAds.ShowRewarded();
}
else
{
rewardedStatusText.text = "Ad not ready";
}
}
else
{
if (MaxSdk.IsRewardedAdReady(RewardedAdUnitId))
{
rewardedStatusText.text = "Showing";
MaxSdk.ShowRewardedAd(RewardedAdUnitId);
}
else
{
rewardedStatusText.text = "Ad not ready";
}
}
}
Metica SDK vs AppLovin Interstitial API
API Calls
Metica's API in contrast to AppLovin does not require an adUnitId
to be passed. The reason is that Metica's AI technology automatically selects and manages the optimal ad unit IDs behind the scenes, eliminating the need for developers to manually specify these IDs in each function call and simplifying integration.
Metica Ads API
MeticaAds.LoadInterstitial();
MeticaAds.IsInterstitialReady();
MeticaAds.ShowInterstitial();
MeticaAds.LoadRewarded();
MeticaAds.IsRewardedAdReady();
MeticaAds.ShowRewarded();
Max SDK API
MaxSdk.LoadInterstitialAd(InterstitialAdUnitId);
MaxSdk.IsInterstitialAdReady(InterstitialAdUnitId);
MaxSdk.ShowInterstitialAd(InterstitialAdUnitId);
MaxSdk.LoadRewardedAd(RewardedAdUnitId);
MaxSdk.IsRewardedAdReady(RewardedAdUnitId);
MaxSdk.ShowRewardedAd(RewardedAdUnitId);
Callbacks
Metica Ad Callbacks
MeticaAdsCallbacks.Interstitial.OnAdLoadSuccess
MeticaAdsCallbacks.Interstitial.OnAdLoadFailed
MeticaAdsCallbacks.Interstitial.OnAdShowSuccess
MeticaAdsCallbacks.Interstitial.OnAdShowFailed
MeticaAdsCallbacks.Interstitial.OnAdClicked
MeticaAdsCallbacks.Interstitial.OnAdHidden
MeticaAdsCallbacks.Rewarded.OnAdLoadSuccess
MeticaAdsCallbacks.Rewarded.OnAdLoadFailed
MeticaAdsCallbacks.Rewarded.OnAdShowSuccess
MeticaAdsCallbacks.Rewarded.OnAdShowFailed
MeticaAdsCallbacks.Rewarded.OnAdClicked
MeticaAdsCallbacks.Rewarded.OnAdHidden
Max Ad Callback
MaxSdkCallbacks.Interstitial.OnAdLoadedEvent
MaxSdkCallbacks.Interstitial.OnAdLoadFailedEvent
MaxSdkCallbacks.Interstitial.OnAdDisplayedEvent
MaxSdkCallbacks.Interstitial.OnAdDisplayFailedEvent
MaxSdkCallbacks.Interstitial.OnAdClickedEvent
MaxSdkCallbacks.Interstitial.OnAdHiddenEvent
MaxSdkCallbacks.Rewarded.OnAdLoadedEvent
MaxSdkCallbacks.Rewarded.OnAdLoadFailedEvent
MaxSdkCallbacks.Rewarded.OnAdDisplayedEvent
MaxSdkCallbacks.Rewarded.OnAdDisplayFailedEvent
MaxSdkCallbacks.Rewarded.OnAdClickedEvent
MaxSdkCallbacks.Rewarded.OnAdHiddenEvent
Code Samples
The Metica Unity SDK package includes examples that can be easily imported into your Assets by selecting the package in the Package Manager and clicking the Import button next to one of the examples.
Currently available examples:
MeticaExample01 shows how to use the SDK via
MeticaAPI
(deprecated). This uses the static calls code style.MeticaExample02 shows how to use the SDK by retrieving the instance and using asynchronous code style.
Privacy Manifest
For iOS, iPadOS, tvOS and watchOS apps, we provide a privacy manifest at Assets/Plugins/PrivacyInfo.xcprivacy that describes the data collected by the Metica SDK.
Last updated
Was this helpful?