Unity Package Manager SDK Integration Guide

 

Before You Begin: SDK Prerequisites

1. Installing the SDK

WARNING: Are you upgrading from the ".unitypackage" to the "UPM" SDK version? You must perform specific upgrade steps, as noted below!
IMPORTANT: Perform these upgrade steps before proceeding with the UPM SDK install.

Upgrading requires manually removing the existing Singular SDK files, which were imported using the deprecated integration process from the .unitypackage.
This MUST be completed before importing the SDK with Unity Package Manager (UPM)!

Remove the following list of files before integrating the SDK using the Unity Package Manager (UPM). Use extra caution and be sure to only remove the Singular files as noted here:

  1. From the project's /Code folder:
    unity_upgrade_code_folder_file_removal.png

  2. From the project's /Plugins/Android folder, remove the AARs and JARs:
    unity_upgrade_plugin_android_folder_file_removal.png

  3. From the project's /Plugins/iOS folder, remove the iOS .h and .m files and the .xcframework:
    unity_upgrade_plugin_ios_folder_file_removal.png

1.1. Downloading and Importing the SDK Package

Installing the Singular Unity SDK using Unity Package Manager (UPM)
  1. In the Package Manager window:

IMPORTANT: If you are NOT using Google's EDM4U, follow these additional steps.
  1. Download the required dependencies from Singular's S3 bucket. For SDK Version 5.2.1, the Plugins.zip is: https://s3.us-west-2.amazonaws.com/maven.singular.net/unity/UPM-non-EDM4U/5.2.1/Plugins.zip
  2. The Extracted files should be moved to the Project Plugins folder.

1.2. Configuration for Android

TIP: How do you update the AndroidManifest when using Unity?
  1. From Unity v2018.3 onwards, you can add your own AndroidManifest file by simply enabling the Custom Main Manifest property on the Player window (which can be accessed by File > Build Settings > Player Settings > Publishing settings). This generates a default AndroidManifest.xml file for you, which you can edit.

    The file will be in the location Assets/Plugins/Android/AndroidManifest.xml

    Source: https://docs.unity3d.com/2023.2/Documentation/Manual/android-manifest.html

  2. Instead of using Unity's custom Main Manifest file, you may access the AndroidManifest.xml from Android Studio after exporting the App from Unity.

TIP: How to update Gradle settings when using Unity.
  1. From Unity v2018.3 onwards, you can add your own custom Gradle build file by simply enabling the Custom Gradle Template property on the Player window (which can be accessed by File > Build Settings > Player Settings > Publishing settings). This generates a default mainTemplate.gradle file for you to edit.

    The file will be in the location: Assets/Plugins/Android/mainTemplate.gradle

    Source: https://docs.unity3d.com/2023.2/Documentation/Manual/android-gradle-overview.html

  2. Instead of using Unity's custom Gradle build file, you may access the Apps build.gradle from Android Studio after exporting the App from Unity.

Are you using Proguard

If you are using Proguard, add the following lines of code to your proguard-unity.txt file:

-keep class com.singular.sdk.** { *; }
-keep public class com.android.installreferrer.** { *; }
-keep public class com.singular.unitybridge.** { *; }

1.3. Tips for iOS

TIP: Update Cocoa Pods after building in Unity and before building in Xcode.

We recommend initiating the following command from the folder where Pods is located.

pod repo update
pod update
TIP: Log the IDFV Identifier from applicationDidBecomeActive().

For testing on iOS, we recommend adding the following line of code in the: Classes > UnityAppController > applicationDidBecomeActive function.

// Printing Identifier for Vendor (IDFV) to Xcode Console for use in Singular SDK Console
NSLog(@"Singular === IDFV: %@", [[[UIDevice currentDevice] identifierForVendor] UUIDString]);

idfv.png

This will allow you to retrieve the IDFV identifier on the App Open in the Xcode Logs. Use this Identifier in the Singular SDK Console to add the test device.

idfv3.png

TIP: Deeplink Support Reminders
  1. Add the Associated Domain in Signing & Capabilities. Without the Associated Domain correctly configured, the App will NOT open when clicking a Singular Tracking Link.

  2. Validate that the Team ID has also been added to the App's Page in the Singular platform. This will allow Singular to build and host the required Apple App Site Association File to enable Universal Links functionality.

IMPORTANT: It is recommended to upgrade from the unitypackage to the UPM SDK as directed above. The content in this dropdown is for reference only.

Deprecated Singular unitypackage SDK and Kids SDK

Legacy: Downloading and Importing the Singular SDK ".unitypackage"

If you are upgrading from Version 4.3.2 or earlier?

