Overview

The Kongregate SDK includes the Adjust SDK which is used for tracking installs, retention, and in-app purchases.

Once you’ve gone through the setup, hop over to Analytics Verification to make sure everything is working properly.

Unity Games that only integrate Analytics (no Kongregate Authentication or Backend) should start with the Analytics Only - Unity Quick Start Guide

Initialization

In order to enable the analytics API, you will need to pass in correct values for the various API options. If using the KongregateInit.cs script in Unity, these fields will be read from kong-config.json.

Optional Settings

Installation/Referral Tracking

=================

The Adjust SDK handles referral tracking. On iOS this happens automatically. On Android, you must include the Play Install Referrer API.

Common Properties

=================

After initializing the API, you will need to set the common properties. Common properties are fields that will be submitted automatically along with each event, including automatic events. Examples of common properties might be hard_currency_balance or tutorial_completed. Your producer will provide you with a list of common properties for your game.

There are two ways to notify our SDK of the common properties:


iOS Example
[[[KongregateAPI instance] analytics] setCommonPropertiesBlock:^NSDictionary *{
        return @{ @"tutorial_completed": tuturialCompleted,
                  @"soft_currency_balance": sofCurrencyBalance,
                  @"hard_currency_balance": hardCurrencyBalance };
    }];
Android Example
api.analytics().setCommonPropertiesEvaluator(new CommonPropertiesEvaluator() {
  @Override
  public Map<String, Object> getCommonProperties() {
    // build and return analytics data
    HashMap<String,Object> props = new HashMap<String, Object>();
    props.put("tuturial_completed", isTutorialComplete);
    props.put("soft_currency_balance", softCurrencyBalance);
    props.put("hard_currency_balance", hardCurrencyBalance);
    // ...
    return props;
  }
});
Unity Example
KongregateInit.SetCommonPropsCallback(() => {
Dictionary<string,object> commonProps = new Dictionary<string, object>()
  {
    { "tutorial_completed", isTutorialComplete },
    { "soft_currency_balance", softCurrencyBalance },
    { "hard_currency_balance", hardCurrencyBalance }
  };
  return commonProps;
});

IMPORTANT NOTE: A common gotcha is the common properties not being available for the initial automatic events the app fires. This may happen for example, if you initialize your common properties from a server call and the server has not responded when the initial installs or session_starts event is fired. The best way to handle this is to keep a local cached version of the common properties. An alternative is to use the KONGREGATE_OPTION_DEFER_ANALYTICS option to ensure the server responds first. The problem with this approach, is events may be lost if the user starts while offline.

Submitting Events

=================

To submit game events, you can use the addEvent method on the analytics API object. This method accepts the name of the event as well as a map of key/value pairs for the event parameters.

You do not need to worry about submitting the events to the server, as that will happen in a background thread periodically.

You may use Swrve QA Mode to watch events come through in realtime from a specific device.


iOS Example

Game fields are passed to events as NSDictionary objects or JSON strings. The valid types for the values include: NSString, NSNumber, NSDate, NSDictionary, and NSArray. The keys must be less than 256 characters and may not contain a ‘.’ or start with a ‘$’.

// to add an event build the event NSDictionary of name value/pairs and add the event
NSDictionary* event = @{@"new_level":@1};
[KongregateAPI.instance.analytics addEvent:event toCollection:@"player_level_ups"];
Android Example
Map<String,Object> event = new HashMap<String, Object>();
event.put("new_level",1);
APIBootstrap.getInstance().analytics().addEvent("player_level_ups",event);
Unity Example
KongrgateAPI.GetAPI().Analytics.AddEvent("player_level_ups", new Dictionary<string,object>() {
  {"new_level",1}
});

Tracking Purchases

The flow described here should only be used when the products IDs follow the txx_<type> naming convention as this is a requirement for the Start/FinishPurchase() methods. This is the suggested flow for games that have not yet been released. Live games newly integrating the SDK will need to use the AddIapTransaction methods.

This Purchase Flow Diagaram gives an overview of when each method should be called. startPurchase should be invoked when a user starts a purchase flow. It will fire an iap_attempts event and store some data to connect it to when finishPurchase is invoked. Depending on the transaction state and result passed, finishPurchase will fire wither an iap_transactions or iap_fails event. More details on Receipt Verification may be found here Receipt Verification.


IMPORTANT NOTE: On iOS, you must invoke [KongregateAPI.instance.analytics finishPurchase] before SKPaymentQueue.finishTransaction. This is true for Unity plugins as well. Many Unity plugins automatically invoke finishTransaction. Be sure to choose one that has the option to seperate out this call, Prime31’s StoreKit for example.

