Skip to content

AppsFlyerSDK/appsflyer-cocos2dx-plugin

Repository files navigation

Cocos2dX AppsFlyer plugin for Android and iOS.


In order for us to provide optimal support, we would kindly ask you to submit any issues to support@appsflyer.com

When submitting an issue please specify your AppsFlyer sign-up (account) email , your app ID , production steps, logs, code snippets and any additional relevant information.


Table of content

  • Android AppsFlyer SDK v6.13.0
  • iOS AppsFlyer SDK v6.13.1

1. Set your Dev_Key and enable AppsFlyer to detect installations, sessions (app opens) and updates.

This is the minimum requirement to start measuring your app installs and is already implemented in this plugin. You MUST modify this call and provide: -devKey - Your application devKey provided by AppsFlyer. -appId - (For iOS only) Your iTunes Application ID.

Add the following lines into applicationDidFinishLaunching and to applicationWillEnterForeground method to be able to initialize measuring with your own AppsFlyer dev key:

#include "AppsFlyer/AppsFlyerX.h"

bool AppDelegate::applicationDidFinishLaunching() {
  AppsFlyerX::setAppsFlyerDevKey("YOUR_DEV_KEY");

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    AppsFlyerX::setAppleAppID("942960987");
#endif
  
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
    AppsFlyerX::start();
#endif
}

void AppDelegate::applicationWillEnterForeground() {
   //..
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
    AppsFlyerX::start();
#endif
}

Also notify AppsFlyer SDK about background event:

void AppDelegate::applicationDidEnterBackground() {

    //...
    AppsFlyerX::didEnterBackground();
}

Starting version 6.13.0, we support a manual mode to seperate the initialization of the AppsFlyer SDK and the start of the SDK. In this case, the AppsFlyer SDK won't start automatically, giving the developer more freedom when to start the AppsFlyer SDK. Please note that in manual mode, the developer is required to implement the API start() in order to start the SDK.
If you are using CMP to collect consent data this feature is needed. See explanation here.

Examples:

bool AppDelegate::applicationDidFinishLaunching() {
...
    AppsFlyerX::setAppsFlyerDevKey("devkey");

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    // In case you want to use manual mode. 
    AppsFlyerX::setManualStart(true);
    // 
    AppsFlyerX::setAppleAppID("appleAppId");
...
}
  • See that we aren't calling any AppsFlyerX::start() in any case. The init function is called in the background in order to catch any deeplinking.

And to start the AppsFlyer SDK:

Example:

//In case you use manual mode
 #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
     AppsFlyerX::setManualStart(false);
 #endif
 AppsFlyerX::start();
 // 

if true AppsFlyer SDK will run in debug mode

Example:

AppsFlyerX::setIsDebug(true);

if true AppsFlyer SDK will enter to pending mode, no activity Be sure to set stop(false) to release the SDK from stop measuring events

Example:

AppsFlyerX::stop(false); // or false

Use to prevent sharing data with some (one or more) networks/integrated partners.

parameter type description
eventName std::vector<std::string> list of partners

Example:

  std::vector<std::string> partners;
  partners.push_back("facebook_int");
  partners.push_back("googleadwords_int");
  AppsFlyerX::sharingFilter(partners);

Use to prevent sharing data with all networks/integrated partners.

Example:

AppsFlyerX::sharingFilterForAllPartners();

  • These in-app events help you track how loyal users discover your app, and attribute them to specific campaigns/media-sources. Please take the time define the event/s you want to measure to allow you to track ROI (Return on Investment) and LTV (Lifetime Value).
  • The logEvent method allows you to send in-app events to AppsFlyer analytics. This method allows you to add events dynamically by adding them directly to the application code.
parameter type description
eventName string custom event name, is presented in your dashboard. See the Event list HERE
eventValues cocos2d::ValueMap event details

Example:

//basic implementation
AppsFlyerX::logEvent(AFEventPurchase, {{ "key1", cocos2d::Value("value1")},
                                         { "key2", cocos2d::Value("value2")}});