Navigate to Assets > Plugins > iOS and remove the following files before importing the new unitypackage!

  • Attributes.h
  • Events.h
  • libSingular.a
  • Singular.h
  • SingularAdData.h
  • SingularConfig.h
  • SingularLinkParams.h
  1. Download the latest Singular Unity Package SDK unitypackage v4.4.2 file.
    or Download the Singular Unity Kids SDK Version 4.2.0 file.
  2. From the Unity Menu navigate to:

    • Assets > Import Package > Custom package
    • Select the downloaded unitypackage
    • Select Import
  3. If NOT using the Kids SDK: Do you plan to support Android 12 devices?

    Add the play-services-ads-identifier-18.0.1.aar file to your Assets/Plugins/Android/ folder so that Unity will include the required dependency to capture the Google Advertising Identifier. If you already have this dependency, you may skip this step.

  4. Update the AndroidManifest Permissions

    In your AndroidManifest.xml file, add the following permissions:

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="BIND_GET_INSTALL_REFERRER_SERVICE" />
    <uses-permission android:name="com.android.vending.CHECK_LICENSE" />
  5. If you have disabled transitive dependencies for the Singular SDK, add the following to your app's build.gradle.

    implementation 'com.android.installreferrer:installreferrer:2.2'
    implementation 'com.google.android.gms:play-services-appset:16.0.0'
  6. The Singular SDK requires the Google Mobile Ads API, part of the Google Play Services APIs 17.0.0+. If you've already integrated Google Play Services into your App, the requirement is fulfilled. If you haven't, you can integrate Google Mobile Ads individually by including the following dependency in your app's build.gradle file: (not required for the Kids SDK)

    implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1+'

    For more information, see Google's guide to setting up Google Play Services.

  7. Additional Configuration for iOS

    After building from Unity, Link the following libraries/frameworks to your Unity XCode project. Navigate to the UnityFramework Target, and choose Build Phases > Link Binary with Libraries. Add the following:

    • WebKit.framework
    • libsqlite3.0.tbd
    • libz.tbd
    • AdServices.framework (Must be added, but mark it as Optional since it's only available for devices with iOS 14.3 and higher). Also Required if you plan to run on Apple Search Ads!

    Important: The AdServices.framework is required in your App Build if you plan to utilize Apple Search Ad Campaigns and wish to track attribution.

  8. Create the SingularSDKObject in the next section using the Non-Prefab instructions HERE
  9. For iOS you must enable the "Add to Embedded Bin" option in the Inspection Pane. Navigate to Assets > Plugins > iOS and select the Singular.xcframework file, then in the Inspection Pane check the "Add to Embedded Bin" option.

    unity.png

2. SDK Integration

2.1. Create the SingularSDKObject

Add the SingularSDKObject to the Hierarchy

Add the SingularSDKObject using the Singular prefab object.

Move the Singular prefab object to the Hierarchy pane

  • From the Project pane, Navigate to: Packages > Singular > SingularSDK > Prefabs.
  • Move the SingularSDKObject into the Hierarchy pane.
    unity_prefab.png
If NOT using the prefab GameObject, manually add the "SingularSDKObject" GameObject, following these steps.

In the Hierarchy pane:

  1. Create an Empty GameObject in your Main scene.
  2. Name the GameObject: SingularSDKObject.
    IMPORTANT: The GameObject must be named "SingularSDKObject" for Singular's SDK to function.
  3. Click on the SingularSDKObject.
  4. Navigate to the Inspection Pane.
  5. From the Inspection pane, Click Add Component
  6. In the search field, type "Singular" and select the "Singular SDK" script. 
    unity_add_script.png

Configure the SingularSDKObject Settings

  1. In the Inspection pane for the SingularSDKObject, paste your Singular SDK Key and SDK Secret into the respective fields. To retrieve the SDK Key and Secret, log into your Singular account and go to "Developer Tools > SDK Integration > SDK Keys").

    sdk_keys.png
    IMPORTANT: DO NOT USE the Singular Reporting API Key or your SDK data will not be received. Follow the instructions above to retrieve the proper key and secret.
    unity_singularsdkobject_settings.png

    If the Singular SDK Key and Secret are incorrectly applied, data will not be sent to Singular.
    Test your implementation using the Singular SDK Console to verify correct behavior.

Note: Default Inspection Pane Settings for the SingularSDKObject:

The following options are enabled in the Inspection Pane:

  • Initialize On Awake (checked)

    This setting enables Unity to control the Singular SDK Initialization based on the Awake status of the App.

    Follow privacy compliance for your App requirements and update this option as required. Unchecking the option disables the initialization of the Singular SDK on the Awake status and would require manual Initialization.

  • SKAN Enabled (checked)

    Starting with Unity SDK version 4.0.17, SKAdNetwork is enabled by default. It is enabled in Managed Mode (in which Singular updates the SKAN conversion value for you using a conversion model you choose in the Singular dashboard).

  • Wait For Tracking Authorization, set to 0 (off)

    If your App is showing the App Tracking Transparency(ATT) prompt, setting this timeout to 300 seconds is recommended. Adding the timeout delays the Singular SDK session, allowing the User to authorize/deny AppTrackingTransparency Consent before logging events to Singular's servers. Once a User responds to the ATT prompt, the Singular SDK will continue without delay. This allows for capturing the IDFA identifier for Install Attribution when consent is provided. If you are not showing ATT, then the default value for this option should remain 0 (no wait).

  • Enable Logging (checked)

    Enables Logging from the Singular SDK. It must be used with the "Log Level" option.
    "Log Level" should be specified with an "int" number, as specified in the enum mapping below. The lower the number in this range - the more verbose the logs will be.

    //Based on Android Logger.java log levels enum: android.util.Log
    public enum LogLevel {
       Verbose = 2,
       Debug   = 3,
       Info    = 4,
       Warn    = 5,
       Error   = 6,
       Assert  = 7
       }

    Note: Currently, most logs are only available on Android.

  • Ddl Timeout Sec set to 0

    By default, the setting of "0" uses a 60-second timeout. This tells the Singular server how long to search for a deeplink value tied to the last touch attribution. If a deferred deep link is found, it is sent back to the app in the Response to the SDK Session Request and processed in the SingularLinkHandler. The server stops searching if no deferred deep link is found within 60 seconds.

  • Session Timeout Sec set to 0

    This is the timeout in seconds before the Singular SDK registers a new session when the app is backgrounded and returns to the foreground. By default, the setting of "0" uses a 60-second timeout. You may adjust this setting for a larger window if required.

  • Shortlink Resolve Timeout set to 0

    By default, the setting of "0" uses a 10-second timeout. This timeout protects the User experience. If the given shortlink is not resolved in the specified time, then the Singular SDK does not trigger a deeplink handler.

