{"id":20643932,"url":"https://github.com/adjust/marmalade_sdk","last_synced_at":"2025-04-16T02:06:51.638Z","repository":{"id":17097166,"uuid":"19862530","full_name":"adjust/marmalade_sdk","owner":"adjust","description":"This is the Marmalade SDK of http://www.adjust.com","archived":false,"fork":false,"pushed_at":"2021-11-16T21:57:28.000Z","size":40026,"stargazers_count":8,"open_issues_count":0,"forks_count":8,"subscribers_count":70,"default_branch":"master","last_synced_at":"2025-04-16T02:06:31.420Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","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":"2014-05-16T16:04:39.000Z","updated_at":"2024-01-24T01:17:28.000Z","dependencies_parsed_at":"2022-07-13T13:51:42.301Z","dependency_job_id":null,"html_url":"https://github.com/adjust/marmalade_sdk","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adjust%2Fmarmalade_sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adjust%2Fmarmalade_sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adjust%2Fmarmalade_sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adjust%2Fmarmalade_sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/adjust","download_url":"https://codeload.github.com/adjust/marmalade_sdk/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249183102,"owners_count":21226141,"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:20.002Z","updated_at":"2025-04-16T02:06:51.621Z","avatar_url":"https://github.com/adjust.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Summary\n\nThis is the Marmalade SDK of Adjust™. You can read more about Adjust™ at [adjust.com].\n\n## Table of contents\n\n* [Example app](#example-app)\n* [Basic integration](#basic-integration)\n   * [Get the SDK](#sdk-get)\n   * [Add the SDK to your project](#sdk-add)\n   * [Integrate the SDK into your app](#sdk-integrate)\n   * [Adjust logging](#adjust-logging)\n   * [Adjust project settings](#adjust-project-settings)\n      * [Android permissions](#android-permissions)\n      * [Google Play Services](#android-gps)\n      * [Proguard settings](#android-proguard)\n      * [Android install referrer](#android-broadcast-receiver)\n      * [iOS frameworks](#ios-frameworks)\n* [Additional features](#additional-features)\n   * [Event tracking](#event-tracking)\n      * [Revenue tracking](#revenue-tracking)\n      * [Revenue deduplication](#revenue-deduplication)\n      * [In-App Purchase verification](#iap-verification)\n      * [Callback parameters](#callback-parameters)\n      * [Partner parameters](#partner-parameters)\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   * [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      * [Adjust device identifier](#di-adid)\n   * [User attribution](#user-attribution)\n   * [Push token](#push-token)\n   * [Pre-installed trackers](#pre-installed-trackers)\n   * [Deep linking](#deeplinking)\n      * [Standard deep linking scenario](#deeplinking-standard)\n      * [Deferred deep linking scenario](#deeplinking-deferred)\n      * [Deep linking setup for Android](#deeplinking-android)\n      * [Deep linking setup for iOS](#deeplinking-ios)\n      * [Reattribution via deep links](#deeplinking-reattribution)\n* [License](#license)\n\n## \u003ca id=\"example-app\"\u003e\u003c/a\u003eExample app\n\nThere is an example app inside the [`example` directory][example-app]. You can use the example app to see how the Adjust SDK can be integrated.\n\n## \u003ca id=\"basic-integration\"\u003eBasic integration\n\nThese are the minimal steps required to integrate the Adjust SDK into your Marmalade project.\n\n**Note**: SDK 4.14.0 for Marmalade is built with **Marmalade 8.8.1** and we advise you to use this Marmalade version or higher. Especially if you want to rebuild our Marmalade extension on your own.\n\n### \u003ca id=\"sdk-get\"\u003e\u003c/a\u003eGet the SDK\n\nDownload the latest version from our [releases page][releases]. Extract the zip file in a folder of your choice.\n\n### \u003ca id=\"sdk-add\"\u003e\u003c/a\u003eAdd the SDK to your project\n\nAdd `AdjustMarmalade` as a subproject of your own.  Edit the `.mkb` file of your project and add the following line:\n\n```\nsubproject path_to_folder/adjust/AdjustMarmalade\n```\n\n### \u003ca id=\"sdk-integrate\"\u003e\u003c/a\u003eIntegrate the SDK into your app\n\nAdd the `AdjustMarmalade.h` header to your project where the `main` function is located. In the `main` function, initialize `adjust_config` structure and call the function `adjust_Start`.\n\n```cpp\n#include \"AdjustMarmalade.h\"\n\nint main() {\n    const char* app_token = \"{YourAppToken}\";\n    const char* environment = \"sandbox\";\n    const char* log_level = \"verbose\";\n\n    adjust_config* config = new adjust_config(app_token, environment);\n    config-\u003eset_log_level(log_level);\n\n    adjust_Start(config);\n\n    // ...\n}\n```\n\nReplace `{YourAppToken}` with your app token. You can this find 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```cpp\nconst char* environment = \"sandbox\";\nconst char* environment = \"production\";\n```\n\n**Important:** This value should be set to `sandbox` if and only if you or someone else is testing your app. Make sure to set the environment to `production` just before you publish the app. Set it back to `sandbox` 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=\"sdk-logging\"\u003e\u003c/a\u003eAdjust logging\n\nYou can increase or decrease the amount of logs you see in tests by calling `set_log_level` on your `adjust_config` instance with one of the following parameters:\n\n```cpp\nconfig-\u003eset_log_level(\"verbose\");   // enable all logging\nconfig-\u003eset_log_level(\"debug\");     // enable more logging\nconfig-\u003eset_log_level(\"info\");      // the default\nconfig-\u003eset_log_level(\"warn\");      // disable info logging\nconfig-\u003eset_log_level(\"error\");     // disable warnings as well\nconfig-\u003eset_log_level(\"assert\");    // disable errors as well\nconfig-\u003eset_log_level(\"suppress\");  // disable all log output\n```\n\n### \u003ca id=\"adjust-project-settings\"\u003e\u003c/a\u003eAdjust project settings\n\nOnce the Adjust SDK has been added to your app, certain tweeks are being performed so that the Adjust SDK can work properly. Below you can find a description of every additional thing that the Adjust SDK performs after you've added it to your app.\n\n### \u003ca id=\"android-permissions\"\u003e\u003c/a\u003eAndroid permissions\n\nThe Adjust SDK adds three permissions to your Android manifest file: `INTERNET`, `ACCESS_WIFI_STATE` and `ACCESS_NETWORK_STATE`. You can see in the `AdjustMarmalade.mkf` file of the Adjust SDK that the `android-extra-manifest` property is being set with content from the `adjust_permissions.xml` file, which is part of the Adjust SDK:\n\n```xml\n\u003cuses-permission android:name=\"android.permission.INTERNET\"/\u003e\n\u003c!-- ACCESS_WIFI_STATE is not needed if your app is using Google Play Services library --\u003e\n\u003cuses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/\u003e\n\u003cuses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/\u003e\n```\n\nThe `INTERNET` permission might be needed by our SDK at any point in time. The `ACCESS_NETWORK_STATE` permission is needed so that our SDK can read MCC and MNC values. The `ACCESS_WIFI_STATE` permission is needed by the Adjust SDK if your app is not targeting the Google Play Store and doesn't use Google Play Services. If you are targeting the Google Play Store and you are using Google Play Services, the Adjust SDK doesn't need this permission and, if you don't need it anywhere else in your app, you can remove it.\n\n### \u003ca id=\"android-gps\"\u003e\u003c/a\u003eGoogle Play Services\n\nSince 1 August 2014, all apps in the Google Play Store must use the [Google Advertising ID][google_ad_id] to uniquely identify devices. To allow the Adjust SDK to use the Google Advertising ID, you must integrate the [Google Play Services][google_play_services].\n\nIn order to add Google Play Services to your Marmalade app, you should edit your app's `.mkb` file and add  `s3eGooglePlayServices` in the `subprojects` list. In addition to this, you should add the following line to `deployment` list of your `.mkb` file:\n\n```\nandroid-extra-strings='(gps_app_id,your.app.package)'\n```\n\nAfter this, Google Play Services will be successfully integrated in your Marmalade app.\n\n### \u003ca id=\"android-proguard\"\u003e\u003c/a\u003eProguard 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 class dalvik.system.VMRuntime {\n    java.lang.String getRuntime();\n}\n-keep class android.os.Build {\n    java.lang.String[] SUPPORTED_ABIS;\n    java.lang.String CPU_ABI;\n}\n-keep class android.content.res.Configuration {\n    android.os.LocaleList getLocales();\n    java.util.Locale locale;\n}\n-keep class android.os.LocaleList {\n    java.util.Locale get(int);\n}\n-keep public class com.android.installreferrer.** { *; }\n```\n\n### \u003ca id=\"android-broadcast-receiver\"\u003e\u003c/a\u003eAndroid install referrer\n\nThe 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]. You can see in the `AdjustMarmalade.mkf` file that the `android-extra-application-manifest` property is being set with content from the `adjust_broadcast_receiver.xml` file:\n\n```xml\n\u003creceiver android:name=\"com.adjust.sdk.AdjustReferrerReceiver\" \n          android:exported=\"true\" \u003e\n    \u003cintent-filter\u003e\n        \u003caction android:name=\"com.android.vending.INSTALL_REFERRER\" /\u003e\n    \u003c/intent-filter\u003e\n\u003c/receiver\u003e\n```\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 add the Adjust broadcast receiver to your manifest file. You can remove it, but inside your own receiver add the call to the Adjust broadcast receiver as described in our [Android guide][broadcast-receiver-custom].\n\n### \u003ca id=\"ios-frameworks\"\u003e\u003c/a\u003eiOS frameworks\n\nThe Adjust SDK plugin adds three iOS frameworks to your generated Xcode project:\n\n* `iAd.framework` - in case you are running iAd campaigns.\n* `AdSupport.framework` - for reading iOS Advertising Id (IDFA).\n* `AdjustSdk.framework` - our native iOS SDK framework.\n\nSettings for this can also be found in `AdjustMarmalade.mkf` file of the Adjust SDK:\n\n```\niphone-link-opts=\"-weak_framework AdSupport -weak_framework iAd\"\niphone-link-opts=\"-F$CWD/sdk/iOS -framework AdjustSdk -ObjC\"\n```\n\nIf you are not running any iAd campaigns, you can feel free to remove the `iAd.framework` dependency.\n\n## \u003ca id=\"additional-features\"\u003e\u003c/a\u003eAdditional features\n\nYou can take advantage of the following features once the Adjust SDK is integrated into your project.\n\n### \u003ca id=\"event-tracking\"\u003e\u003c/a\u003eEvent tracking\n\nWith Adjust, you can track every event that you want. Suppose you want to track every tap on a button. Simply create a new event token in your [dashboard]. Let's say that event token is `abc123`. You can add the following line in your button’s click handler method to track the click:\n\n```cpp\nadjust_event* event = new adjust_event(\"abc123\");\nadjust_TrackEvent(event);\n```\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, then you can track those revenues with events. Let's say a tap is worth €0.01. You could track the revenue event like this:\n\n```cpp\nadjust_event* event = new adjust_event(\"abc123\");\nevent-\u003eset_revenue(0.01, \"EUR\");\n\nadjust_TrackEvent(event);\n```\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.\n\nIf you want to track in-app purchases, please make sure to call the `adjust_TrackEvent` only if the transaction is finished\nand item is purchased. That way you can avoid tracking revenue that is not actually being generated.\n\n```cpp\nadjust_event* event = new adjust_event(\"abc123\");\n\nevent-\u003eset_revenue(0.01, \"EUR\");\nevent-\u003eset_transaction_id(\"transaction_id\");\n\nadjust_TrackEvent(event);\n```\n\n**Note**: Transaction ID is the iOS term, unique identifier for successfully finished Android In-App-Purchases is named **Order ID**.\n\n### \u003ca id=\"iap-verification\"\u003e\u003c/a\u003eIn-App Purchase verification\n\nIn-App Purchase Verification can be done with Marmalade purchase SDK which is currently being developed and will soon be publicly available. For more information, please contact support@adjust.com.\n\n### \u003ca id=\"callback-parameters\"\u003e\u003c/a\u003eCallback parameters\n\nYou can also register a callback URL for that event in your [dashboard][dashboard] and we will send a GET request to that URL whenever the event gets tracked. In that case you can also put some key-value pairs in an object and pass it to the `adjust_TrackEvent` method. We will then append these named parameters to your callback URL.\n\nFor example, suppose you have registered the URL `http://www.adjust.com/callback` for your event with event token `abc123` and execute the following lines:\n\n```cpp\nadjust_event* event = new adjust_event(\"abc123\");\n\nevent-\u003eadd_callback_parameter(\"key\", \"value\");\nevent-\u003eadd_callback_parameter(\"foo\", \"bar\");\n\nadjust_TrackEvent(event);\n```\n\nIn this 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}` for iOS or `{gps_adid}` for Android that can be used as parameter values.  In the resulting callback the `{idfa}` placeholder would be replaced with the ID for Advertisers of the current device for iOS and the `{gps_adid}` would be replaced with the Google Advertising ID of the current device for Android. 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\nSimilarly to the callback parameters mentioned above, you can also add parameters that Adjust will transmit to the network partners of your choice. You can activate these networks in your Adjust dashboard.\n\nFor partner parameters to be added, you would need to call the `add_partner_parameter` method on your `adjust_event` instance.\n\n```cpp\nadjust_event* event = new adjust_event(\"abc123\");\n\nevent-\u003eadd_partner_parameter(\"key\", \"value\");\nevent-\u003eadd_partner_parameter(\"foo\", \"bar\");\n\nadjust_TrackEvent(event);\n```\n\nYou can read more about special partners and networks in our [guide to special partners][special-partners].\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 Session 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 method `adjust_AddSessionCallbackParameter`:\n\n```cpp\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 `adjust_RemoveSessionCallbackParameter`.\n\n```cpp\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 `adjust_ResetSessionCallbackParameters`.\n\n```cpp\nadjust_ResetSessionCallbackParameters();\n```\n\n### \u003ca id=\"session-partner-parameters\"\u003eSession partner parameters\n\nIn the same way that there is [session callback parameters](#session-callback-parameters) that are sent for every 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 its value to an event, it's added through a call to method `adjust_AddSessionPartnerParameter`:\n\n```cpp\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 `adjust_RemoveSessionPartnerParameter`.\n\n```cpp\nadjust_RemoveSessionPartnerParameter(\"foo\");\n```\n\nIf you wish to remove all keys and values from the session partner parameters, you can reset it with the method `adjust_ResetSessionPartnerParameters`.\n\n```cpp\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 sent on install.\n\nSet the initial delay time in seconds with the `set_delay_start` field of the `adjust_config` instance:\n\n```cpp\nconfig-\u003eset_delay_start(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\nAdjust can also send you a callback upon change of attribution. Due to the different sources considered for attribution, this information cannot be provided synchronously. Follow these steps to implement the optional callback in your application:\n\n1. Create void method which receives parameter of type `adjust_attribution_data*`.\n\n2. After creating instance of `adjust_config`, call its `set_attribution_callback` method\nwith the previously created method as parameter.\n\nThe callback function will get called when the SDK receives final attribution data. \nWithin the callback function you have access to the `attribution` parameter. \nHere is a quick summary of its properties:\n\n- `char* tracker_token` the tracker token of the current attribution.\n- `char* tracker_name` the tracker name of the current attribution.\n- `char* network` the network grouping level of the current attribution.\n- `char* campaign` the campaign grouping level of the current attribution.\n- `char* ad_group` the ad group grouping level of the current attribution.\n- `char* creative` the creative grouping level of the current attribution.\n- `char* click_label` the click label of the current attribution.\n- `char* adid` the Adjust device identifier.\n\n```cpp\n#include \"AdjustMarmalade.h\"\n\n//...\n\nstatic void trace_attribution_data(adjust_attribution_data* attribution) {\n    // Printing all attribution properties.\n    IwTrace(ADJUSTMARMALADE, (\"Attribution changed!\"));\n    IwTrace(ADJUSTMARMALADE, (attribution-\u003etracker_token));\n    IwTrace(ADJUSTMARMALADE, (attribution-\u003etracker_name));\n    IwTrace(ADJUSTMARMALADE, (attribution-\u003enetwork));\n    IwTrace(ADJUSTMARMALADE, (attribution-\u003ecampaign));\n    IwTrace(ADJUSTMARMALADE, (attribution-\u003ead_group));\n    IwTrace(ADJUSTMARMALADE, (attribution-\u003ecreative));\n    IwTrace(ADJUSTMARMALADE, (attribution-\u003eclick_label));\n}\n\n// ...\n\nint main() {\n    const char* app_token = \"{YourAppToken}\";\n    const char* environment = \"sandbox\";\n    const char* log_level = \"verbose\";\n\n    adjust_config* config = new adjust_config(app_token, environment);\n    config-\u003eset_log_level(log_level);\n    config-\u003eset_attribution_callback(trace_attribution_data);\n    \n    adjust_Start(config);\n\n    // ...\n}\n```\n\nPlease make sure to consider [applicable attribution data policies.][attribution-data]\n\n### \u003ca id=\"session-event-callbacks\"\u003e\u003c/a\u003eSession and event callbacks\n\nYou can register a callback to be notified of successful and failed tracked events and/or sessions.\n\nFollow the same steps to implement the following callback function for successfully tracked events:\n\n```cpp\n#include \"AdjustMarmalade.h\"\n\n//...\n\nstatic void trace_event_success_data(adjust_event_success_data* response) {\n    IwTrace(ADJUSTMARMALADE, (\"Event successfully tracked!\"));\n    IwTrace(ADJUSTMARMALADE, (response-\u003emessage));\n    IwTrace(ADJUSTMARMALADE, (response-\u003etimestamp));\n    IwTrace(ADJUSTMARMALADE, (response-\u003eevent_token));\n    IwTrace(ADJUSTMARMALADE, (response-\u003eadid));\n    IwTrace(ADJUSTMARMALADE, (response-\u003ejson_response));\n}\n\n// ...\n\nint main() {\n    const char* app_token = \"{YourAppToken}\";\n    const char* environment = \"sandbox\";\n    const char* log_level = \"verbose\";\n\n    adjust_config* config = new adjust_config(app_token, environment);\n    config-\u003eset_log_level(log_level);\n    config-\u003eset_event_success_callback(trace_event_success_data);\n    \n    adjust_Start(config);\n\n    // ...\n}\n```\n\nThe following callback function for failed tracked events:\n\n```cpp\n#include \"AdjustMarmalade.h\"\n\n//...\n\nstatic void trace_event_failure_data(adjust_event_failure_data* response) {\n    IwTrace(ADJUSTMARMALADE, (\"Event tracking failed!\"));\n    IwTrace(ADJUSTMARMALADE, (response-\u003emessage));\n    IwTrace(ADJUSTMARMALADE, (response-\u003etimestamp));\n    IwTrace(ADJUSTMARMALADE, (response-\u003eevent_token));\n    IwTrace(ADJUSTMARMALADE, (response-\u003eadid));\n    IwTrace(ADJUSTMARMALADE, (response-\u003ewill_retry));\n    IwTrace(ADJUSTMARMALADE, (response-\u003ejson_response));\n}\n\n// ...\n\nint main() {\n    const char* app_token = \"{YourAppToken}\";\n    const char* environment = \"sandbox\";\n    const char* log_level = \"verbose\";\n\n    adjust_config* config = new adjust_config(app_token, environment);\n    config-\u003eset_log_level(log_level);\n    config-\u003eset_event_failure_callback(trace_event_failure_data);\n    \n    adjust_Start(config);\n\n    // ...\n}\n```\n\nFor successfully tracked sessions:\n\n```cpp\n#include \"AdjustMarmalade.h\"\n\n//...\n\nstatic void trace_session_success_data(adjust_session_success_data* response) {\n    IwTrace(ADJUSTMARMALADE, (\"Session successfully tracked!\"));\n    IwTrace(ADJUSTMARMALADE, (response-\u003emessage));\n    IwTrace(ADJUSTMARMALADE, (response-\u003etimestamp));\n    IwTrace(ADJUSTMARMALADE, (response-\u003eadid));\n    IwTrace(ADJUSTMARMALADE, (response-\u003ejson_response));\n}\n\n// ...\n\nint main() {\n    const char* app_token = \"{YourAppToken}\";\n    const char* environment = \"sandbox\";\n    const char* log_level = \"verbose\";\n\n    adjust_config* config = new adjust_config(app_token, environment);\n    config-\u003eset_log_level(log_level);\n    config-\u003eset_session_success_callback(trace_session_success_data);\n    \n    adjust_Start(config);\n\n    // ...\n}\n```\n\nAnd for failed tracked sessions:\n\n```cpp\n#include \"AdjustMarmalade.h\"\n\n//...\n\nstatic void trace_session_failure_data(adjust_session_failure_data* response) {\n    IwTrace(ADJUSTMARMALADE, (\"Session tracking failed!\"));\n    IwTrace(ADJUSTMARMALADE, (response-\u003emessage));\n    IwTrace(ADJUSTMARMALADE, (response-\u003etimestamp));\n    IwTrace(ADJUSTMARMALADE, (response-\u003eadid));\n    IwTrace(ADJUSTMARMALADE, (response-\u003ewill_retry));\n    IwTrace(ADJUSTMARMALADE, (response-\u003ejson_response));\n}\n\n// ...\n\nint main() {\n    const char* app_token = \"{YourAppToken}\";\n    const char* environment = \"sandbox\";\n    const char* log_level = \"verbose\";\n\n    adjust_config* config = new adjust_config(app_token, environment);\n    config-\u003eset_log_level(log_level);\n    config-\u003eset_session_failure_callback(trace_session_failure_data);\n    \n    adjust_Start(config);\n\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- `const char* message` the message from the server or the error logged by the SDK.\n- `const char* timestamp` timestamp from the server.\n- `const char* adid` a unique device identifier provided by Adjust.\n- `const char* jsonResponse` the JSON object with the response from the server.\n\nBoth event response data objects contain:\n\n- `const char* eventToken` the event token, if the package tracked was an event.\n\nAnd both event and session failed objects also contain:\n\n- `const char* willRetry` indicates there will be an attempt to resend the package at a later time.\n\n### \u003ca id=\"disable-tracking\"\u003e\u003c/a\u003eDisable tracking\n\nYou can disable the Adjust SDK from tracking by invoking the method `adjust_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```cpp\nadjust_SetEnabled(false);\n```\n\nYou can verify if the Adjust SDK is currently active with the method `adjust_IsEnabled`. It is always possible to activate the Adjust SDK by invoking `adjust_SetEnabled` with the 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 while in offline mode.\n\nYou can activate offline mode by calling `adjust_SetOfflineMode` with the parameter `true`.\n\n```cpp\nadjust_SetOfflineMode(true);\n```\n\nConversely, you can deactivate offline mode by calling `adjust_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 `adjust_config` instance by calling `set_event_buffering_enabled` method:\n\n```cpp\n// ...\n\nint main() {\n    const char* app_token = \"{YourAppToken}\";\n    const char* environment = \"sandbox\";\n    const char* log_level = \"verbose\";\n\n    adjust_config* config = new adjust_config(app_token, environment);\n    config-\u003eset_log_level(log_level);\n    config-\u003eset_event_buffering_enabled(true);\n    \n    adjust_Start(config);\n\n    // ...\n}\n```\n\nIf nothing 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```cpp\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=\"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 `AdjustConfig` instance:\n```cpp\n// ...\n\nint main() {\n    const char* app_token = \"{YourAppToken}\";\n    const char* environment = \"sandbox\";\n    const char* log_level = \"verbose\";\n\n    adjust_config* config = new adjust_config(app_token, environment);\n    config-\u003eset_app_secret(secretId, info1, info2, info3, info4);\n    \n    adjust_Start(config);\n\n    // ...\n}\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 `adjust_config` instance by calling `set_is_sending_in_background_enabled` method:\n\n```cpp\n// ...\n\nint main() {\n    const char* app_token = \"{YourAppToken}\";\n    const char* environment = \"sandbox\";\n    const char* log_level = \"verbose\";\n\n    adjust_config* config = new adjust_config(app_token, environment);\n    config-\u003eset_log_level(log_level);\n    config-\u003eset_is_sending_in_background_enabled(true);\n    \n    adjust_Start(config);\n\n    // ...\n}\n```\n\nIf nothing is set, sending in background is **disabled by default**.\n\n### \u003ca id=\"device-ids\"\u003e\u003c/a\u003eDevice IDs\n\nCertain services (such as Google Analytics) require you to coordinate Device and Client IDs in order to prevent duplicate reporting.\n\n### \u003ca id=\"di-idfa\"\u003eiOS advertising identifier\n\nYou can access the IDFA value of an iOS device by setting the appropriate callback method on the `adjust_config` object and invoking the `adjust_GetIdfa` method:\n\n```cpp\n#include \"AdjustMarmalade.h\"\n\n//...\n\nstatic void trace_idfa_data(const char* response) {\n    IwTrace(ADJUSTMARMALADE, (\"IDFA received!\"));\n    IwTrace(ADJUSTMARMALADE, (response));\n}\n\n// ...\n\nint main() {\n    const char* app_token = \"{YourAppToken}\";\n    const char* environment = \"sandbox\";\n    const char* log_level = \"verbose\";\n\n    adjust_config* config = new adjust_config(app_token, environment);\n    config-\u003eset_log_level(log_level);\n    config-\u003eset_idfa_callback(trace_idfa_data);\n    \n    adjust_Start(config);\n\n    // ...\n    \n    adjust_GetIdfa();\n    \n    // ...\n}\n```\n\n### \u003ca id=\"di-gps-adid\"\u003e\u003c/a\u003eGoogle Play Services advertising identifier\n\nThe Adjust SDK provides you with the possibility to read the Google advertising identifier of the Android device on which your app is running. In order to do this, set the callback method on the `adjust_config` object which receives the `const char*` parameter. After setting this, if you invoke the `adjust_GetGoogleAdId` method, you will receive the Google advertising identifier value in your callback method:\n\n```cpp\n#include \"AdjustMarmalade.h\"\n\n//...\n\nstatic void trace_google_ad_id_data(const char* response) {\n    IwTrace(ADJUSTMARMALADE, (\"Google Advertising Identifier received!\"));\n    IwTrace(ADJUSTMARMALADE, (response));\n}\n\n// ...\n\nint main() {\n    const char* app_token = \"{YourAppToken}\";\n    const char* environment = \"sandbox\";\n    const char* log_level = \"verbose\";\n\n    adjust_config* config = new adjust_config(app_token, environment);\n    config-\u003eset_log_level(log_level);\n    config-\u003eset_google_ad_id_callback(trace_google_ad_id_data);\n    \n    adjust_Start(config);\n\n    // ...\n    \n    adjust_GetGoogleAdId();\n    \n    // ...\n}\n```\n\n### \u003ca id=\"di-adid\"\u003e\u003c/a\u003eAdjust device identifier\n\nFor every device with your app installed on it, the Adjust backend generates a unique **Adjust device identifier** (**adid**). In order to obtain this identifier, call the `adjust_GetAdid` method:\n\n```cpp\nchar* adid;\n\nadjust_GetAdid(\u0026adid);\n\nIwTrace(ADJUSTMARMALADE, (adid));\n```\n\n**Note**: Information about the **adid** is only available after an app 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** value before the SDK has been initialised and installation of your app has been successfully tracked.\n\n### \u003ca id=\"user-attribution\"\u003e\u003c/a\u003eUser attribution\n\nAs described in the [attribution callback section](#attribution-callback), this callback is triggered, providing you with information about a new attribution whenever it changes. If you want to access information about a user's current attribution whenever you need it, you can make a call to the `adjust_GetAttribution` method:\n\n```cpp\nadjust_attribution_data* attribution = new adjust_attribution_data();\nadjust_GetAttribution(attribution);\n\nIwTrace(ADJUSTMARMALADE, (attribution-\u003etracker_token));\nIwTrace(ADJUSTMARMALADE, (attribution-\u003etracker_name));\nIwTrace(ADJUSTMARMALADE, (attribution-\u003enetwork));\nIwTrace(ADJUSTMARMALADE, (attribution-\u003ecampaign));\nIwTrace(ADJUSTMARMALADE, (attribution-\u003ead_group));\nIwTrace(ADJUSTMARMALADE, (attribution-\u003ecreative));\nIwTrace(ADJUSTMARMALADE, (attribution-\u003eclick_label));\nIwTrace(ADJUSTMARMALADE, (attribution-\u003eadid));\n```\n\n**Note**: Information about current attribution is only available after an app installation has been tracked by the Adjust backend and the attribution callback has been triggered. From that moment on, the Adjust SDK has information about a user's attribution and you can access it with this method. So, **it is not possible** to access a user's attribution value before the SDK has been initialised and an attribution callback has been triggered.\n\n### \u003ca id=\"push-token\"\u003e\u003c/a\u003ePush token\n\nTo send us the push notification token, please call `adjust_SetDeviceToken` method **when you obtain your app's push notification token and when ever it changes it's value**:\n\n```cpp\nadjust_SetDeviceToken(\"YourPushNotificationToken\");\n```\n\nPush tokens are used for Audience Builder and client callbacks, and they are required for the upcoming uninstall tracking feature.\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\n1. Create a new tracker in your [dashboard].\n2. Open your app delegate and add set the default tracker of your `adjust_config` instance:\n\n    ```cpp\n    adjust_config* config = new adjust_config(app_token, environment);\n\n    config-\u003eset_default_tracker(\"{TrackerToken}\");\n    \n    adjust_Start(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\n3. Build and run your app. You should see a line like the following in the 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 \nget info about the deep link URL and its content. Hitting the URL can happen when the user has your app already installed \n(standard deep linking scenario) or if they don't have the app on their device (deferred deep linking scenario).\n\n### \u003ca id=\"deeplinking-standard\"\u003e\u003c/a\u003eStandard deep linking scenario\n\nStandard deep linking scenario is a platform specific feature and in order to support it, you need to add some additional \nsettings to your app.\n\nIn order to get info about the URL content in a standard deep linking scenario, you should set a callback method on the \n`adjust_config` object which will receive one `const char*` parameter where the content of the URL will be delivered. You \nshould set this method on the config object by calling the method `set_deeplink_callback`:\n\n```cpp\n#include \"AdjustMarmalade.h\"\n\n//...\n\nstatic void trace_deeplink_data(const char* response) \n{\n    IwTrace(ADJUSTMARMALADE, (\"Deeplink received!\"));\n    IwTrace(ADJUSTMARMALADE, (response));\n}\n\n// ...\n\nint main()\n{\n    const char* app_token = \"{YourAppToken}\";\n    const char* environment = \"sandbox\";\n    const char* log_level = \"verbose\";\n\n    adjust_config* config = new adjust_config(app_token, environment);\n    config-\u003eset_log_level(log_level);\n    config-\u003eset_deeplink_callback(trace_deeplink_data);\n    \n    adjust_Start(config);\n\n    // ...\n}\n```\n\n### \u003ca id=\"deeplinking-deferred\"\u003e\u003c/a\u003eDeferred deep linking scenario\n\nWhile deferred deep linking is not supported out of the box on Android and iOS, our Adjust SDK makes it possible.\n \nIn order to get info about the URL content in a deferred deep linking scenario, you should set a callback method on the \n`adjust_config` object which will receive one `const char*` parameter where the content of the URL will be delivered. You \nshould set this method on the config object by calling the method `set_deferred_deeplink_callback`:\n\n```cpp\n#include \"AdjustMarmalade.h\"\n\n//...\n\nstatic void trace_deferred_deeplink_data(const char* response) \n{\n    IwTrace(ADJUSTMARMALADE, (\"Deferred deeplink received!\"));\n    IwTrace(ADJUSTMARMALADE, (response));\n}\n\n// ...\n\nint main()\n{\n    const char* app_token = \"{YourAppToken}\";\n    const char* environment = \"sandbox\";\n    const char* log_level = \"verbose\";\n\n    adjust_config* config = new adjust_config(app_token, environment);\n    config-\u003eset_log_level(log_level);\n    config-\u003eset_deferred_deeplink_callback(trace_deferred_deeplink_data);\n    \n    adjust_Start(config);\n\n    // ...\n}\n```\n\nIn deferred deep linking scenario, there is one additional setting which can be set on the `adjust_config` object. Once the \nAdjust SDK gets the deferred deep link info, we are offering you the possibility to choose whether our SDK should open this \nURL or not. You can choose to set this option by calling the `set_should_deferred_deeplink_be_opened` method on the config \nobject:\n\n```cpp\n#include \"AdjustMarmalade.h\"\n\n//...\n\nstatic void trace_deferred_deeplink_data(const char* response) \n{\n    IwTrace(ADJUSTMARMALADE, (\"Deferred deeplink received!\"));\n    IwTrace(ADJUSTMARMALADE, (response));\n}\n\n// ...\n\nint main()\n{\n    const char* app_token = \"{YourAppToken}\";\n    const char* environment = \"sandbox\";\n    const char* log_level = \"verbose\";\n\n    adjust_config* config = new adjust_config(app_token, environment);\n    config-\u003eset_log_level(log_level);\n    config-\u003eset_should_deferred_deeplink_be_opened(false);\n    config-\u003eset_deferred_deeplink_callback(trace_deferred_deeplink_data);\n    \n    adjust_Start(config);\n\n    // ...\n}\n```\n\nIf nothing is set, **the Adjust SDK will always try to launch the URL by default**.\n\nTo enable your apps to support deep linking, you should set up schemes for each supported platform.\n\n### \u003ca id=\"deeplinking-android\"\u003e\u003c/a\u003eDeep linking setup for Android\n\nTo set a scheme name for your Android app, you should add the following `\u003cintent-filter\u003e` to the activity you want to launch\nafter deep linking (usually to your default Marmalade Android activity):\n\n```xml\n\u003cintent-filter\u003e\n    \u003caction android:name=\"android.intent.action.VIEW\" /\u003e\n    \u003ccategory android:name=\"android.intent.category.DEFAULT\" /\u003e\n    \u003ccategory android:name=\"android.intent.category.BROWSABLE\" /\u003e\n    \u003cdata android:scheme=\"schemeName\" /\u003e\n\u003c/intent-filter\u003e\n```\n\nYou should replace `schemeName` with your desired scheme name for Android app.\n\nAfter adding this intent filter to our example app, activity definition in `AndroidManifest.xml` looks like this:\n\n```xml\n\u003cactivity android:name=\".${CLASSNAME}\"\n          android:label=\"@string/app_name\"\n          android:configChanges=\"locale|keyboardHidden|orientation|screenSize\"\n          android:launchMode=\"singleTask\"\n          ${EXTRA_ACTIVITY_ATTRIBS}\u003e\n    \u003cintent-filter\u003e\n        \u003caction android:name=\"android.intent.action.MAIN\"/\u003e\n        \u003ccategory android:name=\"android.intent.category.LAUNCHER\"/\u003e\n    \u003c/intent-filter\u003e\n    \u003cintent-filter\u003e\n        \u003caction android:name=\"android.intent.action.VIEW\" /\u003e\n        \u003ccategory android:name=\"android.intent.category.DEFAULT\" /\u003e\n        \u003ccategory android:name=\"android.intent.category.BROWSABLE\" /\u003e\n        \u003cdata android:scheme=\"adjustExample\" /\u003e\n    \u003c/intent-filter\u003e\n\u003c/activity\u003e\n```\n\n### \u003ca id=\"deeplinking-ios\"\u003e\u003c/a\u003eDeep linking setup for iOS\n\nIn iOS, you need to set up the custom URL scheme name, but unlike Android, all that needs to be edited is your app's `.mkb` \nfile. You need to add the following lines to the `deployment` part of your app's `.mkb` file:\n\n```\niphone-bundle-url-name = com.your.bundle\niphone-bundle-url-schemes = schemeName\n```\n\nYou should replace `com.your.bundle` with your app's bundle ID and `schemeName` with your desired scheme name for iOS app.\n\n**Important**: By using this approach for deep linking support in iOS, you will support deep linking handling for devices \nwhich have **iOS 8 and lower**. Starting from **iOS 9**, Apple has introduced universal links for which, at this moment, \nthere's no built in support inside the Marmalade platform. To support this, you would need to edit the natively \ngenerated iOS project in Xcode (if possible) and add support to handle universal links from there. If you are interested in \nfinding out how to do that on the native side, please consult our [native iOS universal links guide][universal-links-guide].\n\n### \u003ca id=\"deeplinking-reattribution\"\u003e\u003c/a\u003eReattribution via deep links\n\nAdjust enables you to run re-engagement campaigns by using deep links. For more information on this, please \ncheck our [official docs][reattribution-with-deeplinks]. \n\nThe Adjust SDK supports this feature out of the box and no additional setup is needed in your app's code.\n\n\n[dashboard]:   http://adjust.com\n[adjust.com]:  http://adjust.com\n\n[releases]:               https://github.com/adjust/marmalade_sdk/releases\n[example-app]:            https://github.com/adjust/marmalade_sdk/tree/master/example\n[google_ad_id]:           https://developer.android.com/google/play-services/id.html\n[callbacks-guide]:        https://docs.adjust.com/en/callbacks\n[custom-receiver]:        https://github.com/adjust/android_sdk/blob/master/doc/referrer.md\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[broadcast-receiver]:     https://github.com/adjust/android_sdk#sdk-broadcast-receiver\n\n[google_play_services]:         http://developer.android.com/google/play-services/setup.html\n[universal-links-guide]:        https://github.com/adjust/ios_sdk/#deeplinking-setup-new\n[broadcast-receiver-custom]:    https://github.com/adjust/android_sdk/blob/master/doc/english/referrer.md\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-2018 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%2Fmarmalade_sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fadjust%2Fmarmalade_sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadjust%2Fmarmalade_sdk/lists"}