//rich in-app-event implementation:
AppsFlyerX::logEvent(AFEventPurchase, {
                        { AFEventParamContentId, Value({Value("12344"), Value("98844"), Value("39944")})},
                        { AFEventParamCurrency, Value({Value(20), Value(11), Value(61)})},
                        { AFEventParamPrice, Value({Value(25), Value(50), Value(10)})},
                        { AFEventParamContentType, Value("ELECTRONIC")},
                        { AFEventParamCurrency, Value("USD")},
                        {AFEventParamRevenue, cocos2d::Value("10.67")}
                });

More info about rich in-app-events you can find HERE

AppsFlyer allows you to access the user attribution data in real-time directly at SDK level. It enables you to customize the landing page a user sees on the very first app open after a fresh app install.

To access AppsFlyer's conversion data from the Android SDK implement the ConversionDataListener callback:

Examples:

static void onConversionDataReceived(cocos2d::ValueMap installData) {}

static void onConversionDataRequestFailure(cocos2d::ValueMap map) {
/*has signature {
                 {"status": "failure"},
                 {"data", "errorMessage"}
                 }*/
}

static void onAppOpenAttribution(cocos2d::ValueMap map) {}

static void onAppOpenAttributionFailure(cocos2d::ValueMap map) {
/*has signature {
                 {"status": "failure"},
                 {"data", "errorMessage"}
                 }*/
}

AppsFlyerX::setOnConversionDataReceived(onConversionDataReceived);
AppsFlyerX::setOnConversionDataRequestFailure(onConversionDataRequestFailure);
AppsFlyerX::setOnAppOpenAttribution(onAppOpenAttribution);
AppsFlyerX::setOnAppOpenAttributionFailure(onAppOpenAttributionFailure);

AppsFlyer enables you to report one or more of the device’s associated email addresses. You must collect the email addresses and report it to AppsFlyer according to your required encryption method. The following encryption methods are available: SHA1, MD5, SHA256 and plain.

parameter type Default description
userEmails std::vector<std::string> --- list of emails
type EmailCryptTypeX --- crypt type: None, sha1, sha256, md5

Examples:

AppsFlyerX::setUserEmails({"kinzer.appsf@gmail.com"}, XEmailCryptTypeSHA256);

Setting your own Custom ID enables you to cross-reference your own unique ID with AppsFlyer’s user ID and the other devices’ IDs. This ID is available in AppsFlyer CSV reports along with postbacks APIs for cross-referencing with you internal IDs.

Note: The ID must be set during the first launch of the app at the SDK initialization. The best practice is to call this API during the deviceready event, where possible.

parameter type description
customerUserId const std::string&

Example:

AppsFlyerX::customerUserId("<USER_ID>");

parameter type Default description
currencyId const std::string& USD ISO 4217 Currency Codes

Examples:

AppsFlyerX::setCurrencyCode("<CURRENCY_ID>");

parameter type Default description
timeoutInterval double See additional info HERE

parameter type Default description
flag bool false disables AdvertiserIdentifier

Examples:

AppsFlyerX::disableAdvertiserIdentifier(true);

parameter type Default description
flag bool false enables/disables device name tracking

Examples:

AppsFlyerX::setShouldCollectDeviceName(true);

parameter type Default description
appInviteOneLinkID std::string& Before calling start in your app, set the OneLink which is invoked according to the OneLink ID. See additional info HERE

Examples:

AppsFlyerX::setAppInviteOneLink("8eOw");

parameter type Default description
flag bool false AppsFlyer provides you a method to opt-out specific users from AppsFlyer analytics. This method complies with the latest privacy requirements and complies with Facebook data and privacy policies. Default is false. Warning Opting out users SEVERELY hurts your attribution information. Use this option ONLY on regions which legally bind you from collecting your users' information.

Examples:

AppsFlyerX::anonymizeUser(true);

parameter type Default description
flag bool false enables/disables collect ASA

Examples:

AppsFlyerX::disableCollectASA(true);

parameter type Default description
flag bool false enables Receipt Validation Sandbox

Examples:

AppsFlyerX::setUseReceiptValidationSandbox(true);

parameter type Default description
flag bool false enables Uninstall Sandbox mode