Other Inspection Pane Options:

Enable Facebook (META Install Referrer)

To support the META Install Referrer Attribution method, add your Facebook App ID to the Inspection Pane in the SingularSDKObject.

  1. Click on the SingularSDKObject in your Main Scene.
  2. Open the Inspection Pane and locate the "Facebook App ID" field.
  3. Add your Facebook App ID

2.2. Using SKAdNetwork

Starting with Unity SDK version 4.0.17, SKAdNetwork is enabled by default. It is enabled in Managed Mode (in which Singular updates the SKAN conversion value for you using a conversion model you choose in the Singular dashboard).

To use SKAdNetwork, you do not need to set anything else or add any code as long as you are using the latest SDK.

Additional Information

Enabling SKAdNetwork in Older Versions of the SDK

If you are using an older version of the SDK, you need to enable SKAdNetwork in one of the following ways:

  • Go to the SingularSDKObject and set SKANEnabled to True.
  • Call SingularSDK.SkanRegisterAppForAdNetworkAttribution() in your app code.
Using SKAdNetwork in Manual Mode (Advanced)

If you choose to manage the SKAN conversion value manually using your logic, you need to do the following:

  • Go to the SingularSDKObject and set manualSKANConversionManagement to True.
  • Use the following methods in your code to set and retrieve the conversion value.
SingularSDK.SkanUpdateConversionValue Method 
Description

Update the SKAdNetwork conversion value.

Note: Use this method if you have selected to update the SKAdNetwork conversion value manually. This method will work only if manualSKANConversionManagement is set to True.

Signature public void SkanUpdateConversionValue(int value)
Usage Example
// A sign-up event happened
Singular.Event("SignUp");

// Update the conversion value to 7
SingularSDK.SkanUpdateConversionValue(7);
SingularSDK.SkanGetConversionValue Method 
Description Get the current conversion value tracked by the Singular SDK.
Signature public int? SkanGetConversionValue()
Usage Example
int? value = SingularSDK.SkanGetConversionValue();
SingularSDK.SetConversionValueUpdatedHandler Method 
Description Set a handler to receive notifications when the conversion value is updated.
Signature public void SetConversionValueUpdatedHandler(SingularConversionValueUpdatedHandler handler)
Usage Example
public class Main : MonoBehaviour, SingularConversionValueUpdatedHandler {
  void Awake() {
    SingularSDK.SetConversionValueUpdatedHandler(this);
  }

  void OnConversionValueUpdated(int value) {
    // Use the conversion value
  }
}

2.3. Handling iOS App Tracking Transparency(ATT) Consent

Are you displaying the App Tracking Transparency(ATT) Prompt?

Starting with iOS 14.5, apps must ask for user consent (using the App Tracking Transparency framework) before they can access and share some user data, including the device's IDFA, which is helpful for tracking purposes.

Singular and Ad Networks greatly benefit from having the IDFA to identify devices and perform install attribution (although there are ways to do this without the IDFA). We strongly recommend asking for the user's consent to get the IDFA.

Delaying the Singular SDK Initialization is recommended until the User responds to the ATT prompt.

By default, the Singular SDK sends a user session when it is initialized. When a session is sent from a new device, it immediately triggers Singular's attribution process - which is performed based only on the data available to Singular at that point. Therefore, asking for consent and retrieving the IDFA before the Singular SDK sends the first session is essential.

TIP: If your App is showing the App Tracking Transparency(ATT) prompt, it is recommended that you set the timeout to 300 seconds. If you are not showing ATT, the default value for this option should remain 0 (no wait).

To configure the waitForTrackingAuthorizationWithTimeoutInterval adjust the configuration option in the SingularSDKObject Inspection pane. This sets the maximum time (in seconds) for the Singular SDK to wait for the User to authorize/deny AppTrackingTransparency Consent before logging events to Singular's servers.

2.4. Handling Deep Links

Deep links are URLs that direct users to specific content within an app. When a user clicks a deep link on a device with the app already installed, the app opens and displays a particular product or experience.

Singular tracking links can incorporate both deep linking and deferred deep linking. For more details, you can refer to our Deep Linking FAQ and the Singular Links FAQ.

Notes:

Expand the sections below for details on platform support and handler code:

Supporting deep linking on Android