iOS Example

// invoke when the user clicks buy
SKProduct* product = ...;
NSDictionary* iapAttemptFields = @{ ... };
[KongregateAPI.instance.analytics startPurchase:product.productIdentifier withQuantity:1 withGameFields:iapAttemptFields];

... // process transaction

// Always invoke finishPurchase before the transaction is finished
SKPaymentTransaction* transaction = ...;
NSDictionary* gameFields = @{ ... };
if (transaction.transactionState == SKPaymentTransactionStatePurchased) {
  if (receiptIsValidated) {
    // invoke when a transaction is succussful and the receipt is verfied
    [KongregateAPI.instance.analytics finishPurchase:KONG_PURCHASE_SUCCESS
                                   withTransactionId:transaction.transactionIdentifier
                                      withGameFields:gameFields];
  } else {
    // invoke when the purchase failed due to invalid receipt
    [KongregateAPI.instance.analytics finishPurchase:KONG_PURCHASE_RECEIPT_FAIL
                                  withTransactionId:transaction.transactionIdentifier
                                     withGameFields:gameFields];
  }
} else if (transaction.transactionState == SKPaymentTransactionStateFailed) {
  // invoke when a purchase fails
  [KongregateAPI.instance.analytics finishPurchase:KONG_PURCHASE_FAIL
                                 withTransactionId:transaction.transactionIdentifier
                                   withGameFields:gameFields];
}

// now you may finish the transaction
[SKPaymentQueue defaultQueue] finishTransaction:transaction]


Android Example

For Android it does not mater if the purchase is consumed before or after finishPurchase is invoked. The example below uses classes from the IabHelper Sample Code.

// invoke when user clicks buy
KongregateAPI kongAPI = APIBootstrap.getInstance();
String productId = "com.kongregate.mobile.games.angryBots.google.t05_coins";
HashMap<String,Object> eventMap = // game specific fields
kongAPI.analytics().startPurchase(productId, eventMap);

... // process transaction

IabResult result = ...;
Purchase purchase = ...;/
HashMap<String,Object> purchaseFields = // game specific fields to pass with result
if (result.isSuccess()) {
  if (receiptIsValidated) {
    // invoke when purchase is successful and receipt is verified
    kongApi.analytics().finishPurchase(AnalyticsServices.IabResult.SUCCESS,
                purchase.getOriginalJson(), purchaseFields, purchase.getSignature());
  } else {
    // invoke if the purchase was successful but the receipt is invalid
    kongApi.analytics().finishPurchase(AnalyticsServices.IabResult.RECEIPT_FAIL,
                                    purchase.getOriginalJson(), purchaseFields);

  }
} else {
  // invoke when a purchase fails
  kongApi.analytics().finishPurchase(AnalyticsServices.IabResult.FAIL, result.getMessage(), purchaseFields);

}

Unity Example

See the KongregateGameObject-Example.cs for a Unity implementation that uses the Prime31 plug-in.

NOTE: Some Unity plug-ins for iOS finish the transaction automatically and/or do not give you access to the transaction ID. We hope to have a work-a-round for these plug-ins in the future, but for now please use a plug-in w/o these limitations. The Prime31 plugin does provide all the required hooks for our SDK.

IAP Item Names

Kongregate uses naming conventions to enable the SDK to retrieve the price of the item in USD. Items must follow this naming convention for the system to work.

<bundle_id>.tXX_<type>, where <bundle_id> is the Google package name or apple bundle, XX is the tier level and type is the item type. For example com.kongregate.mobile.endlessbossfight.google.t02_hard might be a bundle name for a hard currency pack in Endless Boss Fight in the Google Play Store.

Install Referrals

Android Only The SDK now automatically tracks the google install referral data. The wrapped Adjust SDK also tracks the referral data.

Once you have an alpha build uploaded to the Google Play Store, you may use the Google Play URL Builder Tool to help verify referral tracking is working as expected. When the app is next launched the proper utm_campaign, utm_source, utm_medium, utm_term, utm_content, and utm_name values should all be reflected in the Adjust installs event.

Automatic Events and Fields

See Automatic Analytics Fields and Events for detailed breakdown of the events and fields the SDK will send in the various modes.

Adjust Only Events

You may send custom Adjust events by passing the event to the Analytics system using this format: adjust.abcdef, which abcdef is the Adjust token assigned to the event. Note, this is only for custom Adjust events your producer may ask your game to fire. You do not need to use this method for the 3 Adjust events the Kongregate SDK automatically fires (iap_transactions, installs, and session_starts).

KongregateAPI.GetAPI.Analytics.AddEvent("adjust.nnclzg", (string) null);