Examples:

AppsFlyerX::setUseUninstallSandbox(true);

parameter type Default description
publicKey const std::string&
signature const std::string&
purchaseData const std::string&
price const std::string&
currency const std::string&
additionalParameters cocos2d::ValueMap

Examples:

ValueMap test_map;
test_map["key1"] = "value1";
std::string base64EncodedPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3dkBTr2pD2YSqSK2ewlEWwH9Llu0iA4PkwgVOyNRxOsHfrOlqi0Cm51qdNS0aqh/SMZkuQTAroqH3pAr9gVFOiejKRw+ymTaL5wB9+5n1mAbdeO2tv2FDsbawDvp7u6fIBejYt7Dtmih+kcu707fEO58HZWqgzx9qSHmrkMZr6yvHCtAhdBLwSBBjyhPHy7RAwKA+PE+HYVV2UNb5urqIZ9eI1dAv3RHX/xxHVHRJcjnTyMAqBmfFM+o31tp8/1CxGIazVN8HpVk8Qi2uqSS5HdKUu6VnIK8VuAHQbXQn4bG6GXx5Tp0SX1fKrejo7hupNUCgOlqsYHFYxsRkEOi0QIDAQAB";
std::string signature = "OaIdwQOcmrJrMKUx+URVy1I6aeKYiYzflkk1zIKVSs+dDv691neCbR+jlDDzVi3jfSkfirxQISxo7Pe1uzoYbpq9wBk/pMgVjjSbpvCojhA4d/Mwsf4mtAH2LJcVNjhMQdSWvGJlzva3OSt+KQ+9/pRJ15aYT2gFn3SpGSPxNxJmHPIOlM1Lr74MejVu9rnbcSjCB/oI0W4O58p9UWSt5MgmlpqlrK5YqTi1a1VnttY9r1IXFeltwZvmPbcWcYwRHFvemwYGX86huSOFBOYRfaYo9f+DinpoUoXKQEo0JrvKD2/dzFkbUTto1d2OPo1ddaYllgsb2UEV5wwFZFnemg==";
std::string purchaseData = "{\"orderId\":\"\",\"packageName\":\"com.appsflyer.testapp\",\"productId\":\"consumable\",\"purchaseTime\":1497531638107,\"purchaseState\":0,\"developerPayload\":\"2497525891514-5765886608164763986\",\"purchaseToken\":\"pfkalmpnnimamdllmincaida.AO-J1OymunlPCkDQZTf8bPcesoB0n1_ND3WFynoU91-v_R1Px46m3Q-DdRKNlxMVsP2pCTKpo1et1w1IpNVXQ8-zNpRo6a2nXP7a5fQWiDv2asL1dwJPCV8NghDHbstO084IlKo6xcgy\"}";
    
AppsFlyerX::validateAndLogInAppPurchase(base64EncodedPublicKey, 
                                          signature, 
                        "3.00",
                      "ILS",
                      test_map);

parameter type Default description
productIdentifier const std::string&
price const std::string&
currency const std::string&
tranactionId const std::string&
params cocos2d::ValueMap
successBlock std::function<void(cocos2d::ValueMap)>
failureBlock std::function<void(cocos2d::ValueMap)>

Examples:

ValueMap test_map;
test_map["key1"] = "value1";
std::string productIdentifier = "com.mycomp.inapppurchase.cons";
std::string tr_id = "1000000256672208";
  
AppsFlyerX::validateAndLogInAppPurchase(productIdentifier, 
                                          "1.99",
                                          "USD",
                                          tr_id
                      test_map, 
                      successBlock,
                      failureBlock);

Examples:

std::string appsflyerId = AppsFlyerX::getAppsFlyerUID();

  • void AppsFlyerX::handleOpenURL(const std::string& url, const std::string& sourceApplication)
  • void AppsFlyerX::handleOpenURL(std::string url, std::string sourceApplication, void* annotation)
  • void AppsFlyerX::handleOpenURL(std::string url, cocos2d::ValueMap options)

Examples:

TBD

Examples:

AppsFlyerX::registerUninstall("<TOKEN>");