Supporting deep linking on Android

  1. Open the Project > Assets > Plugins > Android > AndroidManifest.xml file in an editor.
  2. Update the activity name property from the default:
    <activity android:name="com.unity3d.player.UnityPlayerActivity"

    to:

    <activity android:name="com.singular.unitybridge.SingularUnityActivity"

    OR

    IMPORTANT: If you've implemented a custom activity:
    1. Add the import statement for the SingularUnityBridge where you are implementing onNewIntent.

      import com.singular.unitybridge.SingularUnityBridge;
    2. Call the SingularUnityBridge.onNewIntent(intent); from the onNewIntent method in your activity:

      Example:
      @Override
      protected void onNewIntent(Intent intent) {
          setIntent(intent);
      
          // Call this method from your custom activity in onNewIntent
          SingularUnityBridge.onNewIntent(intent);
      }

    WARNING: If you have created a custom activity for your app, and it does not extend (inherit from) the Unity Player Activity, then you may consider adding guards in the onNewIntent method to handle cases where the current activity object might be null.

  3. Add an Intent Filter in the appropriate activity to support Android App Scheme deep links with your chosen scheme.
    • Singular supports the Android App Scheme technology to open the App. It is recommended to NOT use a HOST attribute for improved flexibility.
    • In Singular, go to Apps Configuration, find your app, expand the Android App Advanced Settings, and paste the value in the Android App Scheme field. This will allow Singular to serve the scheme as an intent during the redirection of a Singular Tracking Link which is enabled for deep linking.
      If the scheme in the Singular platform does not match the AndroidManifest.xml Intent Filter configuration, the Singular Tracking Links will not open the App. If a specific combination of scheme and host are used, then the same combination must be configured in Singular platform.
    <!-- Added Intent Filter for Singular Android Scheme Deeplinking -->
    <!-- Replace singular-example with your value -->
    
    <intent-filter> <data android:scheme="singular-example"/> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.BROWSABLE"/> </intent-filter>
Supporting deep linking on iOS

Supporting deep linking on iOS

Singular uses iOS Universal Links and app schemes to deep link on iOS. Follow these steps to enable your app to use iOS Universal Links and app scheme deep linking with Singular Links. 

  1. Configure at least one sub-domain for your links in the Attribution > Manage Links page in Singular. For more information, see the Singular Links FAQ.
  2. To set up Universal Links (deep linking in iOS):
    • Log into the Apple Developer Portal.
    • Go to Identifiers and select the app that you want to add Universal Links support to.

      identifiers.png

    • In the Capabilities menu, check the Associated Domains checkbox, and click Save.

      associateddomains.png

  3. To add the "Associated Domains" entitlement to your app:
    • In XCode, go to Project settings > Capabilities > Associated Domains.

    • Add your Singular Links domains.

      associateddomains2.png

  4. Copy your "App Prefix" (AKA "Team ID") from the Apple Developer Portal.
  5. In Singular, go to Apps Configuration, find your app, expand the iOS App Advanced Settings, and paste the value in the Team ID field.  This will allow Singular to host the apple-app-site-association file in your Singular domain for the Universal Links.

    mceclip3.png

  6. Note: This step is required in cases where Universal Links cannot deep link. 
     Below the "Team ID", enter the iOS "App Scheme" to enable deep linking with traditional app scheme deep links as a fallback to Universal Link deep linking.
    mceclip4.png

    If this is the first time your app is supporting an iOS app scheme for deep linking, make sure the app scheme is registered as a "URL Type" in your Xcode project:
    Screenshot of Xcode showing the URL Types section with a URL that reads "com.example.myphotoapp."

    For more information on supporting app schemes for your iOS app, see Apple's developer help article on the topic.

2.5. Initializing the SDK

Note: When implementing the Singular SDKs, remember to comply with the various privacy laws enacted in regions where you do business, including GDPR, CCPA, COPPA, and others. For more information, see SDK Opt-In and Opt-Out Practices.

The SDK initialization code should be called every time your app is opened. It is a prerequisite to all Singular attribution functionality and sends a new session to Singular, which is used to calculate user retention.

By default, SingularSDK.cs initializes the SDK automatically when the scene is created through the Awake method.

Manual Initialization

If you prefer to initialize the SDK manually at a later point in the app's run, do the following:

  1. Disable the Initialize on Awake option in the inspection pane of the SingularSDK object.
  2. Use the SingularSDK.InitializeSingularSDK static method to initialize the SDK:
SingularSDK.InitializeSingularSDK Method
Description Initialize the Singular SDK if it hasn't been initialized on Awake.
Signature
public void InitializeSingularSDK()
Usage Example
// SDK Key and SDK Secret are set on the 
// game object associated with SingularSDK SingularSDK.InitializeSingularSDK();

Note on Thread Safety: The Singular Unity SDK should always be called from the same thread, just as you call other Unity methods.

2.6. Configuring the Session Timeout (Optional)

By default, if the app runs in the background for 60 seconds or more before returning to the foreground, the Singular SDK registers a new session. You can change the default timeout value by modifying the Session Timeout Sec property of your SingularSDKObject.

2.7. Sending the User ID to Singular (Optional)

You may send your internal User ID to Singular using a Singular SDK method.

