com.elevatix.unity.sdk
v2.6.17
Published
Unity SDK for Elevatix
Readme
Elevatix SDK
Table of contents
- Installation
- Configuration
- Initialization
- Track events
- Handle Offers
- Inform about user level and balance
- Testing and troubleshooting
- Complete Api
Installation
- Open Unity editor
- Edit -> Project Settings
- Choose "Package Manager"
- Add new "Scoped Registry"
- Name: Elevatix
- URL: https://registry.npmjs.org
- Scope(s): com.elevatix
- Navigate to Window -> Package Manager
- In packages dropdown choose "My registries"
- Select Elevatix SDK and hit install
That concludes the installation of the SDK!
Configuration
Configuration is straightforward and consist only of two steps
Create the Elevatix "Settings file"
Navigate to Assets -> Create -> Elevatix -> Settings file. This action will generate a settings file named "ElevatixSettings.asset" within the "Assets/Resources" folder.
Obtaining the "Application Key":
- Access dev.admin.elevatix.io and log in using your valid credentials.
- Select the "Settings" page from the menu, situated on the left side of the screen.
- Copy the "Application Key" and proceed to paste it into the ElevatixSettings.asset file within the Unity editor.
You have successfully completed the configuration process!
Migration from 2.6.3 and older version
- The SDK includes a migration script that automatically upgrades the settings asset.
- When you update the SDK and open Unity, the migration process will run automatically.
- You can find the migrated asset at previously stored folder.
- If migration process fails, you can manually migrate the asset by choosing menu option "Migrate Settings" at Tools/Elevatix/Migrate Settings menu.
Initialization and Async Behavior
This documentation section updates the initialization information to better explain the asynchronous behavior of AnalyticsClient.Init() and the media source integration.
Initialization
The AnalyticsClient.Init() method is asynchronous and returns a Task that completes when the initialization process finishes. Initialize Elevatix during the game startup, preferably in the preloading/loading stage.
using Elevatix;
using System.Threading.Tasks;
// Basic initialization
async Task InitializeElevatix()
{
await AnalyticsClient.Init();
// Continue with game initialization after Elevatix is ready
}Application Install Conversion Data
To track user acquisition sources, you can provide media source data during initialization or later when your mmp provides it:
using Elevatix;
using Elevatix.MediaSource;
using System.Threading.Tasks;
async Task InitializeWithMediaSource()
{
// Create media context with the source from your attribution provider
var mediaContext = new MediaContext(mediaSourceName)
.SetCampaignId(campaignId)
.SetCampaignName(campaignName)
.SetMMPUserId(mmpUserId)
.SetAcquisitionCost(acquisitionCost)
.SetAcquisitionModel(acquisitionModel)
.SetAcquisitionCurrency(acquisitionCurrency)
.SetGeo(geoData)
.SetMmpName(mmpName);
// Initialize SDK
await AnalyticsClient.Init();
// After initialization, send the media context to the SDK
await AnalyticsClient.SendMmpAsync(mediaContext);
// Elevatix is now initialized with attribution data
}Important Notes:
- The SDK must be initialized with
AnalyticsClient.Init()before callingSendMmp - If
mediaContextis null, the method will log an error and return - This method is typically used when attribution data becomes available after app initialization
⚠ More info about transfering conversion data can be found below.
Track events
Using Tracker API inform Elevatix about all significant user actions and state changes.
Here is an example of implementation of the event that needs to be tracked:
StoreOpen tracking sample
using Elevatix;
private void OnGameStoreOpened()
{
Tracker.TrackStoreOpen();
}Tracker.TrackOfferPurchase is used to track successful offer purchases in the Elevatix SDK. When a user purchases an offer recommended by Elevatix, this method should be called with the offerId and packId as parameters. The storeTransactionId parameter in the sample method is optional and can be used to include the transaction identifier from the store platform, but it's not required for the tracking functionality.
This tracking should always be implemented after successful store callbacks and validations to ensure accurate purchase data is recorded.
using Elevatix;
//
private void OnOfferPurchaseSuccess(long offerId, long packId, string storeTransactionId = null)
{
Tracker.TrackOfferPurchase(offerId, packId);
}Tracker.TrackCustomPurchase is used to track successful purchases made from an internal game store (not from Elevatix offers). It takes a productId parameter and a list of PurchasedItem objects representing the goods the player received. This method should only be called after successful store validation to ensure accurate purchase data recording.
using Elevatix;
private void OnStorePurchaseSuccess(string productId, List<PurchasedItem> items)
{
Tracker.TrackCustomPurchase(productId, items);
}Please note that in addition to this, you will also need to implement all other tracking methods as outlined in the Complete Tracker API section
Handle Offers
After an important event happens while playing the game and Elevatix is informed through the Tracking API, Elevatix will then look for a special offer designed for that exact moment. There's a way in which Elevatix tells the game what offer should be shown to the user.
The AnalyticsClient includes an object named OffersDispatcher.
This object has method RegisterHanlder that accepts implementation of OfferHandlerBase<T> where T is SingleOffer or MultiOffer.
using Elevatix;
using Elevatix.Offers;
class SingleOfferHandler : OfferHandlerBase<SingleOffer> {
protected override Task HandleAsync(SingleOffer offer)
{
// show dialog with the single offer
}
}
class MultiOfferHandler : OfferHandlerBase<MultiOffer> {
protected override Task HandleAsync(MultiOffer offer)
{
// show dialog with multiple purchase options
}
}
// somewhere during start
AnalyticsClient.OffersDispatcher
.RegisterHandler(new SingleOfferHandler())
.RegisterHandler(new MultiOfferHandler())
.Start();It's necessary to call Start for letting SDK know that game is ready to start handling offers
⚠️ Informing about offer status
When integrating Elevatix, it is extremely important to consider two key events: TrackOfferPurchase and TrackOfferReject. These two trackers play a critical role in understanding player preferences and help in creating personalized offers that increase the likelihood of successful sales in the future.
TrackOfferPurchase: The TrackOfferPurchase event should be called whenever a player purchases an offer. This event allows the Elevatix analytics module to record a successful transaction and understand which offers are most attractive to players.TrackOfferReject: The TrackOfferReject event should be called whenever a player rejects an offer. This allows the Elevatix analytical module to record refusals and understand which offers are less attractive to players.
Inform about user level and balance
There are two compelling reasons why Elevatix requires access to players' product balances and level state:
- Firstly: This information serves as a crucial safeguard, preventing Elevatix from suggesting non-consumable items that the user has already purchased.
- Secondly: It enables Elevatix to make more informed and strategic choices when determining which product(s) should be recommended to the user, thereby enhancing the overall user experience.
Important Note: It is imperative that all AnalyticsClient.SetInventoryItem and AnalyticsClient.SetLevel calls are executed prior to the first Tracker call. This sequence is critical for ensuring the accuracy and effectiveness of the tracking process.
For instance, consider the following scenario:
Given that the user has 300 coins (a form of soft in-game currency, identified as ID - 10) and is at level 15.
The corresponding code should look following:
using Elevatix;
// 10 - Elevatix, product ID
// 300 - is amount of that product
AnalyticsClient.SetInventoryItem(10, 300);
AnalyticsClient.SetLevel(15);Sending mmp data after the first launch
Some media platforms can retrieve attribution data after the first launch of the game.
AppsFlyer
For example, AppsFlyer can retrieve attribution data after the first launch of the game by calling AppsFlyer.getConversionData(gameObject.name) method. This will trigger a default flow of sending attribution data from AppsFlyer to the client application. It will look for the IAppsFlyerConversionData implementation in the selected gameobject and will call void onConversionDataSuccess(string conversionData) on it.
⚠️ Make sure that this method is called only once per user lifetime.
Testing and Troubleshooting
Once the SDK has been successfully integrated and thoroughly tested within the Unity Editor, there may arise a need to conduct testing on a development or test-flight build of the game.
In such instances, the game must provide a mechanism to expose the Elevatix user ID to the developer.
This user ID can be obtained by invoking the AnalyticsClient.GetUserId function. This user ID will reset each time the game is reinstalled, and it is unique to each device.
Complete Api
Analytics Client Class
AnalyticsClient is static class and is part of Elevatix namespace.
AnalyticsClient.Init
Parameter: bool(default - true) - Whether the game is activating offers for a specific player
Description: Initializes SDK
AnalyticsClient.OffersDispatcher
Description: instance of the OffersDispatcher
AnalyticsClient.UserDataService
Description: instance of the UserDataService
AnalyticsClient.Disable
Description: Deactivates all event tracking and offers functionalities
AnalyticsClient.Enable
Description: Activates event tracking and offers features
AnalyticsClient.AreOffersEnabled
Description: Responds to the inquiry regarding the status of Elevatix offers, which can be either enabled or disabled through the administrative application. This determination can only be ascertained once the Elevatix SDK has been initialized
AnalyticsClient.SetLevel
Parameter: long - level of the user
Description: Provides Elevatix with information regarding the current state of the player's level
AnalyticsClient.SetInventoryItem
Parameter: long - The Elevatix product identifier corresponding to the product owned by the user
Parameter: long - The quantity of this product available in the user's balance
Description: Communicates the current state of the player's balance to Elevatix
AnalyticsClient.GetUserId
Description: The method for obtaining the UserID that Elevatix employs for client identification
AnalyticsClient.GetAssetUrls
Description: Returns a list of image URLs utilized in offers. This function is intended to be invoked during the asset loading phase to facilitate the caching of all images
Tracker Class
Tracker is static class and is part of Elevatix namespace.
Tracker.TrackEnterMainScreen
Description: Should be used when when player enters main screen(a.k.a home screen)
Tracker.TrackLevelStart
Parameter: int - Level that player started
Description: Should be used when player enters level
Tracker.TrackLevelWin
Parameter: int - Level that player won
Description: Should be used when player wins level
Tracker.TrackLevelFail
Parameter: int - Level that player failed
Description: Should be used after player fails level
Tracker.TrackOfferReject
Parameter: long - Offer id that player bought
Parameter: long - Pack id that player bought
Description: Should be used after the player has кeject the purchase of a product offered by Elevatix.
Tracker.TrackOfferPurchase
Parameter: long - Offer id that player bought
Parameter: long - Pack id that player bought
Description: Should be used after player bought product from offer provided by the Elevatix
Tracker.TrackProductRestore
Parameter: string - Product that been restored, typically it looks like - com.{your-company}.{productId}
Parameter: List<PurchasedItem> - List of PurchasedItem that represents goods that player got
Description: Should be used when player restores(without additional charges) product purchase
Tracker.TrackCustomPurchase
Parameter: string - Product that been restored, typically it looks like - com.{your-company}.{productId}
Parameter: List<PurchasedItem> - List of PurchasedItem that represents goods that player got
Description: Should be used when player made product purchase
Tracker.TrackCustomRollingPurchase
Parameter: string - Product that been bought from the store, typically it looks like - com.{your-company}.{productId}
Parameter: List<PurchasedItem> - List of PurchasedItem that represents goods that player got
Parameter: int - Index of product in rolling offer chain
Description: Should be used when player bought something via game owned rolling offers
Tracker.TrackBalanceUpdate
Parameter: string - ID of the updated product
Parameter: long - Amount of given(positive number) or taken away(negative number) products
Description: Should be used after players balance has changed
Tracker.TrackAdEvent
Parameter: AdType - type of advertisement (imported from Elevatix.Advertisement namespace)
Description: should be tracked after ad complete
Tracker.TrackCustomEvent
Parameter: string - event name
Description: Should be used to track custom event
Offer
Is high level entity that comes to the game.
Acts as container for the
public class Offer
{
// Offer Id
public long Id;
}SingleOffer
Is offer with exact one pack that user can purchase
public class SingleOffer: Offer
{
// Pack entity
public Pack Pack;
}MultiOffer
Is offer with more than one pack that user can purcase
public class MultiOffer: Offer
{
// Pack entity
public Packs List<Pack>;
}Offers Dispatcher
Object that informs game about offers that game should show for the user.
Analytics client has includes instance of this object
OffersDispatcher.RegisterHandler
Description: Method that registers specific handler for further offers processing
Parameter: handler, implementation of the OfferHandlerBase
OffersDispatcher.Start
Description: Tells dispatcher to "start" dispatching offers Returns: Task that is resolved when initial offers are resolved
Pack
Entity containing products for the user, along with pertinent instructions on how to facilitate its sale.
public class Pack
{
public long Id => id;
// The name of the pack, intended for client-facing display to the user
public string Name;
// Field contains information about how to sell particular pack
public CostPackage CostPackage;
// A list of the products contained within this pack, essentially items to be used as rewards after purchase
public List<Product> Products;
// The type of the pack, with possible values being PackType.Regular and PackType.Subscription
public PackType Type;
// Relevant only for PackType.Subscription, representing units of duration
public DurationType DurationType;
// Relevant only for PackType.Subscription, indicating the duration for which the subscription should be applied
public int Duration;
// Custom keys and values that are filled in during pack creation
// Could be usefull for customization of specific pack
public Dictionary Meta;
// A URL pointing to the image assigned to the pack
public string? ImageUrl;
}Pack Extension Methods
The following extension methods are available for the Pack class:
// Downloads the pack's image using its ImageUrl
// Returns null if ImageUrl is not set or download fails
Task<Sprite> LoadImageAsync()
// Downloads the pack's image without caching
// Returns null if ImageUrl is not set or download fails
// Use this for frequently changing images
Task<Sprite> LoadImageWithoutCacheAsync()
// Downloads the pack's image with custom caching options
// Returns null if ImageUrl is not set or download fails
Task<Sprite> LoadImageAsync(ImageLoaderOptions options)Usage example:
// Load pack image with default caching
Sprite? sprite = await myPack.LoadImageAsync();
// Load pack image without caching
Sprite? dynamicSprite = await myPack.LoadImageWithoutCacheAsync();
// Load with custom options
var options = new ImageLoaderOptions {
UseCache = true,
ValidateCache = false
};
Sprite? customSprite = await myPack.LoadImageAsync(options);ElevatixImageLoader Class
A utility class that provides methods for loading and caching images in the Elevatix SDK.
Methods
LoadImageAsync
public static Task<Sprite?> LoadImageAsync(string imageUrl)Downloads an image from the specified URL and returns it as a Sprite. Uses default caching behavior.
- Parameters:
imageUrl: URL of the image to download
- Returns: Downloaded sprite or null if download failed
LoadImageWithoutCacheAsync
public static Task<Sprite?> LoadImageWithoutCacheAsync(string imageUrl)Downloads an image from the specified URL without caching. Use this for frequently changing images.
- Parameters:
imageUrl: URL of the image to download
- Returns: Downloaded sprite or null if download failed
LoadImageAsync (with options)
public static Task<Sprite?> LoadImageAsync(string imageUrl, ImageLoaderOptions options)Downloads an image from the specified URL with custom caching configuration.
- Parameters:
imageUrl: URL of the image to downloadoptions: Custom configuration for image loading
- Returns: Downloaded sprite or null if download failed
Cache Management
The SDK provides methods to manage the image cache:
// Get total cache size in bytes
long cacheSize = ElevatixImageLoader.GetCacheSize();
// Clear all cached images
ElevatixImageLoader.ClearCache();ImageLoaderOptions Class
Configuration options for image loading behavior.
Properties:
UseCache: Whether to use caching for downloaded images (default: true)ValidateCache: Whether to validate cached images against server ETag (default: true)
Preset Options:
ImageLoaderOptions.Default: Default options with caching enabledImageLoaderOptions.NoCache: Options with caching disabled for dynamic content
Usage Example
// Load image with default caching
Sprite? sprite = await ElevatixImageLoader.LoadImageAsync("https://example.com/image.png");
// Load image without caching
Sprite? dynamicSprite = await ElevatixImageLoader.LoadImageWithoutCacheAsync("https://example.com/dynamic.png");
// Load with custom options
var options = new ImageLoaderOptions {
UseCache = true,
ValidateCache = false
};
Sprite? customSprite = await ElevatixImageLoader.LoadImageAsync("https://example.com/custom.png", options);Cost Package
It's easier to think of the Cost Package as similar to a 'Price Tag' in a retail store.
public class CostPackage
{
// Product id from the store. Should be used to show the price and execute purchase
public string ProductId;
}Product
public class Product
{
// Identifier for the product, consistent with its use in TrackBalanceUpdate and SetInventoryItem.
// Particularly necessary for awarding users
public long Id;
// The name of the product
public string Name;
// A flag set from the admin application. Used to identify the product's category and may require custom logic
public bool Special;
// Either "HARD" or "SOFT." This field allows for custom logic based on these two categories
public string CurrencyType;
// Either "CONSUMABLE" or "NON_CONSUMABLE." This field allows for custom logic based on these two categories
public string ConsumeType;
// Quantity of products in the parent pack
public int Quantity;
// Custom string of the product assigned during pack creation in the admin app
public string CustomProperty;
#nullable enable
// Image associated with the specific product in the "Elevatix Settings" file
public Sprite? Image;
// String associated with the specific product in "Elevatix Settings".
// It might be used to display the sprite image with rich text
public string? Sprite;
// URL pointing to the image assigned to the product
public string? ImageUrl;
#nullable disable
}PurchasedItem
Entity that represents goods that user received as one of rewards to purchase.
class PurchasedItem {
/// <summary>
/// Entity that represents goods that user received as one of rewards to purchase
/// </summary>
/// <param name="productId">Product Identifier registered in elevatix admin app</param>
/// <param name="amount">Amount for items granted to the user</param>
/// <param name="customProperty">Custom value of that most likely would be some kind of "type"</param>
public PurchasedItem(long productId, double amount, string customProperty = null)
}UserDataService
Object for defining player data. Instantiated in the AnalyticsClient.UserData field
SetRegistrationDate
Important note: This method should be called before AnalyticsClient.Init call, otherwise is ignored
Description: Notifies Elevatix about user registration date
Parameter: long timestamp of the moment when user got registered or installed the app
Integration with AppsFlyer for Install Attribution
To track the source of app installs and provide this data to Elevatix, you can integrate AppsFlyer's conversion data. This will allow Elevatix to optimize offers based on user acquisition channels.
Getting AppsFlyer Conversion Data
To retrieve the media source from AppsFlyer and pass it to Elevatix during initialization:
using AppsFlyerSDK;
using Elevatix;
using Elevatix.MediaSource;
public class AppsFlayerIntegration : MonoBehaviour, IAppsFlyerConversionData
{
private void Start()
{
// Initialize AppsFlyer with conversion data listener
AppsFlyer.initSDK("YOUR_DEV_KEY", "YOUR_APP_ID");
AppsFlyer.startSDK();
AppsFlyer.registerConversionDataListener(this);
}
public void onConversionDataSuccess(string conversionData)
{
// Parse conversion data
Dictionary<string, object> conversionDataDictionary = AppsFlyer.CallbackStringToDictionary(conversionData);
// Check if this is a valid attribution
if (conversionDataDictionary.ContainsKey("af_status") &&
conversionDataDictionary["af_status"].ToString() == "Non-organic")
{
string mediaSource = "organic"; // Default to organic
// Extract media source if available
if (conversionDataDictionary.ContainsKey("media_source"))
{
mediaSource = conversionDataDictionary["media_source"].ToString();
}
// Create MediaContext
var mediaContext = new MediaContext(mediaSource);
// Set MMP name
mediaContext.SetMMPName("appsFlyer");
// Set additional attribution data if available
if (conversionDataDictionary.ContainsKey("campaign"))
{
mediaContext.SetCampaignId(conversionDataDictionary["campaign"].ToString());
}
if (conversionDataDictionary.ContainsKey("af_customer_user_id"))
{
mediaContext.SetExternalUserId(conversionDataDictionary["af_customer_user_id"].ToString());
}
if (conversionDataDictionary.ContainsKey("af_cost_value"))
{
mediaContext.SetAcquisitionCost(conversionDataDictionary["af_cost_value"].ToString());
}
if (conversionDataDictionary.ContainsKey("af_cost_currency"))
{
mediaContext.SetAcquisitionCurrency(conversionDataDictionary["af_cost_currency"].ToString());
}
if(conversionDataDictionary.ContainsKey("af_cost_model"))
{
mediaContext.SetAcquisitionModel(conversionDataDictionary["af_cost_model"].ToString());
}
//initialize Elevatix
AnalyticsClient.Init(mediaContext: mediaContext);
}
else
{
// Handle organic installs
var mediaContext = new MediaContext("organic");
AnalyticsClient.Init(mediaContext: mediaContext);
}
}
public void onConversionDataFail(string error)
{
Debug.LogError("AppsFlyer conversion data failed: " + error);
// Initialize Elevatix without media source data
AnalyticsClient.Init();
}
// Required implementations for IAppsFlyerConversionData
public void onAppOpenAttribution(string attributionData) { }
public void onAppOpenAttributionFailure(string error) { }
}Important Notes
- Make sure to initialize AppsFlyer before Elevatix to ensure conversion data is available
- The conversion data might not be immediately available at app launch, especially on first installs
- For testing, use AppsFlyer's test devices and debug mode to verify the data flow
For more details on AppsFlyer's conversion data, refer to AppsFlyer documentation.