For more Info see the DOCs

You can use the registerUninstall(void* deviceToken, unsigned long length) API.

or

As alternative way use directly native API: Open your Xcode project and locate the file AppController.mm under the iOS folder inside your project. Add the following code snippet under didFinishLaunchingWithOptions :

#import "AppsFlyerLib.h"

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//...
UIUserNotificationType userNotificationTypes = (UIUserNotificationTypeAlert |
                                                    UIUserNotificationTypeBadge |
                                                    UIUserNotificationTypeSound);
    UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:userNotificationTypes
                                                                             categories:nil];
    [application registerUserNotificationSettings:settings];
    [application registerForRemoteNotifications];
//..
}

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {    
    [[AppsFlyerLib shared] registerUninstall:deviceToken];
}

and method implementation:

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {    
    [[AppsFlyerLib shared] registerUninstall:deviceToken];
}

parameter type Default description
host std::string& host name that should override appsflyer.com
Examples:
AppsFlyerX::setHost("mynewhost.com");

parameter type Default description
minTimeBetweenSessions unsigned long host name that should override appsflyer.com
Examples:
AppsFlyerX::setMinTimeBetweenSessions(9);

Allows to pass GCM/FCM Tokens that where collected by third party plugins to the AppsFlyer server. Can be used for Uninstall measuring.

parameter type description
token String GCM/FCM Token

In ver. >4.2.5 deeplinking metadata (scheme/host) is sent automatically TBD

TBD

#import "AppsFlyerLib.h"

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//...
 AppsFlyerX::setDidResolveDeepLink(didResolveDeepLink);
//..
}
static void didResolveDeepLink(AppsFlyerXDeepLinkResult result){
    CCLOG("%s", "AppDelegate.cpp got ddl!");
    std::string ddl = "Deep link data is \n";
    switch (result.status) {
    case NOTFOUND:
            CCLOG("deep link not found");
            break;
        case FOUND:
            if (!result.deepLink.empty()){
                if (!result.getMediaSource().empty()) {
                    CCLOG("Media source is %s", result.getMediaSource().c_str());
                }
                for (auto &t : result.deepLink){
                    CCLOG("%s - %s", t.first.c_str(), t.second.asString().c_str());
                    ddl.append(t.first.c_str());
                    ddl.append(" : ");
                    ddl.append(t.second.asString().c_str());
                    ddl.append("\n");
                }
            }
    }
    }
}

Partners and advertisers can add more data in SDK events.

parameter type description
partnerId String partner identifier
data cocos2d::ValueMap data to add
  ValueMap data;
    data["thePartnerId"] = "abcd";
    data["Item_id"] = 1;
    data["isLegacy"] = false;
    AppsFlyerX::setPartnerData("partnerID", data);

Use to get conversion data with Branded links.

parameter type description
domains std::vector<std::string> list of custom domains

Example:

  std::vector<std::string> domains;
  domains.push_back("test.domain.com");
  domains.push_back("myDomain.com");
  AppsFlyerX::setOneLinkCustomDomain(domains);

Use to get conversion data with Branded links.

parameter type description
language std::string Language to set

Example:

  AppsFlyerX::setCurrentDeviceLanguage("English");

Used by advertisers to set some (one or more) networks/integrated partners to exclude from getting data.

parameter type description
partners std::vector<std::string> partners to exclude from getting data

Example:

  std::vector<std::string> partners;
  partners.push_back("partners_1");
  AppsFlyerX::setSharingFilterForPartners(partners); // Single partner

  std::vector<std::string> partners;
  partners.push_back("partners_1");
  partners.push_back("partners_2");
  AppsFlyerX::setSharingFilterForPartners(partners); // Multiple partner

  std::vector<std::string> partners;
  partners.push_back("all");
  AppsFlyerX::setSharingFilterForPartners(partners); // All partners

  std::vector<std::string> partners;
  partners.push_back("");
  AppsFlyerX::setSharingFilterForPartners(partners); // Reset list (default)

  std::vector<std::string> partners;
  AppsFlyerX::setSharingFilterForPartners(partners); // Reset list (default)