Note: If you use Singular's Cross-Device solution, you must collect the User ID across all platforms.

  • The User ID can be any identifier and should not expose PII (Personally Identifiable Information). For example, you should not use a User's email address, username, or phone number. Singular recommends using a hashed value unique only to your first-party data.
  • The User ID value passed to Singular should also be the same internal User ID you capture across all platforms (Web/Mobile/PC/Console/Offline).
  • Singular will include the User ID in user-level exports, ETL, and Internal BI postbacks (if configured). The User ID is first-party data, and Singular does not share it with other parties.
  • When set with the Singular SDK Method, the User ID value persists until it is unset using the UnsetCustomUserId method or until the app is uninstalled. Closing or restarting the app does not unset the User ID.

To set the User ID, use the SetCustomUserId method. To unset it (for example, if the User "logs out" of the account), call UnsetCustomUserId.

Note: If multiple Users use a single device, we recommend implementing a logout flow to set and unset the User ID for each login and logout.

If you already know the user ID when the app opens, call SetCustomUserId before initializing the Singular SDK. This way, Singular can get the User ID from the first session. However, the User ID is typically unavailable until the User registers or performs a login. In that case, call SetCustomUserId after the registration flow is complete.

SingularSDK.SetCustomUserId Method
Description Send the user ID to Singular.
Signature public void SetCustomUserId(string customUserId)
Usage Example
SingularSDK.SetCustomUserId("custom_user_id");
SingularSDK.UnsetCustomUserId Method
Description Unset the user ID that has been sent to Singular.
Signature public void UnsetCustomUserId()
Usage Example
SingularSDK.UnsetCustomUserId();

Optional: Custom User ID Device Mapping

Important: This advanced Enterprise feature is only available in exceptional cases. Please consult with one of Singular’s Solution Engineers before implementing it.

Singular can receive additional mobile event tracking data via a server-to-server integration. To utilize this feature, you must map the User ID to Singular’s Mobile Device tracking identifier.

Note: Call this method as soon as possible after initializing the Singular SDK or once you have the User ID.

SingularSDK.SetDeviceCustomUserId Method
Description Sets the Custom User Id the same as login and maps it to Singular’s tracking identifier.
Signature public void SetDeviceCustomUserId(string customUserId)
Usage Example
SingularSDK.SetDeviceCustomUserId('CustomUserId');

3. Tracking Events and Revenue

3.1. Tracking Events (Non Revenue)

Singular can collect data about in-app events to help analyze the performance of your campaigns and measure KPIs. For example, your organization may want to collect data about user logins, registrations, tutorial completions, or leveling up in a gaming app.

Singular supports a variety of standard events. Ad networks often support these commonly used events for reporting and optimization. Another advantage is that when you use standard event names, Singular recognizes them automatically and adds them to the Events list without you having to define them manually. We recommend using standard events whenever possible.

The list of events sent to Singular (with the accompanying attributes) should be compiled by the UA/marketing/business team based on your organization's marketing KPIs. The business team can follow How to Track In-App Events: Guide For Singular Attribution Customers.

With each event you track, you can pass various attributes. See the recommended standard attributes per event.

Send standard events to Singular using the event or eventWithArgs methods in your code.

Note: For standard events, use the event's Unity name as it appears in the Unity SDK List of Standard Events and Attributes, e.g., sngLogin.

SingularSDK.Event(Events.sngLogin);

For custom events, events that your organization wants to measure that do not match any of Singular's standard events, use any custom name (maximum of 32 characters). We recommend using names in English for compatibility with any ad network partners that may receive the event from Singular for optimization purposes.

SingularSDK.Event Method
Description Send user events to Singular for tracking.
Signatures
public static void Event(string name)
public static void Event(string name, params object[] args)
public static void Event(Dictionary<string, object> args,
string name)
Note: When passing dictionaries, dictionary values must have one of these types: string, int, long, float, double, null, ArrayList, Dictionary<string, object>

Usage Example

// 1) Send the standard event Login
SingularSDK.Event(Events.sngLogin);
// 2) An example custom event passing two key value pairs
SingularSDK.Event("myEventName", "Key1", "Value1", "Key2", 1234);
// 3) An example JSON Event passing a dictionary
// Create a dictionary for attributes
Dictionary<string, object> attributes = new Dictionary<string, object>();

// Add attributes
attributes["key1"] = "value1";
attributes["key2"] = "value2";
attributes["key3"] = "value3";
// Add more attributes as needed

SingularSDK.Event(attributes, "myEventName");

3.2. Tracking Revenue

Singular can collect data about revenue gained through the app to help analyze the performance and ROI of your campaigns. Singular will make the data available in reports, log export, and postbacks.

Notes: Any revenue reported in a different currency will be auto-converted to your organization's preferred currency set in your Singular account.

You can track revenue events using Unity's built-in IAP (In-App Purchases) object. This way, Singular gets all the available information about the purchase for richer reporting. Singular also gets the purchase receipt, which Singular uses in the back end to validate the purchase and rule out attribution fraud.

SingularSDK.InAppPurchase Method
Description Send an IAP product to Singular to track the purchase event.
Signatures
public static void InAppPurchase(Product product,
Dictionary<string, object> attributes, bool isRestored = false)
public static void InAppPurchase(string eventName,
Product product, Dictionary<string, object> attributes,
bool isRestored = false)
public static void InAppPurchase(IEnumerable<Product> products,
Dictionary<string, object> attributes, bool isRestored = false)
public static void InAppPurchase(string eventName,
IEnumerable<Product> products, Dictionary<string, object>
attributes, bool isRestored = false)

