{"id":20643858,"url":"https://github.com/adjust/xamarin_sdk","last_synced_at":"2025-04-06T12:11:28.810Z","repository":{"id":31107702,"uuid":"34667066","full_name":"adjust/xamarin_sdk","owner":"adjust","description":"This is the Xamarin SDK of","archived":false,"fork":false,"pushed_at":"2025-01-31T10:31:19.000Z","size":72233,"stargazers_count":14,"open_issues_count":4,"forks_count":13,"subscribers_count":53,"default_branch":"master","last_synced_at":"2025-03-30T11:08:51.643Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://www.adjust.com","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/adjust.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-04-27T13:04:10.000Z","updated_at":"2025-01-31T10:30:54.000Z","dependencies_parsed_at":"2022-09-09T03:50:45.931Z","dependency_job_id":null,"html_url":"https://github.com/adjust/xamarin_sdk","commit_stats":null,"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adjust%2Fxamarin_sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adjust%2Fxamarin_sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adjust%2Fxamarin_sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adjust%2Fxamarin_sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/adjust","download_url":"https://codeload.github.com/adjust/xamarin_sdk/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247478324,"owners_count":20945266,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-16T16:14:07.655Z","updated_at":"2025-04-06T12:11:28.775Z","avatar_url":"https://github.com/adjust.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Summary\n\nThis is the Xamarin SDK of Adjust™. You can read more about Adjust™ at [adjust.com].\n\n## Table of contents\n\n* [Example apps](#example-apps)\n* [Basic integration](#basic-integration)\n   * [Get the SDK](#sdk-get)\n   * [Add the SDK from NuGet package manager](#sdk-add-nuget)\n   * [Add the SDK project reference to your app](#sdk-add-project)\n   * [Add the SDK DLL reference to your app](#sdk-add-dll)\n   * [Additional settings](#sdk-additional-settings)\n      * [[Android] Add Google Play Services](#android-gps)\n      * [[Android] Add permissions](#android-permissions)\n      * [[Android] Install referrer](#android-referrer)\n         * [Google Play Referrer API](#android-referrer-gpr-api)\n         * [Google Play Store intent](#android-referrer-gps-intent)\n      * [[Android] Proguard settings](#android-proguard)\n      * [[iOS] Additional linker flags](#ios-linker-flags)\n   * [Integrate the SDK into your app](#sdk-integrate)\n   * [Android session tracking](#session-tracking-android)\n      * [API level 14 and higher](#session-tracking-api14)\n      * [API level 9 until 13](#session-tracking-api9)\n   * [Adjust logging](#adjust-logging)\n   * [Build your app](#build-your-app)\n* [Additional features](#additional-features)\n   * [AppTrackingTransparency framework](#att-framework)\n      * [App-tracking authorisation wrapper](#ata-wrapper)\n      * [Get current authorisation status](#ata-getter)\n   * [SKAdNetwork framework](#skadn-framework)\n      * [Update SKAdNetwork conversion value](#skadn-update-conversion-value)\n      * [Conversion value updated callback](#skadn-cv-updated-callback)\n   * [Event tracking](#event-tracking)\n      * [Revenue tracking](#revenue-tracking)\n      * [Revenue deduplication](#revenue-deduplication)\n      * [Callback parameters](#callback-parameters)\n      * [Partner parameters](#partner-parameters)\n      * [Callback identifier](#callback-id)\n   * [Subscription tracking](#subscription-tracking)\n   * [Session parameters](#session-parameters)\n      * [Session callback parameters](#session-callback-parameters)\n      * [Session partner parameters](#session-partner-parameters)\n      * [Delay start](#delay-start)\n   * [Attribution callback](#attribution-callback)\n   * [Session and event callbacks](#session-event-callbacks)\n   * [Disable tracking](#disable-tracking)\n   * [Offline mode](#offline-mode)\n   * [Event buffering](#event-buffering)\n   * [GDPR right to be forgotten](#gdpr-forget-me)\n   * [Disable third-party sharing](#disable-third-party-sharing)\n   * [SDK signature](#sdk-signature)\n   * [Background tracking](#background-tracking)\n   * [Device IDs](#device-ids)\n      * [iOS Advertising Identifier](#di-idfa)\n      * [Google Play Services advertising identifier](#di-gps-adid)\n      * [Amazon advertising identifier](#di-fire-adid)\n      * [Adjust device identifier](#di-adid)\n   * [Set external device ID](#set-external-device-id)\n   * [Push token](#push-token)\n   * [Pre-installed trackers](#pre-installed-trackers)\n   * [Deep linking](#deeplinking)\n      * [Standard deep linking scenario](#deeplinking-standard)\n      * [Deep linking on iOS 8 and earlier](#deeplinking-setup-old)\n      * [Deep linking on iOS 9 and later](#deeplinking-setup-new)\n      * [Deferred deep linking scenario](#deeplinking-deferred)\n      * [Reattribution via deep links](#deeplinking-reattribution)\n   * [Data residency](#data-residency)\n* [License](#license)\n\n## \u003ca id=\"example-apps\"\u003e\u003c/a\u003eExample apps\n\nThere is an iOS example app inside the [`iOS` directory][demo-app-ios] and Android example app inside the [`Android` directory][demo-app-android]. You can open the Xamarin Studio / Visual Studio for Mac project to see an example on how the Adjust SDK can be integrated.\n\n## \u003ca id=\"basic-integration\"\u003e\u003c/a\u003eBasic integration\n\nWe will describe the steps to integrate the Adjust SDK into your Xamarin project. We are going to assume that you use Xamarin Studio or Visual Studio for your development.\n\n### \u003ca id=\"sdk-get\"\u003e\u003c/a\u003eGet the SDK\n\nDownload the latest version from our [releases page][releases] or via NuGet package manager. In case you want to add Adjust SDK to your app:\n\n- From NuGet package manager, continue from [this step](#sdk-add-nuget). \n- As project reference, continue from [this step](#sdk-add-project).\n- As DLL reference, continue from [this step](#sdk-add-dll).\n\n#### \u003ca id=\"sdk-add-nuget\"\u003e\u003c/a\u003eAdd the SDK from NuGet package manager\n\nRight click on the `Packages` under the project in the Solution Explorer, then click on `Add Packages...`. In the newly opened `Add Packages` window, type in the search box `\"Adjust Xamarin Android\"` for Android project, or `\"Adjust Xamarin iOS\"` for iOS project. The Adjust Xamarin Android/iOS package should be the first search result. Click on it, and in the bottom right corner, click on `Add Package`.\n\n### \u003ca id=\"sdk-add-project\"\u003e\u003c/a\u003eAdd the SDK as project reference\n\nChoose to add an existing project to your solution. Select the `AdjustSdk.Xamarin.iOS` project file and hit `Open`. Repeat the same process for `AdjustSdk.Xamarin.Android` project. After this, you will have the Adjust SDK bindings added as a submodule to your solution. After you have successfully added the Adjust SDK bindings project to your solution, you should also add a reference to it in your app project properties. In case you don't want to add reference to the Adjust SDK via project reference, you can skip this step and add it as DLL reference to your app which is explained in the step below.\n\n### \u003ca id=\"sdk-add-dll\"\u003e\u003c/a\u003eAdd the SDK as DLL reference\n\nThe next step is to add a reference to the bindings DLL in your project properties. In the references window, choose the `.Net Assembly` pane and select the `AdjustSdk.Xamarin.iOS.dll` and `AdjustSdk.Xamarin.Android.dll` that you have downloaded.\n\n### \u003ca id=\"sdk-additional-settings\"\u003e\u003c/a\u003eAdditional settings\n\nOnce the Adjust SDK has been added to your app, certain tweaks need to be performed so that the Adjust SDK can work properly. Below you can find a description of every additional thing that you need to do after you've added the Adjust SDK into to your app.\n\n### \u003ca id=\"android-gps\"\u003e\u003c/a\u003e[Android] Add Google Play Services\n\nSince the 1st of August of 2014, apps in the Google Play Store must use the Google Advertising ID to uniquely identify devices. To allow the Adjust SDK to use the Google Advertising ID, you must integrate Google Play Services. If you haven't done this yet, follow these steps:\n\n- Choose to `Add Packages` by your `Packages` folder in Android app project.\n- Search for `Xamarin Google Play Services - Analytics` and add them to your app.\n\n### \u003ca id=\"android-permissions\"\u003e\u003c/a\u003e[Android] Add permissions\n\nIn `Properties` folder, open the `AndroidManifest.xml` of your Android app project. Add the `Internet` and `AccessNetworkState` permission if it's not already there.\n\nIf you are **not targeting the Google Play Store**, add the `AccessWifiState` permission as well.\n\n#### \u003ca id=\"gps-adid-permission\"\u003e\u003c/a\u003eAdd permission to gather Google advertising ID\n\nIf you are targeting Android 12 and above (API level 31), you need to add the `com.google.android.gms.AD_ID` permission to read the device's advertising ID. Add the following line to your `AndroidManifest.xml` to enable the permission.\n\n```xml\n\u003cuses-permission android:name=\"com.google.android.gms.permission.AD_ID\"/\u003e\n```\n\nFor more information, see [Google's `AdvertisingIdClient.Info` documentation](https://developers.google.com/android/reference/com/google/android/gms/ads/identifier/AdvertisingIdClient.Info#public-string-getid).\n\n### \u003ca id=\"android-referrer\"\u003e\u003c/a\u003e[Android] Install referrer\n\nIn order to correctly attribute an install of your Android app to its source, Adjust needs information about the **install referrer**. This can be obtained by using the **Google Play Referrer API** or by catching the **Google Play Store intent** with a broadcast receiver.\n\n**Important**: The Google Play Referrer API is newly introduced by Google with the express purpose of providing a more reliable and secure way of obtaining install referrer information and to aid attribution providers in the fight against click injection. It is **strongly advised** that you support this in your application. The Google Play Store intent is a less secure way of obtaining install referrer information. It will continue to exist in parallel with the new Google Play Referrer API temporarily, but it is set to be deprecated in future.\n\n#### \u003ca id=\"android-referrer-gpr-api\"\u003e\u003c/a\u003eGoogle Play Referrer API\n\nGoogle Play Referrer API is already included in Adjust SDK. Nothing more needs to be done.\n\nAlso, make sure that you have paid attention to the [Proguard settings](#android-proguard) chapter and that you have added all the rules mentioned in it, especially the one needed for this feature:\n\n```\n-keep public class com.android.installreferrer.** { *; }\n```\n\nThis feature is supported if you are using the **Adjust SDK v4.12.0 or above**.\n\n#### \u003ca id=\"android-referrer-gps-intent\"\u003e\u003c/a\u003eGoogle Play Store intent\n\nThe Google Play Store `INSTALL_REFERRER` intent should be captured with a broadcast receiver. The Adjust install referrer broadcast receiver is added to your app by default. For more information, you can check our native [Android SDK README][broadcast-receiver]. We've included a class called `AdjustReferrerReceiver.cs` in our plugin which automatically captures that intent. The full name of the class is `com.adjust.binding.AdjustReferrerReceiver.cs`. Feel free to use it for testing install referrers by triggering it manually. More on that [here][testing-broadcast-receivers].\n\nPlease bear in mind that if you are using your own broadcast receiver which handles the `INSTALL_REFERRER` intent, you don't need to use Adjust broadcast receiver. Simply add the call to the Adjust broadcast receiver as described in our [Android guide][broadcast-receiver-custom] in your custom receiver.\n\n### \u003ca id=\"android-proguard\"\u003e\u003c/a\u003e[Android] Proguard settings\n\nIf you are using Proguard, add these lines to your Proguard file:\n\n```\n-keep class com.adjust.sdk.** { *; }\n-keep class com.google.android.gms.common.ConnectionResult {\n    int SUCCESS;\n}\n-keep class com.google.android.gms.ads.identifier.AdvertisingIdClient {\n    com.google.android.gms.ads.identifier.AdvertisingIdClient$Info getAdvertisingIdInfo(android.content.Context);\n}\n-keep class com.google.android.gms.ads.identifier.AdvertisingIdClient$Info {\n    java.lang.String getId();\n    boolean isLimitAdTrackingEnabled();\n}\n-keep public class com.android.installreferrer.** { *; }\n```\n\nIf you are **not targeting the Google Play Store**, you can remove the `com.google.android.gms` rules.\n\n### \u003ca id=\"ios-linker-flags\"\u003e\u003c/a\u003e[iOS] Additional linker flags\n\nAdjust SDK is able to get additional information by default linking weakly additional iOS frameworks to your app:\n\n- `AdSupport.framework` - This framework is needed so that SDK can access to IDFA value and (prior to iOS 14) LAT information.\n- `iAd.framework` - This framework is needed so that SDK can automatically handle attribution for ASA campaigns you might be running.\n- `AdServices.framework` - For devices running iOS 14.3 or higher, this framework allows the SDK to automatically handle attribution for ASA campaigns. It is required when leveraging the Apple Ads Attribution API.\n- `StoreKit.framework` - This framework is needed for access to `SKAdNetwork` framework and for Adjust SDK to handle communication with it automatically in iOS 14 or later.\n- `AppTrackingTransparency.framework` - This framework is needed in iOS 14 and later for SDK to be able to wrap user's tracking consent dialog and access to value of the user's consent to be tracked or not.\n\n### \u003ca id=\"sdk-integrate\"\u003e\u003c/a\u003eIntegrate the SDK into your app\n\nTo start with, we'll set up basic session tracking.\n\n---\n\n**For iOS app:**\n\nOpen the source file of your app delegate. Add the `using` statement at the top of the file, then add the following call to `Adjust` in the `FinishedLaunching` method of your app delegate:\n\n```cs\nusing AdjustBindingsiOS;\n\n// ...\n\nstring yourAppToken = \"{YourAppToken}\";\nstring environment = AdjustConfig.EnvironmentSandbox;\n\nvar config = ADJConfig.ConfigWithAppToken(yourAppToken, environment);\n\nAdjust.AppDidLaunch(config);\n```\n\n---\n\n**For Android app:**\n\nWe recommend using a global Android [Application][android_application] class to initialize the SDK. If don't have one in your app already, create a class that extends `Application`. In your `Application` class, find or create the `onCreate` method and add the following code to initialize the Adjust SDK:\n\n```cs\nusing Com.Adjust.Sdk;\n\n// ...\n\nstring appToken = \"{YourAppToken}\";\nstring environment = AdjustConfig.EnvironmentSandbox;\n\nvar config = new AdjustConfig(this, appToken, environment);\n\nAdjust.OnCreate(config);\n```\n\nPlease, pay special attention to [Android session tracking](#session-tracking-android) chapter as well, since it is vital for enabling proper session tracking for your Android app.\n\n---\n\nReplace `{YourAppToken}` with your app token. You can find this in your [dashboard].\n\nDepending on whether you build your app for testing or for production, you must set `environment` with one of these values:\n\n```cs\nstring environment = AdjustConfig.EnvironmentSandbox;\nstring environment = AdjustConfig.EnvironmentProduction;\n```\n\n**Important:** This value should be set to `AdjustConfig.EnvironmentSandbox` if and only if you or someone else is testing your app. Make sure to set the environment to `AdjustConfig.EnvironmentProduction` just before you publish the app. Set it back to `AdjustConfig.EnvironmentSandbox` when you start developing and testing it again.\n\nWe use this environment to distinguish between real traffic and test traffic from test devices. It is very important that you keep this value meaningful at all times! This is especially important if you are tracking revenue.\n\n### \u003ca id=\"session-tracking-android\"\u003e\u003c/a\u003eAndroid session tracking\n\n**Note**: This step is **really important** and please **make sure that you implement it properly in your app**. By implementing it, you will enable proper session tracking by the Adjust SDK in your app.\n\n### \u003ca id=\"session-tracking-api14\"\u003e\u003c/a\u003eAPI level 14 and higher\n\n- Add a private class that implements the `Java.Lang.Object` and  `IActivityLifecycleCallbacks` interface. If you don't have access to this interface, your app is targeting an Android API level inferior to 14. You will have to update manually each Activity by following these [instructions](#session-tracking-api9). If you had `Adjust.OnResume` and `Adjust.OnPause` calls on each Activity of your app before, you should remove them.\n- Edit the `OnActivityResumed(Activity activity)` method and add a call to `Adjust.OnResume()`. Edit the `OnActivityPaused(Activity activity)` method and add a call to `Adjust.OnPause()`.\n- After the adjust SDK is configured, add a call to the `RegisterActivityLifecycleCallbacks` method with an instance of the created `ActivityLifecycleCallbacks` class.\n\n    ```cs\n    using Com.Adjust.Sdk;\n\n    // ...\n\n    [Application(AllowBackup = true)]\n    public class GlobalApplication : Application\n    {\n        public GlobalApplication(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)\n        {\n        }\n\n        public override void OnCreate()\n        {\n            base.OnCreate();\n\n            string appToken = \"{YourAppToken}\";\n            string environment = AdjustConfig.EnvironmentSandbox;\n\n            var config = new AdjustConfig(this, appToken, environment);\n\n            Adjust.OnCreate(config);\n\n            RegisterActivityLifecycleCallbacks(new ActivityLifecycleCallbacks());\n        }\n\n        private class ActivityLifecycleCallbacks : Java.Lang.Object, IActivityLifecycleCallbacks\n        {\n            public void OnActivityPaused(Activity activity)\n            {\n                Adjust.OnPause();\n            }\n\n            public void OnActivityResumed(Activity activity)\n            {\n                Adjust.OnResume()\n            }\n\n            public void OnActivityCreated(Activity activity, Bundle savedInstanceState)\n            {\n            }\n\n            public void OnActivityDestroyed(Activity activity)\n            {\n            }\n\n            public void OnActivitySaveInstanceState(Activity activity, Bundle outState)\n            {\n            }\n\n            public void OnActivityStarted(Activity activity)\n            {\n            }\n\n            public void OnActivityStopped(Activity activity)\n            {\n            }\n        }\n    }\n    ```\n\n### \u003ca id=\"session-tracking-api9\"\u003e\u003c/a\u003eAPI level 9 until 13\n\nIf your app's minimal supported API level is between `9` and `13`, consider updating it to at least `14` to simplify the integration process in the long term. Consult the official Android [dashboard][android-dashboard] to know the latest market share of the major versions.\n\nIf you still want to target these lower API levels, in order to provide proper session tracking it is required to call certain Adjust SDK methods every time any Activity resumes or pauses. Otherwise the SDK might miss a session start or session end. In order to do so you should **follow these steps for each Activity of your app**:\n\n- Open the source file of your Activity.\n- Add the `using` statement at the top of the file.\n- In your Activity's `OnResume` method call `Adjust.OnResume`. Create the method if needed.\n- In your Activity's `OnPause` method call `Adjust.OnPause`. Create the method if needed.\n\nAfter these steps your activity should look like this:\n\n```cs\nusing Com.Adjust.Sdk;\n\n// ...\n\n[Activity(Label = \"Example\", MainLauncher = true)]\npublic class MainActivity : Activity\n{\n    protected override void OnCreate(Bundle savedInstanceState)\n    {\n        base.OnCreate(savedInstanceState);\n    }\n\n    protected override void OnResume()\n    {\n        base.OnResume();\n\n        Adjust.OnResume();\n    }\n\n    protected override void OnPause()\n    {\n        base.OnPause();\n\n        Adjust.OnPause();\n    }\n}\n```\n\nRepeat these steps for **every** Activity of your app. Don't forget these steps when you create new Activities in the future. Depending on your coding style you might want to implement this in a common superclass of all your Activities.\n\n### \u003ca id=\"adjust-logging\"\u003e\u003c/a\u003eAdjust logging\n\n**For iOS app:**\n\nYou can increase or decrease the amount of logs you see in tests by setting `LogLevel` property on your `ADJConfig` instance with one of the following parameters:\n\n```cs\nconfig.LogLevel = ADJLogLevel.Verbose;  // enable all logging\nconfig.LogLevel = ADJLogLevel.Debug;    // enable more logging\nconfig.LogLevel = ADJLogLevel.Info;     // the default\nconfig.LogLevel = ADJLogLevel.Warn;     // disable info logging\nconfig.LogLevel = ADJLogLevel.Error;    // disable warnings as well\nconfig.LogLevel = ADJLogLevel.Assert;   // disable errors as well\nconfig.LogLevel = ADJLogLevel.Suppress; // disable all logging\n```\n\nIf you don't want your app in production to display any logs coming from the Adjust SDK, then you should select `ADJLogLevel.Suppress` and in addition to that, initialise `ADJConfig` object with another constructor where you should enable suppress log level mode:\n\n```cs\nusing AdjustBindingsiOS;\n\n// ...\n\nstring yourAppToken = \"{YourAppToken}\";\nstring environment = AdjustConfig.EnvironmentSandbox;\n\nvar config = ADJConfig.ConfigWithAppToken(yourAppToken, environment);\nconfig.LogLevel = ADJLogLevel.Suppress;\n\nAdjust.AppDidLaunch(config);\n```\n\n---\n\n**For Android app:**\n\nYou can increase or decrease the amount of logs you see in tests by calling `SetLogLevel` on your `AdjustConfig` instance with one of the following parameters:\n\n```cs\nconfig.SetLogLevel(LogLevel.Verbose);     // enable all logging\nconfig.SetLogLevel(LogLevel.Debug);       // enable more logging\nconfig.SetLogLevel(LogLevel.Info);        // the default\nconfig.SetLogLevel(LogLevel.Warn);        // disable info logging\nconfig.SetLogLevel(LogLevel.Error);       // disable warnings as well\nconfig.SetLogLevel(LogLevel.Assert);      // disable errors as well\nconfig.SetLogLevel(LogLevel.Supress);    // disable all logging\n```\n\nIf you don't want your app in production to display any logs coming from the adjust SDK, then you should select `LogLevel.Supress` and in addition to that, initialise `AdjustConfig` object with another constructor where you should enable suppress log level mode:\n\n```cs\nusing Com.Adjust.Sdk;\n\n// ...\n\nstring appToken = \"{YourAppToken}\";\nstring environment = AdjustConfig.EnvironmentSandbox;\n\nAdjustConfig config = new AdjustConfig(this, appToken, environment, true);\nconfig.SetLogLevel(LogLevel.Supress);\n\nAdjust.OnCreate(config);\n```\n\n### \u003ca id=\"build-your-app\"\u003e\u003c/a\u003eBuild your app\n\nBuild and run your app. If the build succeeds, you should carefully read the SDK logs in the console. After the app launched for the first time, you should see the info log `Install tracked`.\n\n## \u003ca id=\"additional-features\"\u003e\u003c/a\u003eAdditional features\n\nOnce you integrate the Adjust SDK into your app, you can take advantage of the following features.\n\n### \u003ca id=\"att-framework\"\u003e\u003c/a\u003e[iOS] AppTrackingTransparency framework\n\nFor each package sent, the Adjust backend receives one of the following four (4) states of consent for access to app-related data that can be used for tracking the user or the device:\n\n- Authorized\n- Denied\n- Not Determined\n- Restricted\n\nAfter a device receives an authorization request to approve access to app-related data, which is used for user device tracking, the returned status will either be Authorized or Denied.\n\nBefore a device receives an authorization request for access to app-related data, which is used for tracking the user or device, the returned status will be Not Determined.\n\nIf authorization to use app tracking data is restricted, the returned status will be Restricted.\n\nThe SDK has a built-in mechanism to receive an updated status after a user responds to the pop-up dialog, in case you don't want to customize your displayed dialog pop-up. To conveniently and efficiently communicate the new state of consent to the backend, Adjust SDK offers a wrapper around the app tracking authorization method described in the following chapter, App-tracking authorization wrapper.\n\n### \u003ca id=\"ata-wrapper\"\u003e\u003c/a\u003e[iOS] App-tracking authorisation wrapper\n\nAdjust SDK offers the possibility to use it for requesting user authorization in accessing their app-related data. Adjust SDK has a wrapper built on top of the [requestTrackingAuthorizationWithCompletionHandler:](https://developer.apple.com/documentation/apptrackingtransparency/attrackingmanager/3547037-requesttrackingauthorizationwith?language=objc) method, where you can as well define the callback method to get information about a user's choice. Also, with the use of this wrapper, as soon as a user responds to the pop-up dialog, it's then communicated back using your callback method. The SDK will also inform the backend of the user's choice. The `nuint` status value will be delivered via your callback method with the following meaning:\n\n- 0: `ATTrackingManagerAuthorizationStatusNotDetermined`\n- 1: `ATTrackingManagerAuthorizationStatusRestricted`\n- 2: `ATTrackingManagerAuthorizationStatusDenied`\n- 3: `ATTrackingManagerAuthorizationStatusAuthorized`\n\nTo use this wrapper, you can call it as such:\n\n```cs\nAdjust.RequestTrackingAuthorization((status) =\u003e {\n    switch (status) {\n        case 0:\n            // ATTrackingManagerAuthorizationStatusNotDetermined case\n            break;\n        case 1:\n            // ATTrackingManagerAuthorizationStatusRestricted case\n            break;\n        case 2:\n            // ATTrackingManagerAuthorizationStatusDenied case\n            break;\n        case 3:\n            // ATTrackingManagerAuthorizationStatusAuthorized case\n            break;\n    }\n});\n```\n\n### \u003ca id=\"ata-getter\"\u003e\u003c/a\u003e[iOS] Get current authorisation status\n\nTo get the current app tracking authorization status you can get the value of `AppTrackingAuthorizationStatus` property of `Adjust` class that will return one of the following possibilities:\n\n* `0`: The user hasn't been asked yet\n* `1`: The user device is restricted\n* `2`: The user denied access to IDFA\n* `3`: The user authorized access to IDFA\n* `-1`: The status is not available\n\n### \u003ca id=\"skadn-framework\"\u003e\u003c/a\u003e[iOS] SKAdNetwork framework\n\nIf you have implemented the Adjust Xamarin SDK v4.23.0 or above and your app is running on iOS 14 and above, the communication with SKAdNetwork will be set on by default, although you can choose to turn it off. When set on, Adjust automatically registers for SKAdNetwork attribution when the SDK is initialized. If events are set up in the Adjust dashboard to receive conversion values, the Adjust backend sends the conversion value data to the SDK. The SDK then sets the conversion value. After Adjust receives the SKAdNetwork callback data, it is then displayed in the dashboard.\n\nIn case you don't want the Adjust SDK to automatically communicate with SKAdNetwork, you can disable that by calling the following method on configuration object:\n\n```cs\nadjustConfig.DeactivateSKAdNetworkHandling();\n```\n\n### \u003ca id=\"skadn-update-conversion-value\"\u003e\u003c/a\u003e[iOS] Update SKAdNetwork conversion value\n\nYou can use Adjust SDK wrapper method `UpdateConversionValue` to update SKAdNetwork conversion value for your user:\n\n```cs\nAdjust.UpdateConversionValue(6);\n```\n\n### \u003ca id=\"skadn-cv-updated-callback\"\u003e\u003c/a\u003e[iOS] Conversion value updated callback\n\nYou can register callback to get notified each time when Adjust SDK updates conversion value for the user.\n\n```cs\npublic class AdjustDelegateXamarin : AdjustDelegate\n{\n    public override void AdjustConversionValueUpdated(NSNumber conversionValue)\n    {\n        Console.WriteLine(\"adjust: Conversion value updated! Covnersion value: \" + conversionValue.ToString());\n    }\n}\n```\n\n### \u003ca id=\"event-tracking\"\u003e\u003c/a\u003eEvent tracking\n\nYou can use Adjust to track events. Let's say you want to track every tap on a particular button. You would create a new event token in your [dashboard], which has an associated event token - resembling something like `abc123`. In your button's `TouchUpInside` handler you would then add the following lines to track the tap:\n\n**For iOS app:**\n\n```cs\nvar adjustEvent = ADJEvent.EventWithEventToken(\"abc123\");\nAdjust.TrackEvent(adjustEvent);\n```\n\n**For Android app:**\n\n```cs\nAdjustEvent eventClick = new AdjustEvent(\"abc123\");\nAdjust.TrackEvent(eventClick);\n```\n\nWhen tapping the button you should now see `Event tracked` in the logs.\n\n### \u003ca id=\"revenue-tracking\"\u003e\u003c/a\u003eRevenue tracking\n\nIf your users can generate revenue by tapping on advertisements or making In-App Purchases you can track those revenues with events. Let's say a tap is worth one Euro cent. You could then track the revenue event like this:\n\n**For iOS app:**\n\n```cs\nvar adjustEvent = ADJEvent.EventWithEventToken(\"abc123\");\nadjustEvent.SetRevenue(0.01, \"EUR\");\nAdjust.TrackEvent(adjustEvent);\n```\n\n**For Android app:**\n\n```cs\nAdjustEvent eventRevenue = new AdjustEvent(\"abc123\");\nadjustEvent.SetRevenue(0.01, \"EUR\");\nAdjust.TrackEvent(adjustEvent);\n```\n\nWhen you set a currency token, Adjust will automatically convert the incoming revenues into a reporting revenue of your choice. Read more about [currency conversion here][currency-conversion].\n\nYou can read more about revenue and event tracking in the [event tracking guide][event-tracking].\n\n### \u003ca id=\"revenue-deduplication\"\u003e\u003c/a\u003eRevenue deduplication\n\nYou can also add an optional transaction ID to avoid tracking duplicate revenues. The last ten transaction IDs are remembered, and revenue events with duplicate transaction IDs are skipped. This is especially useful for In-App Purchase tracking. You can see an example below. Please make sure to call the `TrackEvent` only if the transaction is finished and item is purchased.\n\n**For iOS app:**\n\n```cs\nvar adjustEvent = ADJEvent.EventWithEventToken(\"abc123\");\nadjustEvent.SetRevenue(0.01, \"EUR\");\nadjustEvent.SetTransactionId(\"{TransactionIdentifier}\");\nAdjust.TrackEvent(adjustEvent);\n```\n\n**For Android app:**\n\n```cs\nAdjustEvent adjustEvent = new AdjustEvent(\"abc123\");\nadjustEvent.SetRevenue(0.01, \"EUR\");\nadjustEvent.SetOrderId(\"YourOrderId\");\nAdjust.TrackEvent(adjustEvent);\n```\n\n### \u003ca id=\"callback-parameters\"\u003e\u003c/a\u003eCallback parameters\n\nYou can register a callback URL for your events in your [dashboard]. We will send a GET request to that URL whenever the event is tracked. You can add callback parameters to that event by calling `AddCallbackParameter` on the event before tracking it. We will then append these parameters to your callback URL.\n\nFor example, suppose you have registered the URL `http://www.adjust.com/callback` then track an event like this:\n\n**For iOS app:**\n\n```cs\nvar adjustEvent = ADJEvent.EventWithEventToken(\"abc123\");\nadjustEvent.AddCallbackParameter(\"key\", \"value\");\nadjustEvent.AddCallbackParameter(\"foo\", \"bar\");\nAdjust.TrackEvent(adjustEvent);\n```\n\n**For Android app:**\n\n```cs\nAdjustEvent adjustEvent = new AdjustEvent(\"abc123\");\nadjustEvent.AddCallbackParameter(\"key\", \"value\");\nadjustEvent.AddCallbackParameter(\"foo\", \"bar\");\nAdjust.TrackEvent(adjustEvent);\n```\n\nIn that case we would track the event and send a request to:\n\n```\nhttp://www.adjust.com/callback?key=value\u0026foo=bar\n```\n\nIt should be mentioned that we support a variety of placeholders like `{idfa}` or `{gps_adid}` that can be used as parameter values. In the resulting callback this placeholder would be replaced with the ID for Advertisers of the current device. Also note that we don't store any of your custom parameters, but only append them to your callbacks. If you haven't registered a callback for an event, these parameters won't even be read.\n\nYou can read more about using URL callbacks, including a full list of available values, in our [callbacks guide][callbacks-guide].\n\n### \u003ca id=\"partner-parameters\"\u003e\u003c/a\u003ePartner parameters\n\nYou can also add parameters to be transmitted to network partners, for the integrations that have been activated in your Adjust dashboard. This works similarly to the callback parameters mentioned above, but can be added by calling the `AddPartnerParameter` method on your `ADJEvent`/`AdjustEvent` instance.\n\n**For iOS app:**\n\n```cs\nvar adjustEvent = ADJEvent.EventWithEventToken(\"abc123\");\nadjustEvent.AddPartnerParameter(\"key\", \"value\");\nadjustEvent.AddPartnerParameter(\"foo\", \"bar\");\nAdjust.TrackEvent(adjustEvent);\n```\n\n**For Android app:**\n```cs\nAdjustEvent adjustEvent = new AdjustEvent(\"abc123\");\nadjustEvent.AddPartnerParameter(\"key\", \"value\");\nadjustEvent.AddPartnerParameter(\"foo\", \"bar\");\nAdjust.TrackEvent(adjustEvent);\n```\n\nYou can read more about special partners and these integrations in our [guide to special partners][special-partners].\n\n### \u003ca id=\"callback-id\"\u003e\u003c/a\u003eCallback identifier\n\nYou can also add custom string identifier to each event you want to track. This identifier will later be reported in event success and/or event failure callbacks to enable you to keep track on which event was successfully tracked or not. You can set this identifier by calling the `SetCallbackId` method on your `ADJEvent`/`AdjustEvent` instance:\n\n**For iOS apps:**\n\n```cs\nvar adjustEvent = ADJEvent.EventWithEventToken(\"abc123\");\nadjustEvent.SetCallbackId(\"Your-Custom-Id\");\nAdjust.TrackEvent(adjustEvent);\n```\n\n**For Android apps:**\n\n```cs\nAdjustEvent adjustEvent = new AdjustEvent(\"abc123\");\nadjustEvent.SetCallbackId(\"Your-Custom-Id\");\nAdjust.TrackEvent(adjustEvent);\n```\n\n### \u003ca id=\"subscription-tracking\"\u003e\u003c/a\u003eSubscription tracking\n\n**Note**: This feature is only available in the SDK v4.22.0 and above.\n\nYou can track App Store and Play Store subscriptions and verify their validity with the Adjust SDK. After a subscription has been successfully purchased, make the following call to the Adjust SDK:\n\n**For App Store subscription:**\n\n```cs\nADJSubscription subscription = new ADJSubscription(price, currency, transactionId, receipt);\nsubscription.SetTransactionDate(transactionDate);\nsubscription.SetSalesRegion(salesRegion);\n\nAdjust.TrackSubscription(subscription);\n```\n\n**For Play Store subscription:**\n\n```cs\nAdjustPlayStoreSubscription subscription = new AdjustPlayStoreSubscription(\n    price,\n    currency,\n    sku,\n    orderId,\n    signature,\n    purchaseToken);\nsubscription.SetPurchaseTime(purchaseTime);\n\nAdjust.TrackPlayStoreSubscription(subscription);\n```\n\nSubscription tracking parameters for App Store subscription:\n\n- [price](https://developer.apple.com/documentation/storekit/skproduct/1506094-price?language=objc)\n- currency (you need to pass [currencyCode](https://developer.apple.com/documentation/foundation/nslocale/1642836-currencycode?language=objc) of the [priceLocale](https://developer.apple.com/documentation/storekit/skproduct/1506145-pricelocale?language=objc) object)\n- [transactionId](https://developer.apple.com/documentation/storekit/skpaymenttransaction/1411288-transactionidentifier?language=objc)\n- [receipt](https://developer.apple.com/documentation/foundation/nsbundle/1407276-appstorereceipturl)\n- [transactionDate](https://developer.apple.com/documentation/storekit/skpaymenttransaction/1411273-transactiondate?language=objc)\n- salesRegion (you need to pass [countryCode](https://developer.apple.com/documentation/foundation/nslocale/1643060-countrycode?language=objc) of the [priceLocale](https://developer.apple.com/documentation/storekit/skproduct/1506145-pricelocale?language=objc) object)\n\nSubscription tracking parameters for Play Store subscription:\n\n- [price](https://developer.android.com/reference/com/android/billingclient/api/SkuDetails#getpriceamountmicros)\n- [currency](https://developer.android.com/reference/com/android/billingclient/api/SkuDetails#getpricecurrencycode)\n- [sku](https://developer.android.com/reference/com/android/billingclient/api/Purchase#getsku)\n- [orderId](https://developer.android.com/reference/com/android/billingclient/api/Purchase#getorderid)\n- [signature](https://developer.android.com/reference/com/android/billingclient/api/Purchase#getsignature)\n- [purchaseToken](https://developer.android.com/reference/com/android/billingclient/api/Purchase#getpurchasetoken)\n- [purchaseTime](https://developer.android.com/reference/com/android/billingclient/api/Purchase#getpurchasetime)\n\nJust like with event tracking, you can attach callback and partner parameters to the subscription object as well:\n\n**For App Store subscription:**\n\n```cs\nADJSubscription subscription = new ADJSubscription(price, currency, transactionId, receipt);\nsubscription.SetTransactionDate(transactionDate);\nsubscription.SetSalesRegion(salesRegion);\n\n// add callback parameters\nsubscription.AddCallbackParameter(\"key\", \"value\");\nsubscription.AddCallbackParameter(\"foo\", \"bar\");\n\n// add partner parameters\nsubscription.AddPartnerParameter(\"key\", \"value\");\nsubscription.AddPartnerParameter(\"foo\", \"bar\");\n\nAdjust.TrackSubscription(subscription);\n```\n\n**For Play Store subscription:**\n\n```cs\nAdjustPlayStoreSubscription subscription = new AdjustPlayStoreSubscription(\n    price,\n    currency,\n    sku,\n    orderId,\n    signature,\n    purchaseToken);\nsubscription.SetPurchaseTime(purchaseTime);\n\n// add callback parameters\nsubscription.AddCallbackParameter(\"key\", \"value\");\nsubscription.AddCallbackParameter(\"foo\", \"bar\");\n\n// add partner parameters\nsubscription.AddPartnerParameter(\"key\", \"value\");\nsubscription.AddPartnerParameter(\"foo\", \"bar\");\n\nAdjust.TrackPlayStoreSubscription(subscription);\n```\n\n### \u003ca id=\"session-parameters\"\u003e\u003c/a\u003eSession parameters\n\nSome parameters are saved to be sent in every event and session of the Adjust SDK. Once you have added any of these parameters, you don't need to add them every time, since they will be saved locally. If you add the same parameter twice, there will be no effect.\n\nThese session parameters can be called before the Adjust SDK is launched to make sure they are sent even on install. If you need to send them with an install, but can only obtain the needed values after launch, it's possible to [delay](#delay-start) the first launch of the Adjust SDK to allow this behaviour.\n\n### \u003ca id=\"session-callback-parameters\"\u003e\u003c/a\u003eSession callback parameters\n\nThe same callback parameters that are registered for [events](#callback-parameters) can be also saved to be sent in every event or session of the Adjust SDK.\n\nThe session callback parameters have a similar interface of the event callback parameters. Instead of adding the key and it's value to an event, it's added through a call to `Adjust` method `AddSessionCallbackParameter`:\n\n```cs\nAdjust.AddSessionCallbackParameter(\"foo\", \"bar\");\n```\n\nThe session callback parameters will be merged with the callback parameters added to an event. The callback parameters added to an event have precedence over the session callback parameters. Meaning that, when adding a callback parameter to an event with the same key to one added from the session, the value that prevails is the callback parameter added to the event.\n\nIt's possible to remove a specific session callback parameter by passing the desiring key to the method `RemoveSessionCallbackParameter`.\n\n```cs\nAdjust.RemoveSessionCallbackParameter(\"foo\");\n```\n\nIf you wish to remove all key and values from the session callback parameters, you can reset it with the method `ResetSessionCallbackParameters`.\n\n```cs\nAdjust.ResetSessionCallbackParameters();\n```\n\n### \u003ca id=\"session-partner-parameters\"\u003e\u003c/a\u003eSession partner parameters\n\nIn the same way that there is [session callback parameters](#session-callback-parameters) that are sent every in event or session of the Adjust SDK, there is also session partner parameters.\n\nThese will be transmitted to network partners, for the integrations that have been activated in your Adjust [dashboard].\n\nThe session partner parameters have a similar interface to the event partner parameters. Instead of adding the key and it's value to an event, it's added through a call to `Adjust` method `AddSessionPartnerParameter`:\n\n```cs\nAdjust.AddSessionPartnerParameter(\"foo\", \"bar\");\n```\n\nThe session partner parameters will be merged with the partner parameters added to an event. The partner parameters added to an event have precedence over the session partner parameters. Meaning that, when adding a partner parameter to an event with the same key to one added from the session, the value that prevails is the partner parameter added to the event.\n\nIt's possible to remove a specific session partner parameter by passing the desiring key to the method `RemoveSessionPartnerParameter`.\n\n```cs\nAdjust.RemoveSessionPartnerParameter(\"foo\");\n```\n\nIf you wish to remove all key and values from the session partner parameters, you can reset it with the method `ResetSessionPartnerParameters`.\n\n```cs\nAdjust.ResetSessionPartnerParameters();\n```\n\n### \u003ca id=\"delay-start\"\u003e\u003c/a\u003eDelay start\n\nDelaying the start of the Adjust SDK allows your app some time to obtain session parameters, such as unique identifiers, to be send on install.\n\nSet the initial delay time in seconds with the `DelayStart` property of the `ADJConfig`/`AdjustConfig` instance:\n\n**For iOS app:**\n\n```cs\nconfig.DelayStart = 5.5;\n```\n\n**For Android app:**\n\n```cs\nconfig.SetDelayStart(5.5);\n```\n\nIn this case this will make the Adjust SDK not send the initial install session and any event created for 5.5 seconds. After this time is expired or if you call `Adjust.SendFirstPackages()` in the meanwhile, every session parameter will be added to the delayed install session and events and the Adjust SDK will resume as usual.\n\n**The maximum delay start time of the adjust SDK is 10 seconds**.\n\n### \u003ca id=\"attribution-callback\"\u003e\u003c/a\u003eAttribution callback\n\nYou can register a callback to be notified of tracker attribution changes. Due to the different sources considered for attribution, this information can not by provided synchronously. Follow these steps to implement the optional callback in your app:\n\nPlease make sure to consider our [applicable attribution data policies][attribution-data].\n\n**For iOS app:**\n\n- Open `AppDelegate.cs` and create a class which inherits from `AdjustDelegate` and override its `AdjustAttributionChanged` method.\n    \n    ```cs\n    public class AdjustDelegateXamarin : AdjustDelegate\n    {\n        public override void AdjustAttributionChanged (ADJAttribution attribution)\n        {\n            Console.WriteLine (\"Attribution changed!\");\n            Console.WriteLine (\"New attribution: {0}\", attribution.ToString ());\n        }\n    }\n    ```\n\n- Add the private field of type `AdjustDelegateXamarin` to this `AppDelegate` class.\n\n    ```cs\n    private AdjustDelegateXamarin adjustDelegate = null;\n    ```\n\n- Initialize and set the delegate with your `ADJConfig` instance:\n\n    ```cs\n    adjustDelegate = new AdjustDelegateXamarin();\n    // ...\n    adjustConfig.Delegate = adjustDelegate;\n    ```\n    \n**For Android app:**\n\n- Implement the `IOnAttributionChangedListener` interface in your Application class.\n\n    ```cs\n    [Application (AllowBackup = true)]\n    public class GlobalApplication : Application, IOnAttributionChangedListener\n    {\n        ...\n    }\n    ```\n- Override the `OnAttributionChanged` callback which will be triggered when the attribution has been changed.\n\n    ```cs\n    public void OnAttributionChanged(AdjustAttribution attribution)\n    {\n        Console.WriteLine(\"Attribution changed!\");\n        Console.WriteLine(\"New attribution: {0}\", attribution.ToString ());\n    }\n    ```\n\n- Set your Application class instance as the listener in the `AdjustConfig` object.\n\n    ```cs\n    AdjustConfig config = new AdjustConfig(this, yourAppToken, environment);\n    config.SetOnAttributionChangedListener(this);\n    Adjust.OnCreate (config);\n    ```\n\nThe callback function will be called  when the SDK receives final attribution data. Within the callback function you have access to the `attribution` parameter. Here is a quick summary of its properties:\n\n- `TrackerToken`    the tracker token of the current attribution.\n- `TrackerName`     the tracker name of the current attribution.\n- `Network`         the network grouping level of the current attribution.\n- `Campaign`        the campaign grouping level of the current attribution.\n- `Adgroup`         the ad group grouping level of the current attribution.\n- `Creative`        the creative grouping level of the current attribution.\n- `ClickLabel`      the click label of the current attribution.\n- `Adid`            the Adjust device identifier.\n- `CostType`        the cost type.\n- `CostAmount`      the cost amount.\n- `CostCurrency`    the cost currency.\n\n**Note**: The cost data - `CostType`, `CostAmount` \u0026 `CostCurrency` are only available when configured in `AdjustConfig` by seting `NeedsCost` property. If not configured or configured, but not being part of the attribution, these fields will have value `null`. This feature is available in SDK v4.29.0 and above.\n\n**For iOS apps:**\n\n```cs\nconfig.NeedsCost = true;\n```\n\n**For Android apps:**\n```cs\nconfig.SetNeedsCost(true);\n```\n\n### \u003ca id=\"session-event-callbacks\"\u003e\u003c/a\u003eSession and event callbacks\n\n---\n\n**For iOS app:** \n\nYou can register a callback to be notified of successful and failed events and/or sessions. Like with attribution callback, this should be done in your custom class which inherits from `AdjustDelegate`.\n\nFollow the same steps to implement the following callback function for successful tracked events:\n\n```cs\npublic class AdjustDelegateXamarin : AdjustDelegate\n{\n    public override void AdjustEventTrackingSucceeded(ADJEventSuccess eventSuccessResponseData)\n    {\n        Console.WriteLine(\"Event tracking succeeded! Info: \" + eventSuccessResponseData.ToString());\n    }\n}\n```\n\nThe following callback function for failed tracked events:\n\n```cs\npublic class AdjustDelegateXamarin : AdjustDelegate\n{\n    public override void AdjustEventTrackingFailed(ADJEventFailure eventFailureResponseData)\n    {\n        Console.WriteLine(\"Event tracking failed! Info: \" + eventFailureResponseData.ToString());\n    }\n}\n```\n\nFor successful tracked sessions:\n\n```cs\npublic class AdjustDelegateXamarin : AdjustDelegate\n{\n    public override void AdjustSessionTrackingSucceeded(ADJSessionSuccess sessionSuccessResponseData)\n    {\n        Console.WriteLine(\"Session tracking succeeded! Info: \" + sessionSuccessResponseData.ToString());\n    }\n}\n```\n\nAnd for failed tracked sessions:\n\n```cs\npublic class AdjustDelegateXamarin : AdjustDelegate\n{\n    public override void AdjustSessionTrackingFailed(ADJSessionFailure sessionFailureResponseData)\n    {\n        Console.WriteLine(\"Session tracking failed! Info: \" + sessionFailureResponseData.ToString());\n    }\n}\n```\n\nThe callback functions will be called after the SDK tries to send a package to the server. Within the callback you have access to a response data object specifically for the callback. Here is a quick summary of the session response data properties:\n\n- `string Message` the message from the server or the error logged by the SDK.\n- `string Timestamp` timestamp from the server.\n- `string Adid` a unique device identifier provided by adjust.\n- `NSDictionary\u003cstring, object\u003e JsonResponse` the JSON object with the response from the server.\n\nBoth event response data objects contain:\n\n- `string EventToken` the event token, if the package tracked was an event.\n- `string CallbackId` the custom defined callback ID set on event object.\n\nAnd both event and session failed objects also contain:\n\n- `bool WillRetry` indicates there will be an attempt to resend the package at a later time.\n\n---\n\n**For Android app:**\n\nYou can register a callback to be notified of successful and failed events and/or sessions. Like with attribution callback, this should be done in your custom class which implements corresponding interface for each callback method.\n\nFollow the same steps to implement the following callback function for successful tracked events. You need to set the listener object on `AdjustConfig` instance which implements `IOnEventTrackingSucceededListener` interface:\n\n```cs\n[Application(AllowBackup = true)]\npublic class GlobalApplication : Application, IOnEventTrackingSucceededListener\n{\n    public override void OnCreate()\n    {\n        base.OnCreate();\n\n        string appToken = \"{YourAppToken}\";\n        string environment = AdjustConfig.EnvironmentSandbox;\n        AdjustConfig config = new AdjustConfig(this, appToken, environment);\n\n        // Set event tracking success callback.\n        config.SetOnEventTrackingSucceededListener(this);\n\n        Adjust.OnCreate(config);\n    }\n\n    public void OnFinishedEventTrackingSucceeded(AdjustEventSuccess eventSuccess)\n    {\n        Console.WriteLine(\"Event tracking succeeded! \" + eventSuccess.ToString());\n    }\n}\n```\n\nFor failed tracked events, you need to set the listener object on `AdjustConfig` instance which implements `IOnEventTrackingFailedListener` interface:\n\n```cs\n[Application(AllowBackup = true)]\npublic class GlobalApplication : Application, IOnEventTrackingFailedListener\n{\n    public override void OnCreate()\n    {\n        base.OnCreate();\n\n        string appToken = \"{YourAppToken}\";\n        string environment = AdjustConfig.EnvironmentSandbox;\n        AdjustConfig config = new AdjustConfig(this, appToken, environment);\n\n        // Set event tracking failure callback.\n        config.SetOnEventTrackingFailedListener(this);\n\n        Adjust.OnCreate(config);\n    }\n\n    public void OnFinishedEventTrackingFailed(AdjustEventFailure eventFailure)\n    {\n        Console.WriteLine(\"Event tracking failed! \" + eventFailure.ToString());\n    }\n}\n```\n\nFor successful tracked sessions, you need to set the listener object on `AdjustConfig` instance which implements `IOnSessionTrackingSucceededListener` interface:\n\n```cs\n[Application(AllowBackup = true)]\npublic class GlobalApplication : Application, IOnSessionTrackingSucceededListener\n{\n    public override void OnCreate()\n    {\n        base.OnCreate();\n\n        string appToken = \"{YourAppToken}\";\n        string environment = AdjustConfig.EnvironmentSandbox;\n        AdjustConfig config = new AdjustConfig(this, appToken, environment);\n\n        // Set session tracking success callback.\n        config.SetOnSessionTrackingSucceededListener(this);\n\n        Adjust.OnCreate(config);\n    }\n\n    public void OnFinishedSessionTrackingSucceeded(AdjustSessionSuccess sessionSuccess)\n    {\n        Console.WriteLine(\"Session tracking succeeded! \" + sessionSuccess.ToString());\n    }\n}\n```\n\nFor failed tracked sessions, you need to set the listener object on `AdjustConfig` instance which implements `IOnSessionTrackingFailedListener` interface:\n\n```cs\n[Application(AllowBackup = true)]\npublic class GlobalApplication : Application, IOnSessionTrackingFailedListener\n{\n    public override void OnCreate()\n    {\n        base.OnCreate();\n\n        string appToken = \"{YourAppToken}\";\n        string environment = AdjustConfig.EnvironmentSandbox;\n        AdjustConfig config = new AdjustConfig(this, appToken, environment);\n\n        // Set session tracking failure callback.\n        config.SetOnSessionTrackingFailedListener(this);\n\n        Adjust.OnCreate(config);\n    }\n\n    public void OnFinishedSessionTrackingFailed(AdjustSessionFailure sessionFailure)\n    {\n        Console.WriteLine(\"Session tracking failed! \" + sessionFailure.ToString());\n    }\n}\n```\n\nThe callback functions will be called after the SDK tries to send a package to the server. Within the callback you have access to a response data object specifically for the callback. Here is a quick summary of the session response data properties:\n\n- `string Message` the message from the server or the error logged by the SDK.\n- `string Timestamp` timestamp from the server.\n- `string Adid` a unique device identifier provided by adjust.\n- `JSONObject JsonResponse` the JSON object with the response from the server.\n\nBoth event response data objects contain:\n\n- `string EventToken` the event token, if the package tracked was an event.\n- `string CallbackId` the custom defined callback ID set on event object.\n\nAnd both event and session failed objects also contain:\n\n- `bool WillRetry` indicates there will be an attempt to resend the package at a later time.\n\n---\n\n### \u003ca id=\"disable-tracking\"\u003e\u003c/a\u003eDisable tracking\n\nYou can disable the Adjust SDK from tracking by invoking the method `SetEnabled` with the enabled parameter as `false`. **This setting is remembered between sessions**, but it can only be activated after the first session.\n\n```cs\nAdjust.SetEnabled(false);\n```\n\nYou can verify if the Adjust SDK is currently active with the property `IsEnabled`. It is always possible to activate the Adjust SDK by invoking `SetEnabled` with the enabled parameter set to `true`.\n\n### \u003ca id=\"offline-mode\"\u003e\u003c/a\u003eOffline mode\n\nYou can put the adjust SDK in offline mode to suspend transmission to our servers, while retaining tracked data to be sent later. When in offline mode, all information is saved in a file, so be careful not to trigger too many events.\n\nYou can activate offline mode by calling `SetOfflineMode` with the parameter `true`.\n\n```cs\nAdjust.SetOfflineMode(true);\n```\n\nConversely, you can deactivate offline mode by calling `SetOfflineMode` with `false`. When the Adjust SDK is put back in online mode, all saved information is send to our servers with the correct time information.\n\nUnlike disabling tracking, **this setting is not remembered** between sessions. This means that the SDK is in online mode whenever it is started, even if the app was terminated in offline mode.\n\n### \u003ca id=\"event-buffering\"\u003e\u003c/a\u003eEvent buffering\n\nIf your app makes heavy use of event tracking, you might want to delay some HTTP requests in order to send them in one batch every minute. You can enable event buffering with your `ADJConfig`/`AdjustConfig` instance:\n\n**For iOS app:**\n\n```cs\nvar config = ADJConfig.ConfigWithAppToken(yourAppToken, environment);\nconfig.EventBufferingEnabled = true;\nAdjust.AppDidLaunch(config);\n```\n\n**For Android app:**\n\n```cs\nAdjustConfig config = new AdjustConfig(this, yourAppToken, environment);\nconfig.SetEventBufferingEnabled((Java.Lang.Boolean)true);\nAdjust.OnCreate(config);\n```\n\nIf nothing is set, event buffering is **disabled by default**.\n\n### \u003ca id=\"gdpr-forget-me\"\u003e\u003c/a\u003eGDPR right to be forgotten\n\nIn accordance with article 17 of the EU's General Data Protection Regulation (GDPR), you can notify Adjust when a user has exercised their right to be forgotten. Calling the following method will instruct the Adjust SDK to communicate the user's choice to be forgotten to the Adjust backend:\n\n```cs\nAdjust.GdprForgetMe();\n```\n\nUpon receiving this information, Adjust will erase the user's data and the Adjust SDK will stop tracking the user. No requests from this device will be sent to Adjust in the future.\n\n### \u003ca id=\"disable-third-party-sharing\"\u003e\u003c/a\u003eDisable third-party sharing for specific users\n\nYou can now notify Adjust when a user has exercised their right to stop sharing their data with partners for marketing purposes, but has allowed it to be shared for statistics purposes. \n\nCall the following method to instruct the Adjust SDK to communicate the user's choice to disable data sharing to the Adjust backend:\n\n**For iOS app:**\n\n```cs\nAdjust.DisableThirdPartySharing();\n```\n\n**For Android app:**\n\n```cs\nAdjust.DisableThirdPartySharing(this);\n```\n\nUpon receiving this information, Adjust will block the sharing of that specific user's data to partners and the Adjust SDK will continue to work as usual.\n\n### \u003ca id=\"sdk-signature\"\u003e\u003c/a\u003eSDK signature\n\nAn account manager must activate the Adjust SDK signature. Contact Adjust support (support@adjust.com) if you are interested in using this feature.\n\nIf the SDK signature has already been enabled on your account and you have access to App Secrets in your Adjust Dashboard, please use the method below to integrate the SDK signature into your app.\n\nAn App Secret is set by passing all secret parameters (`secretId`, `info1`, `info2`, `info3`, `info4`) to `SetAppSecret` method of `ADJConfig`/`AdjustConfig` instance:\n\n**For iOS app:**\n\n```cs\nvar config = ADJConfig.ConfigWithAppToken(appToken, environment);\nconfig.SetAppSecret(secretId, info1, info2, info3, info4);\nAdjust.AppDidLaunch(config);\n```\n\n**For Android app:**\n\n```cs\nAdjustConfig config = AdjustConfig(this, appToken, environment);\nconfig.SetAppSecret(secretId, info1, info2, info3, info4);\nAdjust.OnCreate(config);\n```\n\n### \u003ca id=\"background-tracking\"\u003e\u003c/a\u003eBackground tracking\n\nThe default behaviour of the Adjust SDK is to **pause sending HTTP requests while the app is in the background**. You can change this in your `ADJConfig`/`AdjustConfig` instance:\n\n**For iOS apps:**\n\n```cs\nvar config = ADJConfig.ConfigWithAppToken(yourAppToken, environment);\nconfig.SendInBackground = true;\nAdjust.AppDidLaunch(config);\n```\n\n**For Android apps:**\n\n```cs\nAdjustConfig config = new AdjustConfig(this, yourAppToken, environment);\nconfig.SetSendInBackground(true);\nAdjust.OnCreate(config);\n```\n\nIf nothing set, sending in background is **disabled by default**.\n\n### \u003ca id=\"device-ids\"\u003e\u003c/a\u003eDevice IDs\n\nThe adjust SDK offers the possibility to obtain some device identifiers.\n\n### \u003ca id=\"di-idfa\"\u003e\u003c/a\u003eiOS Advertising Identifier\n\nCertain services (such as Google Analytics) require you to coordinate device and client IDs in order to prevent duplicate reporting.\n\nTo obtain the IDFA device identifier, access the `Idfa` property of the `Adjust` instance:\n\n```cs\nstring idfa = Adjust.Idfa;\n```\n\n### \u003ca id=\"di-gps-adid\"\u003e\u003c/a\u003eGoogle Play Services advertising identifier\n\nThe Google Play Services Advertising Identifier (Google advertising ID) is a unique identifier for a device. Users can opt out of sharing their Google advertising ID by toggling the \"Opt out of Ads Personalization\" setting on their device. When a user has enabled this setting, the Adjust SDK returns a string of zeros when trying to read the Google advertising ID.\n\n\u003e **Important**: If you are targeting Android 12 and above (API level 31), you need to add the [`com.google.android.gms.AD_ID` permission](#gps-adid-permission) to your app. If you do not add this permission, you will not be able to read the Google advertising ID even if the user has not opted out of sharing their ID.\n\nCertain services (such as Google Analytics) require you to coordinate Device and Client IDs in order to prevent duplicated reporting.\n\nIf you need to obtain the Google Advertising ID, there is a restriction that only allows it to be read in a background thread. If you call the function `getGoogleAdId` with the context and a `OnDeviceIdsRead` instance, it will work in any situation:\n\n```cs\nusing Com.Adjust.Sdk;\n\n// ...\n\n[Application(AllowBackup = true)]\npublic class GlobalApplication : Application, IOnDeviceIdsRead\n{\n    public override void OnCreate()\n    {\n        base.OnCreate();\n\n        string appToken = \"{YourAppToken}\";\n        string environment = AdjustConfig.EnvironmentSandbox;\n\n        var config = new AdjustConfig(this, appToken, environment);\n\n        Adjust.OnCreate(config);\n\n        Adjust.GetGoogleAdId(this, this);\n    }\n\n    public void OnGoogleAdIdRead(string googleAdId)\n    {\n        Console.WriteLine(\"Google Ad Id read: \" + googleAdId);\n    }\n}\n```\n\nInside the method `onGoogleAdIdRead` of the `OnDeviceIdsRead` instance, you will have access to the Google Advertising ID through the variable `googleAdId`.\n\n### \u003ca id=\"di-fire-adid\"\u003e\u003c/a\u003eAmazon advertising identifier\n\nIf you need to obtain the Amazon advertising ID, you can call the `GetAmazonAdId` method of the `Adjust` instance and pass your callback as a parameter to which the Amazon advertising ID value will be sent once obtained:\n\n```csharp\nConsole.WriteLine(\"Amazon Ad Id: \" + Adjust.GetAmazonAdId(this));\n```\n\n### \u003ca id=\"di-adid\"\u003e\u003c/a\u003eAdjust device identifier\n\nFor each device with your app installed, the Adjust backend generates a unique **Adjust device identifier** (**adid**). In order to obtain this identifier, you can access the following property of the `Adjust` instance:\n\n```cs\nstirng adid = Adjust.Adid;\n```\n\n**Note**: Information about the **adid** is available after the app's installation has been tracked by the Adjust backend. From that moment on, the Adjust SDK has information about the device **adid** and you can access it with this method. So, **it is not possible** to access the **adid** before the SDK has been initialised and the installation of your app has been successfully tracked.\n\n### \u003ca id=\"set-external-device-id\"\u003e\u003c/a\u003eSet external device ID\n\n\u003e **Note** If you want to use external device IDs, please contact your Adjust representative. They will talk you through the best approach for your use case.\n\nAn external device identifier is a custom value that you can assign to a device or user. They can help you to recognize users across sessions and platforms. They can also help you to deduplicate installs by user so that a user isn't counted as multiple new installs.\n\nYou can also use an external device ID as a custom identifier for a device. This can be useful if you use these identifiers elsewhere and want to keep continuity.\n\nCheck out our [external device identifiers article](https://help.adjust.com/en/article/external-device-identifiers) for more information.\n\n\u003e **Note** This setting requires Adjust SDK v4.21.0 or later.\n\nTo set an external device ID, assign the identifier to the `ExternalDeviceId` property of your config instance. Do this before you initialize the Adjust SDK.\n\n**For iOS apps:**\n\n```csharp\nvar config = ADJConfig.ConfigWithAppToken(yourAppToken, environment);\nconfig.ExternalDeviceId = \"{Your-External-Device-Id}\";\nAdjust.AppDidLaunch(config);\n```\n\n**For Android apps:**\n\n```csharp\nAdjustConfig config = new AdjustConfig(this, yourAppToken, environment);\nconfig.ExternalDeviceId = \"{Your-External-Device-Id}\";\nAdjust.OnCreate(config);\n```\n\n\u003e **Important**: You need to make sure this ID is **unique to the user or device** depending on your use-case. Using the same ID across different users or devices could lead to duplicated data. Talk to your Adjust representative for more information.\n\nIf you want to use the external device ID in your business analytics, you can pass it as a session callback parameter. See the section on [session callback parameters](#session-callback-parameters) for more information.\n\nYou can import existing external device IDs into Adjust. This ensures that the backend matches future data to your existing device records. If you want to do this, please contact your Adjust representative.\n\n### \u003ca id=\"user-attribution\"\u003e\u003c/a\u003eUser attribution\n\nThe attribution callback will be triggered as described in the [attribution callback section](#attribution-callback), providing you with information about any new attribution whenever it changes. If you want to access information about a user's current attribution at any other time, you can do so through the following property of the `Adjust` instance:\n\n```cs\nADJAttribution attribution = Adjust.Attribution;\n```\n\n### \u003ca id=\"push-token\"\u003e\u003c/a\u003ePush token\n\nPush tokens are used for Audience Builder and client callbacks, and they are required for uninstall and reinstall tracking.\n\nTo send us the push notification token, add the following call to Adjust once you have obtained your token or when ever it's value is changed:\n\n```cs\nAdjust.SetPushToken(\"YourPushNotificationsToken\");\n```\n\n**Note for iOS**: `Adjust.SetDeviceToken(NSData)` method is marked as deprecated as of Android SDK v4.14.0. Please, use `Adjust.SetPushToken(string)` method instead.\n\n### \u003ca id=\"pre-installed-trackers\"\u003e\u003c/a\u003ePre-installed trackers\n\nIf you want to use the Adjust SDK to recognize users that found your app pre-installed on their device, follow these steps.\n\n- Create a new tracker in your [dashboard].\n- Open your app delegate and add set the default tracker of your `ADJConfig`:\n\n    **For iOS apps:**\n    \n    ```cs\n    var config = ADJConfig.ConfigWithAppToken(yourAppToken, environment);\n    config.DefaultTracker = \"{TrackerToken}\";\n    Adjust.AppDidLaunch(config);\n    ```\n    \n    **For Android apps:**\n    \n    ```cs\n    AdjustConfig config = new AdjustConfig(this, yourAppToken, environment);\n    config.SetDefaultTracker(\"{TrackerToken}\");\n    Adjust.OnCreate(config);\n    ```\n\n  Replace `{TrackerToken}` with the tracker token you created in step 2. Please note that the dashboard displays a tracker \n  URL (including `http://app.adjust.com/`). In your source code, you should specify only the six-character token and not the\n  entire URL.\n\n- Build and run your app. You should see a line like the following in app's log output:\n\n    ```\n    Default tracker: 'abc123'\n    ```\n\n### \u003ca id=\"deeplinking\"\u003e\u003c/a\u003eDeep linking\n\nIf you are using the Adjust tracker URL with an option to deep link into your app from the URL, there is the possibility to get information about the deep link URL and its content. Hitting the URL can happen when the user already has your app installed (standard deep linking scenario) or if they do not have the app on their device (deferred deep linking scenario). In the standard deep linking scenario, the iOS and Android platforms offer native support for you to get the info about the deep link content. The deferred deep linking scenario is something that the platforms does not support out of the box. In this scenario, the Adjust SDK will offer you the tools you need to get the information about the deep link content.\n\n### \u003ca id=\"deeplinking-standard\"\u003e\u003c/a\u003eStandard deep linking scenario\n\n---\n\n**For iOS apps:**\n\nIf your user already has the app installed and hits the tracker URL with deep link information in it, your application will get opened and the content of the deep link will be sent to your app so that you can parse it and decide what to do next in your app. As you have read in our official iOS SDK README, deep linking in iOS at this moment can be done with usage of custom URL scheme in tracker URL (iOS 8 and earlier) or with usage of universal links (iOS 9 and newer).\n\nDepending on which scenario you want to use for your app (or if you want to use them both to support wide range of devices), you need to set up your app to handle one of these or both scenarios.\n\n---\n\n**For Android apps:**\n\nIf a user has your app installed and you want it to launch after hitting an Adjust tracker URL with the `deep_link` parameter in it, you need enable deep linking in your app. This is done by choosing a desired **unique scheme name** and assigning it to the Activity which you want to launch once the app opens after the user has clicked on the link. This can be done by setting certain properties on the Activity class which you would like to see launched once the deep link has been clicked and your app has opened. You need to set up a proper intent filter and name the scheme:\n\n```cs\n[Activity(Label = \"Example\", MainLauncher = true)]\n    [IntentFilter\n     (new[] { Intent.ActionView },\n        Categories = new[] { Intent.CategoryDefault, Intent.CategoryBrowsable },\n        DataScheme = \"adjust-example\")]\n    public class MainActivity : Activity\n    {\n        // ...\n    }\n```\n\nWith this now set, you need to use the assigned scheme name in the Adjust tracker URL's `deep_link` parameter. A tracker URL without any information added to the deep link can be built to look something like this:\n\n```\nhttps://app.adjust.com/abc123?deep_link=adjust-example%3A%2F%2F\n```\n\nPlease, have in mind that the `deep_link` parameter value in the URL **must be URL encoded**.\n\nAfter clicking this tracker URL, and with the app set as described above, your app will launch along with the `MainActivity` intent. Inside the `MainActivity` class, you will automatically be provided with the information about the `deep_link` parameter content. Once this content is delivered to you, it **will not be encoded**, although it was encoded in the URL.\n\nDepending on the `launchMode` setting of your Activity, information about the `deep_link` parameter content will be delivered to the appropriate place in the Activity file. For more information about the possible values of the `launchMode` property, check [the official Android documentation][android-launch-modes].\n\nThere are two possible places in which information about the deep link content will be delivered to your desired Activity via `Intent` object - either in the Activity's `OnCreate` or `OnNewIntent` method. After the app has launched and one of these methods is triggered, you will be able to get the actual deeplink passed in the `deep_link` parameter in the click URL. You can then use this information to do some additional logic in your app.\n\nYou can extract the deep link content from these two methods like this:\n\n```cs\nusing Android.Content;\nusing Com.Adjust.Sdk;\n\n// ...\n\nprotected override void OnCreate(Bundle savedInstanceState)\n{\n    base.OnCreate(savedInstanceState);\n\n    Intent intent = this.Intent;\n    var data = intent.Data;\n\n    // data.ToString() -\u003e This is your deep_link parameter value.\n}\n```\n\n```cs\nusing Android.Content;\nusing Com.Adjust.Sdk;\n\n// ...\n\nprotected override void OnNewIntent(Android.Content.Intent intent)\n{\n    base.OnNewIntent(intent);\n\n    var data = intent.Data;\n\n    // data.ToString() -\u003e This is your deep_link parameter value.\n}\n```\n\n### \u003ca id=\"deeplinking-setup-old\"\u003e\u003c/a\u003eDeep linking on iOS 8 and earlier\n\nIn order to set deep linking support for iOS 8 and earlier devices, you need to set up custom URL scheme in your app's `Info.plist` file. Open your `Info.plist` file and go to `Advanced` tab. In there, fill in your `Bundle ID` value in `Identifier` field and custom URL scheme for your app in `URL Schemes` field.\n\nWith this completed, when you app gets opened by click on tracker URL with deep link info which contains your custom URL scheme in it, `OpenUrl` method in your `AppDelegate` class will get called and you will get the deep link info in there.\n\n```cs\npublic override bool OpenUrl(UIApplication application, NSUrl url, string sourceApplication, NSObject annotation)\n{\n    // url -\u003e This is your deep link content.\n\n    return true;\n}\n```\n\nWith this setup, you have successfully set up deep linking handling for iOS devices with iOS 8 and earlier versions.\n\n### \u003ca id=\"deeplinking-setup-new\"\u003e\u003c/a\u003eDeep linking on iOS 9 and later\n\nIn order to set deep linking support for iOS 9 and later devices, you need to enable your app to handle Apple universal links. If you followed our official iOS SDK README instructions, you have successfully enabled `Associated Domains` for your app in Apple Developer portal. In order to enable this in your app project, please open `Entitlements.plist`. In there you will see `Associated Domains` part which you need to enable by checking the `Enable Associated Domains` check box. After this you only need to add domain which was generated for you in the Adjust dashboard.\n\nWith this completed, when your app gets opened by click on universal link, `ContinueUserActivity` method in your `AppDelegate` class will get called and you will get the deep link info in there.\n\n```cs\npublic override bool ContinueUserActivity(UIApplication application, NSUserActivity userActivity, UIApplicationRestorationHandler completionHandler)\n{\n    if (userActivity.ActivityType == NSUserActivityType.BrowsingWeb)\n    {\n        // userActivity.WebPageUrl -\u003e This is your deep link content.\n    }\n\n    return true;\n}\n```\n\nWith this setup, you have successfully set up deep linking handling for iOS devices with iOS 9 and later versions.\n\n### \u003ca id=\"deeplinking-deferred\"\u003e\u003c/a\u003eDeferred deep linking scenario\n\n---\n\n**For iOS apps:**\n\nIn order to get info about the URL content in a deferred deep linking scenario, you should implement a callback method in the same way like you were setting callbacks for attribution, events and sessions. You need to override `AdjustDeeplinkResponse` in the class which inherits from `AdjustDelegate`:\n\n```cs\npublic class AdjustDelegateXamarin : AdjustDelegate\n{\n    public override bool AdjustDeeplinkResponse(NSUrl deeplink)\n    {\n        Console.WriteLine(\"adjust: Deferred deep link received! URL = \" + deeplink.ToString());\n\n        return true;\n        // return false;\n    }\n}\n```\n\nIn deferred deep linking scenario, there is one additional setting which can be set in the `AdjustDeeplinkResponse` method via it's return value. Once the Adjust SDK gets the deferred deep link info, we are offering you the possibility to choose whether our SDK should open this URL or not. You can choose to set this option by returning either `true` if you want us to open the URL or `false` if you don't want us to do anything.\n\nIf this callback is not implemented, **the Adjust SDK will always try to launch the URL by default**.\n\n---\n\n**For Android apps:**\n\nDeferred deep linking scenario happens when a user clicks on the Adjust tracker URL with the `deep_link` parameter in it, but does not have the app installed on the device at the moment of click. After that, the user will get redirected to the Play Store to download and install your app. After opening it for the first time, the content of the `deep_link` parameter will be delivered to the app.\n\nIn order to get info about the `deep_link` parameter content in a deferred deep linking scenario, you should set a listener method on the `AdjustConfig` object. Listener object needs to implement `IOnDeeplinkResponseListener` interface and override it's `LaunchReceivedDeeplink` method. This will get triggered once the Adjust SDK gets the info about the deep link content from the backend.\n\n```cs\n[Application(AllowBackup = true)]\npublic class GlobalApplication : Application, IOnDeeplinkResponseListener\n{\n    public override void OnCreate()\n    {\n        base.OnCreate();\n\n        string appToken = \"{YourAppToken}\";\n        string environment = AdjustConfig.EnvironmentSandbox;\n        AdjustConfig config = new AdjustConfig(this, appToken, environment);\n\n        // Set deferred deeplink callback.\n        config.SetOnDeeplinkResponseListener(this);\n\n        Adjust.OnCreate(config);\n    }\n\n    public bool LaunchReceivedDeeplink(Android.Net.Uri deeplink)\n    {\n        Console.WriteLine(\"Deferred deeplink arrived! URL = \" + deeplink.ToString());\n\n        return true;\n        // return false;\n    }\n}\n```\n\nOnce the aAdjust SDK receives the info about the deep link content from the backend, it will deliver you the info about its content in this listener and expect the `bool` return value from you. This return value represents your decision on whether the Adjust SDK should launch the Activity to which you have assigned the scheme name from the deep link (like in the standard deep linking scenario) or not.\n\nIf you return `true`, we will launch it and the exact same scenario which is described in the [Standard deep linking scenario chapter](#deeplinking-standard) will happen. If you do not want the SDK to launch the Activity, you can return `false` from this listener and based on the deep link content decide on your own what to do next in your app.\n\n### \u003ca id=\"deeplinking-reattribution\"\u003e\u003c/a\u003eReattribution via deep links\n\nAdjust enables you to run re-engagement campaigns with usage of deep links. For more information on how to do that, please check our [official docs][reattribution-with-deeplinks]. \n\nIf you are using this feature, in order for your user to be properly reattributed, you need to make one additional call to the adjust SDK in your app.\n\nOnce you have received deep link content information in your app, add a call to `Adjust.AppWillOpenUrl` method. By making this call, the Adjust SDK will try to find if there is any new attribution info inside of the deep link and if any, it will be sent to the Adjust backend. If your user should be reattributed due to a click on the Adjust tracker URL with deep link content in it, you will see the [attribution callback](#attribution-callback) in your app being triggered with new attribution info for this user.\n\n**For iOS apps:**\n\nThe call to `Adjust.AppWillOpenUrl` should be done like this to support deeplinking in all iOS versions:\n\n```cs\npublic override bool OpenUrl(UIApplication application, NSUrl url, string sourceApplication, NSObject annotation)\n{\n    // url -\u003e This is your deep link content.\n    Adjust.AppWillOpenUrl(url);\n\n    return true;\n}\n```\n\n```cs\npublic override bool ContinueUserActivity(UIApplication application, NSUserActivity userActivity, UIApplicationRestorationHandler completionHandler)\n{\n    if (userActivity.ActivityType == NSUserActivityType.BrowsingWeb)\n    {\n        // userActivity.WebPageUrl -\u003e This is your deep link content.\n        Adjust.AppWillOpenUrl(userActivity.WebPageUrl);\n    }\n\n    return true;\n}\n```\n\n**For Androoid apps:**\n\nThe call to `Adjust.AppWillOpenUrl` should be done like this:\n\n```cs\nusing Android.Content;\nusing Com.Adjust.Sdk;\n\n// ...\n\nprotected override void OnCreate(Bundle savedInstanceState)\n{\n    base.OnCreate(savedInstanceState);\n\n    Intent intent = this.Intent;\n    var data = intent.Data;\n\n    // data.ToString() -\u003e This is your deep_link parameter value.\n\n    Adjust.AppWillOpenUrl(data, this);\n}\n```\n\n```cs\nusing Android.Content;\nusing Com.Adjust.Sdk;\n\n// ...\n\nprotected override void OnNewIntent(Android.Content.Intent intent)\n{\n    base.OnNewIntent(intent);\n\n    var data = intent.Data;\n\n    // data.ToString() -\u003e This is your deep_link parameter value.\n\n    Adjust.AppWillOpenUrl(data, this);\n}\n```\n\n**Note for Android**: `Adjust.AppWillOpenUrl(Android.Net.Uri)` method is marked as deprecated as of Android SDK v4.14.0. Please, use `Adjust.appWillOpenUrl(Android.Net.Uri, Context)` method instead.\n\n### \u003ca id=\"data-residency\"\u003e\u003c/a\u003eData residency\n\nIn order to enable data residency feature, make sure to set URL strategy setting of the `AdjustConfig` instance with one of the following constants:\n\n**For iOS apps:**\n\n```cs\nconfig.UrlStrategy = AdjustConfig.DataResidencyEU; // for EU data residency region\nconfig.UrlStrategy = AdjustConfig.DataResidencyTR; // for Turkey data residency region\nconfig.UrlStrategy = AdjustConfig.DataResidencyUS; // for US data residency region\n```\n\n**For Android apps:**\n\n```cs\nconfig.SetUrlStrategy(AdjustConfig.DataResidencyEu); // for EU data residency region\nconfig.SetUrlStrategy(AdjustConfig.DataResidencyTr); // for Turkey data residency region\nconfig.SetUrlStrategy(AdjustConfig.DataResidencyUs); // for US data residency region\n```\n\n[dashboard]:                    http://adjust.com\n[adjust.com]:                   http://adjust.com\n[demo-app-ios]:                 ./ios\n[demo-app-android]:             ./android\n[releases]:                     https://github.com/adjust/xamarin_sdk/releases\n[event-tracking]:               https://docs.adjust.com/en/event-tracking\n[callbacks-guide]:              https://docs.adjust.com/en/callbacks\n[special-partners]:             https://docs.adjust.com/en/special-partners\n[attribution-data]:             https://github.com/adjust/sdks/blob/master/doc/attribution-data.md\n[android-dashboard]:            http://developer.android.com/about/dashboards/index.html\n[android_application]:          http://developer.android.com/reference/android/app/Application.html\n[currency-conversion]:          https://docs.adjust.com/en/event-tracking/#tracking-purchases-in-different-currencies\n[android-launch-modes]:         https://developer.android.com/guide/topics/manifest/activity-element.html\n[ios-readme-deeplinking]:       https://github.com/adjust/ios_sdk/#deeplink-reattributions\n[reattribution-with-deeplinks]: https://docs.adjust.com/en/deeplinking/#manually-appending-attribution-data-to-a-deep-link\n\n## \u003ca id=\"license\"\u003e\u003c/a\u003eLicense\n\nThe Adjust SDK is licensed under the MIT License.\n\nCopyright (c) 2012-2021 Adjust GmbH, http://www.adjust.com\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\nof the Software, and to permit persons to whom the Software is furnished to do\nso, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadjust%2Fxamarin_sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fadjust%2Fxamarin_sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadjust%2Fxamarin_sdk/lists"}