Use to opt-out of collecting the network operator name (carrier) and sim operator name from the device.

parameter type description
disable bool Defaults to false

Example:

  AppsFlyerX::setDisableNetworkData(true);

Migration Guide to v6

Integration guide Migration guide In v6 of AppsFlyer SDK there are some api breaking changes:

Before v6 v6
trackAppLaunch start
trackEvent logEvent
trackLocation logLocation
stopTracking stop
validateAndTrackInAppPurchase validateAndLogInAppPurchase
setDeviceTrackingDisabled anonymizeUser

iOS

on iOS you need to implement IDFA request pop up and add AppTrackTransparency framework in order for the plugin to work

For a general introduction to DMA consent data, see here. The SDK offers two alternative methods for gathering consent data:

  • Through a Consent Management Platform (CMP): If the app uses a CMP that complies with the Transparency and Consent Framework (TCF) v2.2 protocol, the SDK can automatically retrieve the consent details.

    OR

  • Through a dedicated SDK API: Developers can pass Google's required consent data directly to the SDK using a specific API designed for this purpose.

Use CMP to collect consent data

A CMP compatible with TCF v2.2 collects DMA consent data and stores it in SharedPreferences(Android) or NSUserDefaults(iOS). To enable the SDK to access this data and include it with every event, follow these steps:

  1. Call AppsFlyerX::enableTCFDataCollection(true) to instruct the SDK to collect the TCF data from the device.
  2. Set the the adapter to be manual(see (#manual-start)[manual mode]).
    This will allow us to delay the Conversion call to provide the SDK with the user consent.
  3. Use the CMP to decide if you need the consent dialog in the current session.
  4. If needed, show the consent dialog, using the CMP, to capture the user consent decision. Otherwise, go to step 6.
  5. Get confirmation from the CMP that the user has made their consent decision, and the data is available in SharedPreferences or NSUserDefaults.
  6. Call start the following way:
     #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
         AppsFlyerX::setManualStart(false);
     #endif
     AppsFlyerX::start();
    

AppDelegate

bool AppDelegate::applicationDidFinishLaunching() {

    AppsFlyerX::stop(false);
    AppsFlyerX::enableTCFDataCollection(true);
    AppsFlyerX::setIsDebug(true);
    AppsFlyerX::setAppsFlyerDevKey("devkey");

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    // In case you want to use manual mode. 
    AppsFlyerX::setManualStart(true);
    // 
    AppsFlyerX::setAppleAppID("appleAppId");

Scene class

  • after getting CMP results
 #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
     AppsFlyerX::setManualStart(false);
 #endif
 AppsFlyerX::start();

Manually collect consent data

If your app does not use a CMP compatible with TCF v2.2, use the SDK API detailed below to provide the consent data directly to the SDK.

  1. Initialize AppsFlyerX using manual mode. This will allow us to delay the Conversion call in order to provide the SDK with the user consent.
  2. Determine whether the GDPR applies or not to the user.
    - If GDPR applies to the user, perform the following:
    1. Given that GDPR is applicable to the user, determine whether the consent data is already stored for this session.
      1. If there is no consent data stored, show the consent dialog to capture the user consent decision.
      2. If there is consent data stored continue to the next step.
    2. To transfer the consent data to the SDK create an object called AppsFlyerXConsent using the forGDPRUser() method with the following parameters:
      - hasConsentForDataUsage - Indicates whether the user has consented to use their data for advertising purposes.
      - hasConsentForAdsPersonalization - Indicates whether the user has consented to use their data for personalized advertising purposes.
    3. Call AppsFlyerX::setConsentData() with the AppsFlyerXConsent object.
    4. Call start: #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) AppsFlyerX::setManualStart(false); #endif AppsFlyerX::start();

    - If GDPR doesn’t apply to the user perform the following:
    1. Create an AppsFlyerXConsent object using the forNonGDPRUser() method. This method doesn’t accept any parameters.
    2. Call AppsFlyerX::setConsentData() with the AppsFlyerXConsent object.
    3. Call start: #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) AppsFlyerX::setManualStart(false); #endif AppsFlyerX::start();