Notes:

  • product is the product object received from IAP: UnityEngine.Purchasing.Product
  • attributes: Use this parameter to pass additional information to Singular. If you don't have any attributes to pass, just pass null.
  • isRestored: Indicate whether the transaction is restored. Default: false.
Usage Example
// IAP with a single product and no extra attributes
SingularSDK.InAppPurchase(myProduct, null);
// IAP with a single product and attributes
var attr = new Dictionary<string, object>() {
["my_first_attribute"] = "value1",
["my_second_attribute"] = "value2"};
 
SingularSDK.InAppPurchase(myProduct, attr);
// IAP with with a single product, 
// no extra attributes and a custom event name

SingularSDK.InAppPurchase("MyCustomProduct",
myProduct, null);
// IAP with list of products, no extra attributes
SingularSDK.InAppPurchase(myProductList, null);
// IAP with with list of products, no extra attributes
// and a custom event name

SingularSDK.InAppPurchase("MyCustomProducts",
myProductList, null);
Alternative Way to Track Revenue: Revenue and CustomRevenue Methods

If you cannot use Unity IAP, the Singular SDK provides two methods for passing information about a purchase to Singular "manually":

  • Use Revenue to pass information about a purchase to Singular by detailing the transaction currency, amount, and other optional details.
  • CustomRevenue is similar but allows you to give the event a custom name.

Note: If you use Revenue/CustomRevenue instead of InAppPurchase, Singular cannot verify the purchase receipt.

SingularSDK.Revenue Method
Description Send a revenue event to Singular.
Signatures
public static void Revenue(string currency, double amount)
public static void Revenue(string currency, double amount, string productSKU, string productName, string productCategory, int productQuantity, double productPrice)
public static void Revenue(string currency, double amount, Dictionary<string, object> attributes)
Note: Pass currency as a three-letter ISO 4217 currency code, such as "USD", "EUR", "INR".
Usage Example
// Send a revenue event with no product details
SingularSDK.Revenue("USD", 1.99);
// Send a revenue event with product details
SingularSDK.Revenue("USD", 4.99, "coin_package_abc123", "Coin Pack 5", "Bundles", 1, 4.99);
// Send a revenue event with JSON Dictionary for attributes
Dictionary<string, object> attributes = new Dictionary<string, object>();

// Add attributes attributes["productSKU"] = "coin_package_abc123"; attributes["productName"] = "Coin Pack 5"; attributes["productCategory"] = "Bundles"; attributes["productQuantity"] = 2; attributes["productPrice"] = 4.99;
SingularSDK.Revenue("USD", 9.98, attributes);
SingularSDK.CustomRevenue Method
Description Send a revenue event with a custom name to Singular.
Signatures
public static void CustomRevenue(string eventName, string currency, double amount)
public static void CustomRevenue(string eventName, string currency, double amount, string productSKU, string productName, string productCategory, int productQuantity, double productPrice)
public static void CustomRevenue(string eventName, string currency, double amount, Dictionary<string, object> attributes)
Note: Pass currency as a three-letter ISO 4217 currency code, such as "USD", "EUR", "INR".
Usage Example
// Send a revenue event with a custom name
SingularSDK.CustomRevenue("MyCustomRevenue", "USD", 9.99);
// Send a revenue event with a custom name + product details
SingularSDK.CustomRevenue("MyCustomRevenue", "USD", 50.50, "abc123", "myProductName", "myProductCategory", 2, 25.50);
// Send a revenue event with a custom name + JSON Dictionary for attributes
// Create a dictionary for attributes
Dictionary<string, object> attributes = new Dictionary<string, object>();

// Add attributes attributes["productSKU"] = "coin_package_abc123"; attributes["productName"] = "Coin Pack 5"; attributes["productCategory"] = "Bundles"; attributes["productQuantity"] = 2; attributes["productPrice"] = 4.99; // Add more attributes as needed SingularSDK.CustomRevenue("MyCustomRevenue", "USD", 9.98, attributes);

3.3. Hybrid Event Tracking (Advanced)

Singular recommends sending all events and revenue through the Singular SDK integrated into your app. However, Singular can collect events and revenue from other sources.

Any event NOT sent from the Singular SDK must comply with Singular's Server-to-Server Event documentation requirements and provide the matching device identifier to correctly attribute an event.

Important:

Discrepancies will occur if device identifiers used on Server-to-Server event requests do not have a matching device identifier in Singular. Be aware of the following possibilities:

  • If an event request is received "before" the Singular SDK has recorded the device identifier from an App Session, then the event request will be considered the "first session" for the unknown device and Singular will attribute the device as an organic attribution.
  • If the Singular SDK did record a device identifier, but the Singular SDK identifier differs from the device identifier specified in the Server-to-Server Event request, then the event will be attributed incorrectly.

Hybrid Event Tracking Guides

Sending Events from an Internal Server

Singular can collect data about revenue from your Server to help analyze the performance and ROI of your campaigns.

Requirements:

  • From an in-app Registration or Login Event, capture and pass the device identifiers and store this data with the User ID on your server. Because device identifiers may change for a user, be sure to update the identifiers when a user generates an app session. This guarantees the server-side event will be attributed to the correct device.
  • Server-side events are platform-specific and should only be sent with the device identifier matching the device platform (e.g., IDFA or IDFV for iOS devices).
  • You can use the Singular Internal BI postback mechanism to push an event in real-time to your internal endpoint so that you can update the data set on the server side. See the Internal BI Postback FAQ.
  • Review the "Tracking Revenue" section in the Server-to-Server Integration guide for details.
Sending Events from a Revenue Provider
Third-party providers like RevenueCat or adapty can provide Purchase and Subscription Revenue to Singular.

Follow the links below for details on how to enable these partners.

Sending Events from Segment

To enable Segment to send events to Singular, in parallel with the Singular SDK, you must add a "Cloud-Mode" Destination in Segment. Follow our guide HERE.

4. Advanced Options

4.1. Creating Short Referrer Links

Note: This functionality is available in SDK version 4.0.16+.

Use short links to transform long, parameter-filled Singular Links into shorter and more secure links that are convenient for sharing.

Typically, you will want to create short links dynamically so that your app's users can share them with friends to invite them to use the app.

To create a short link, you need:

  • A Singular Link that leads to your app download (see the Singular Links FAQ).
  • You can add any parameters you want to the link dynamically (see Tracking Link Parameters for the list of options).
  • If you want to track new app installs back to the user who shared the link, you must provide the Referrer Name and Referrer ID of the referring user.

Use the createReferrerShortLink method to create a short link, as in the example below.

void callback(string shortLinkURL, string error){
    // Add your share logic here if shortLinkURL is not null
    // If there was an error, add logic to retry/abort/modify the params
// passed to the function, based on the cause of the error } SingularSDK.createReferrerShortLink( "https://sample.sng.link/B4tbm/v8fp?_dl=https%3A%2F%2Fabc.com", "John Doe", // Referrer Name "342", // Referrer ID new Dictionary<string, string>() { // a Dictionary object containing any parameters you want to add {"channel", "sms"} }, callback );

4.2. Adding Ad Revenue Attribution Support

Singular is integrated with mediation platforms such as Google AdMob, AppLovin, Unity LevelPlay (IronSource), and TradPlus for ad revenue attribution. Singular also supports other mediation platforms through our generic ad revenue SDK integration.

You can get ad revenue attribution data from your mediation platform by adding a code snippet to your Singular SDK integration. This also allows you to get ad revenue data for SKAdNetwork campaigns.

Getting user-level ad revenue from your mediation platform enables Singular to send attributed ad revenue back to media sources that can accept this data to run AdROAS campaigns.

See instructions and code snippets for SDK Implementation [HERE].

4.3. Tracking Uninstalls

Note: Uninstall tracking is only available to Enterprise customers.

Android Uninstall Tracking

To enable uninstall tracking for your Android app, first configure the app in the Singular platform as detailed in Setting Up Uninstall Tracking. Then, follow the instructions below.

Note: Google deprecated the GCM APIs on April 2018. Use FCM for uninstall tracking.

Enabling Uninstall Tracking Using Firebase Cloud Messaging (FCM):

1. Integrate with FCM:

To track uninstalls, you can use the services of the Firebase Cloud Messaging (FCM) platform. If you are not already using FCM, follow Google's instructions on how to Set up a Firebase Cloud Messaging client app on Android.

FCM Requirements (source)

FCM clients require Android 4.1 or higher devices with the Google Play Store app installed or an emulator running Android 4.1 with Google APIs. Note that you are not limited to deploying your Android apps through the Google Play Store.

Users/devices not running on supported versions of Android will not be available for Singular uninstall tracking.

2. Update the AndroidManifest.xml File:

Update your AndroidManifest.xml file to add the necessary intent filter for your app (replace MyFirebaseMessagingService with your class that implements the Firebase Service):

<service android:name=".java.MyFirebaseMessagingService" android:exported="false">
  <intent-filter>
    <action android:name="com.google.firebase.MESSAGING_EVENT" />
  </intent-filter> 
</service>

3. Register and Send the FCM Device Token:

After retrieving the FCM token, pass it as a parameter to the 'RegisterTokenForUninstall' method:

SingularSDK.RegisterTokenForUninstall(String fcmDeviceToken);

The 'RegisterTokenForUninstall' method should be called before the 'SingularSDK.InitializeSingularSDK()' method.

iOS Uninstall Tracking

Uninstall tracking on iOS is based on Apple push-notification technology. If your app doesn't support push notifications, see Apple's guide. If your app already supports push notifications, you must pass the device token returned from APNS using the RegisterTokenForUninstall method after the SDK is initialized. 

SingularSDK.RegisterTokenForUninstall Method
Description Pass the device token returned from APNS. The APNS token is usually binary data in the native form, but you must pass it as a string.
Signature
public static void RegisterTokenForUninstall
(string APNSToken)
Usage Example
// pass the APNS token as a hex-string 
  SingularSDK.RegisterTokenForUninstall("ba85ab31a7c7
f5c2f012587f29fb0e596d4b67e7b7b2838fa1a8582c1f7dbdee");

4.4. Adding Global Properties

With every session and event sent from the app, the Singular SDK lets you define custom additional properties to send to the Singular servers. These properties can represent any information you want about the user, the app mode, status, or anything else. Once you set these properties, they are available as dimensions in your reports, and you can use them to break down your data.

For example, if you have a gaming app, you can define a property called "Level" and set it initially to "0". Any session and event sent from the app will be sent with "Level": "0". Once the user levels up, you reset the property to "1" and so on. You can then get your reports, including sessions, event counts, and revenue data, broken down by user level.

  • You can define up to 5 global properties.
  • They persist between app runs (with the latest value you gave them) until you unset them or the user uninstalls the app.
  • Each property name and value can be up to 200 characters long. If you pass a longer property name or value, it will be truncated to 200 characters.
  • Global properties are accessible and available in user-level exports and postbacks. In the future, aggregate reporting support will be added. Let your Singular customer success manager know if you have any questions or are interested in updates to global properties support!

Setting Global Properties Before Initialization

You can use the SetGlobalProperty method to set global properties through SingularSDK before initializing the SDK. If you want your global properties included in the session, turn off the 'Initialize On awake' flag

Since global properties and their values persist between app runs, the property you are setting may already be set to a different value. Use the overrideExisting parameter to tell the SDK whether to override an existing property with the new value.

Setting Global Properties After Initialization

You can use the following methods to set, unset, and retrieve global properties at any time during the app's run.

SingularSDK.SetGlobalProperty Method
Description

Set a global property to a given value.

Notes:

  • If the property does not exist yet and there are already 5 other global properties, it will not be added.
  • If the property has already been set, the overrideExisting parameter determines whether the existing value will be overridden.
  • The method returns true if the property was set successfully or false otherwise.
Signature public static bool SetGlobalProperty(string key, string value, bool overrideExisting)
Usage Example
bool result = SingularSDK.SetGlobalProperty("key", "value", false);
SingularSDK.GetGlobalProperties Method
Description Retrieve all the global properties and their current values as a Map.
Signature public static Dictionary<string, string> GetGlobalProperties()
Usage Example
Dictionary<string, string> props = SingularSDK.GetGlobalProperties();
SingularSDK.UnsetGlobalProperty Method
Description Remove a global property.
Signature public static void UnsetGlobalProperty(string key)
Usage Example
SingularSDK.UnsetGlobalProperty(“test_key”);
SingularSDK.ClearGlobalProperties Method
Description Remove all global properties.
Signature public static void ClearGlobalProperties()
Usage Example
SingularSDK.clearGlobalProperties();

4.5. Collecting the Install Referrer on Older Android Devices

In Android, the install referrer is Singular's most accurate tool for determining attribution and helping Singular detect and analyze fraud attempts. It is an identifier provided by the Google Play Store that points to the ad the user clicked on before installing the app.

On devices with the latest Google Play Store version, the Singular SDK automatically collects the install referrer value (since Singular is integrated with the latest Google Play Referrer API).

To collect the install referrer on older devices, follow the instructions in the Android SDK guide.

5. Complying with Data Privacy Laws

5.1. LimitDataSharing

Singular provides privacy-safeguarding functionality to help you cooperate with any partners who may be complying with consumer privacy laws such as GDPR and CCPA (California Consumer Privacy Act). These partners want to be notified if the end-user has consented to share their private information.

LimitDataSharing

If you have implemented a way to ask users for consent to share their information, use the limitDataSharing method to notify Singular of the user's choice:

  • Use limitDataSharing:NO to indicate that the user consented (opted in) to share their information.
  • Use limitDataSharing:YES if the user did not consent.

Singular uses LimitDataSharing in "User Privacy Postbacks" and passes this information on to partners who require it to comply with relevant regulations. See "User Privacy and Limit Data Sharing" for more information.

Note: The method's use is optional, but the partner may share attribution information with Singular only if specifically notified that the user has opted in.

SingularSDK.LimitDataSharing Method
Signature SingularSDK.LimitDataSharing(bool shouldLimitDataSharing)
Description Notify Singular of user consent (opt-in) for sharing private data. The Limit Data Sharing method gives you an option to control whether your app sends user data to third parties. This is useful if you want to restrict data sharing based on user preferences or privacy requirements.
Usage Example
// User has opted in to sharing data
SingularSDK.LimitDataSharing(false);

5.2. Additional Methods for GDPR Compliance

The Singular SDK provides several methods to help you comply with GDPR policies and let Singular know about user consent or non-consent for tracking.

SingularSDK.TrackingOptIn Method
Description Notify Singular of user consent (opt-in) for tracking. The TrackingOptIn() method is used to send a "gdpr" event to Singular's servers. If you don't call this method, the app will continue tracking users as if they have given consent, but it won't specifically mark them as GDPR opt-in. If your app needs to comply with GDPR (General Data Protection Regulation), you should call this function to ensure that user consent is properly recorded.
Usage Example
SingularSDK.TrackingOptIn();
SingularSDK.StopAllTracking Method
Description Stop all tracking activities for this user on this app.
Note: This method effectively disables the SDK, even after the app restarts (the state is persistent)! The only way to re-enable tracking is by calling resumeAllTracking().
Usage Example
SingularSDK.StopAllTracking();
SingularSDK.ResumeAllTracking Method
Description Resume tracking for this user on this app.
Usage Example
SingularSDK.ResumeAllTracking();
SingularSDK.IsAllTrackingStopped Method
Description Check the tracking status for this user on this app. Returns true if tracking has been stopped using StopAllTracking() and not resumed.
Usage Example
SingularSDK.IsAllTrackingStopped();