- Affise Attribution Android Library
- Description
- Features
- ProviderType identifiers collection
- Event send control
- Events tracking
- Custom events tracking
- Predefined event parameters
- Events buffering
- Advertising Identifier (google) tracking
- Open Advertising Identifier (huawei) tracking
- Install referrer tracking
- Push token tracking
- Uninstall tracking
- APK preinstall tracking
- Links
- Offline mode
- Disable tracking
- Disable background tracking
- GDPR right to be forgotten
- Get referrer
- Get referrer parameter
- Referrer keys
- Get module status
- Get random user Id
- Get Affice device Id
- Get providers
- Is first run
- WebView tracking
- Custom
- SDK to SDK integrations
- Debug
Affise SDK is a software you can use to collect app usage statistics, device identifiers, deeplink usage, track install referrer.
API24+Kotlin1.9+
For kotlin build script build.gradle.kts use:
val affise_version = "1.7.3"
dependencies {
// Add Affise library
implementation("com.affise:attribution:$affise_version")
// Add Affise modules
implementation("com.affise:module-advertising:$affise_version")
implementation("com.affise:module-androidid:$affise_version")
implementation("com.affise:module-link:$affise_version")
implementation("com.affise:module-network:$affise_version")
implementation("com.affise:module-phone:$affise_version")
implementation("com.affise:module-status:$affise_version")
implementation("com.affise:module-subscription:$affise_version")
// implementation("com.affise:module-appsflyer:$affise_version")
// implementation("com.affise:module-rustore:$affise_version")
// implementation("com.affise:module-huawei:$affise_version")
// implementation("com.affise:module-meta:$affise_version")
// implementation("com.affise:module-tiktok:$affise_version")
// Add install referrer
implementation("com.android.installreferrer:installreferrer:2.2")
}For groovy build script build.gradle use:
final affise_version = '1.7.3'
dependencies {
// Add Affise library
implementation "com.affise:attribution:$affise_version"
// Add Affise modules
implementation "com.affise:module-advertising:$affise_version"
implementation "com.affise:module-androidid:$affise_version"
implementation "com.affise:module-link:$affise_version"
implementation "com.affise:module-network:$affise_version"
implementation "com.affise:module-phone:$affise_version"
implementation "com.affise:module-status:$affise_version"
implementation "com.affise:module-subscription:$affise_version"
// implementation "com.affise:module-appsflyer:$affise_version"
// implementation "com.affise:module-rustore:$affise_version"
// implementation "com.affise:module-huawei:$affise_version"
// implementation "com.affise:module-meta:$affise_version"
// implementation "com.affise:module-tiktok:$affise_version"
// Add install referrer
implementation 'com.android.installreferrer:installreferrer:2.2'
}Download latest Affise SDK (attribution-1.7.3.aar)
from releases page and place this binary to gradle application
module lib directory app/libs/attribution-1.7.3.aar
Add library as gradle file dependency to application module build script Add install referrer library
For kotlin build script build.gradle.kts use:
val affise_version = "1.7.3"
dependencies {
// ...
// Add Affise library
implementation(files("libs/attribution-1.7.3.aar"))
// Add Affise modules
implementation(files("libs/module-advertising-$affise_version.aar"))
implementation(files("libs/module-androidid-$affise_version.aar"))
implementation(files("libs/module-link-$affise_version.aar"))
implementation(files("libs/module-network-$affise_version.aar"))
implementation(files("libs/module-phone-$affise_version.aar"))
implementation(files("libs/module-status-$affise_version.aar"))
implementation(files("libs/module-subscription-$affise_version.aar"))
// implementation(files("libs/module-appsflyer-$affise_version.aar"))
// implementation(files("libs/module-rustore-$affise_version.aar"))
// implementation(files("libs/module-huawei-$affise_version.aar"))
// implementation(files("libs/module-meta-$affise_version.aar"))
// implementation(files("libs/module-tiktok-$affise_version.aar"))
// Add install referrer
implementation("com.android.installreferrer:installreferrer:2.2")
}For groovy build script build.gradle use:
final affise_version = '1.7.3'
dependencies {
// ...
// Add Affise library
implementation files("libs/attribution-${affise_version}.aar")
// Add Affise modules
implementation files("libs/module-advertising-${affise_version}.aar")
implementation files("libs/module-androidid-${affise_version}.aar")
implementation files("libs/module-link-${affise_version}.aar")
implementation files("libs/module-network-${affise_version}.aar")
implementation files("libs/module-phone-${affise_version}.aar")
implementation files("libs/module-status-${affise_version}.aar")
implementation files("libs/module-subscription-${affise_version}.aar")
// implementation files("libs/module-appsflyer-${affise_version}.aar")
// implementation files("libs/module-rustore-${affise_version}.aar")
// implementation files("libs/module-huawei-${affise_version}.aar")
// implementation files("libs/module-meta-${affise_version}.aar")
// implementation files("libs/module-tiktok-${affise_version}.aar")
// Add install referrer
implementation 'com.android.installreferrer:installreferrer:2.2'
}After library is added as dependency sync project with gradle files and initialize.
Demo app App.kt
For kotlin use:
class App : Application() {
override fun onCreate() {
super.onCreate()
Affise
.settings(
affiseAppId = "Your appId", //Change to your app id
secretKey = "Your SDK secretKey", //Change to your SDK secretKey
)
.start(this) // Start Affise SDK
}
}For java use:
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
Affise
.settings(
"Your appId", //Change to your app id
"Your SDK secretKey" //Change to your SDK secretKey
)
.start(this); // Start Affise SDK
}
}Check Affise library initialization
Affise
.settings(
affiseAppId = "Your appId",
secretKey = "Your SDK secretKey",
)
.setOnInitSuccess {
// Called if library initialization succeeded
println("Affise: init success")
}
.setOnInitError {
// Called if library initialization failed
println("Affise: init error ${it.localizedMessage}")
}
.start(this)Caution
π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯
Please make sure your credentials are valid
Visit section validation credentials
π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯
Set SDK server domain:
class App : Application() {
override fun onCreate() {
super.onCreate()
Affise
.settings(
affiseAppId = "Your appId",
secretKey = "Your SDK secretKey",
)
.setDomain("https://YoureCustomDomain/") // Set custom domain
.start(this) // Start Affise SDK
}
}Caution
π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯
How to install modules read in Integration section
π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯
| Module | Version |
|---|---|
Advertising |
|
AndroidId |
|
AppsFlyer |
|
Link |
|
Network |
|
Phone |
|
Status |
|
Subscription |
|
RuStore |
|
Huawei |
|
Meta |
|
TikTok |
Get list of installed modules:
Affise.Module.getModulesInstalled()To manually stop modules from starting use Affise.settings.setDisableModules:
Affise
.settings(
affiseAppId = "Your appId",
secretKey = "Your SDK secretKey",
)
.setDisableModules(listOf(
AffiseModules.Advertising,
AffiseModules.Subscription,
))
.start(this) // Start Affise SDKCaution
π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯
For module Advertising to send GAID (Google Advertising ID)
Uses com.google.android.gms:play-services-ads-identifier
π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯
val gaid = Affise.getProviders()[ProviderType.GAID_ADID] as? StringSend AppsFlyer event data to Affise
//AppsFlyer event data
val eventValues: Map<String, Any> = mapOf(
AFInAppEventParameterName.PRICE to 1234.56,
AFInAppEventParameterName.CONTENT_ID to "1234567",
)
// Send AppsFlyer event
AppsFlyerLib.getInstance().logEvent(
applicationContext,
AFInAppEventType.ADD_TO_WISH_LIST, eventValues
)
// Send AppsFlyer data to Affise
Affise.Module.AppsFlyer.logEvent(AFInAppEventType.ADD_TO_WISH_LIST, eventValues)Is Module present:
Affise.Module.AppsFlyer.hasModule()Caution
π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯
Use Huawei Module to get OAID (Open Advertising Identifier)
Uses com.huawei.hms:ads-identifier
π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯
val oaid = Affise.getProviders()[ProviderType.OAID] as? StringReturn last url in chan of redirection
π₯Support MAX 10 redirectionsπ₯
Affise.Module.Link.resolve("SITE_WITH_REDIRECTION") { redirectUrl ->
// handle redirect url
}For java use:
Affise.Module.Link.resolve("SITE_WITH_REDIRECTION", redirectUrl -> {
// handle redirect url
});Is Module present:
Affise.Module.Link.hasModule()- Add
queriesto yourAndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<queries>
<package android:name="com.facebook.katana" />
<package android:name="com.instagram.android" />
<package android:name="com.facebook.lite" />
</queries>
<application>
...
</application>
</manifest>- Add your
Facebook App Idas config valueAffiseConfig.FbAppIdinAffise.settings
Affise
.settings(
affiseAppId = "Your appId",
secretKey = "Your SDK secretKey",
)
.setConfigValue(AffiseConfig.FbAppId, "Your Facebook App Id")
.start(this)Affise.Module.getStatus(AffiseModules.Status) { response ->
// handle response
}Get products by ids:
val ids = ["exampple.product.id_1", "exampple.product.id_2"]
Affise.Module.Subscription.fetchProducts(ids) { result ->
when (result) {
is AffiseResult.Success -> {
val products: List<AffiseProduct> = result.value.products
val invalidIds: List<String> = result.value.invalidIds
}
is AffiseResult.Error -> {
val error: String = result.error.message
}
}
}Purchase product:
// Specify AffiseProductType for correct affise event
Affise.Module.Subscription.purchase(activity, product, AffiseProductType.CONSUMABLE) { result ->
when (result) {
is AffiseResult.Success -> {
val purchasedInfo: AffisePurchasedInfo = result.value
}
is AffiseResult.Error -> {
val error: String = result.error.message
}
}
}Is Module present:
Affise.Module.Subscription.hasModule()CONSUMABLENON_CONSUMABLERENEWABLE_SUBSCRIPTIONNON_RENEWABLE_SUBSCRIPTION
Required com.github.tiktok:tiktok-business-android-sdk
Send TikTok event data to Affise TikTok Docs
//TikTok event data
val event = TTAddToCartEvent.newBuilder("TikTok event id")
.setDescription("product1")//Description of the item or page.
.setCurrency(TTContentsEventConstants.Currency.JPY)//The ISO 4217 currency code.
.setValue(123.4)//Value of the order or items sold.
.setContents(
TTContentParams.newBuilder()//Relevant products in an event with product information.
.setContentId("item1")//Unique ID of the product or content.
.setContentCategory("game")//Category of the page or product.
.setBrand("tt")//Brand name of the product item.
.setPrice(123.4f)//The price of the item.
.setQuantity(1)//The number of items.
.setContentName("item1 test")
.build()
)//Name of the page or product.
.setContentType("IAP")//The type of content in the event.
.build()
// Send TikTok event
TikTokBusinessSdk.trackTTEvent(event)
// Send TikTok data to Affise
Affise.Module.TikTok.sendEvent(event.eventName, event.properties, event.eventId)Is Module present:
Affise.Module.TikTok.hasModule()For a minimal working functionality your app needs to declare internet permission:
<manifest>
<!-- ... -->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>Some methods require to return same data on application reinstall
It is achieved by using Affise AndroidId Module
Such SDK methods are:
To simulate multiple device install for testing purpose you can use one of two options:
- Disable module dependencies:
// Disable module dependency
// implementation("com.affise:module-androidid:$affise_version")- Disable module programmatically:
Affise
.settings(
affiseAppId = "Your appId",
secretKey = "Your SDK secretKey",
)
.setDisableModules(listOf(
AffiseModules.AndroidId, // Disable module programmatically
))
.start(this)Note
Read more about Persistent data
There are two working mode for Affice device Id:
- Return persistent value on each reinstall
- Return new value on each reinstall
First mode require enabling Affise AndroidId Module
// Enable module dependency
implementation("com.affise:module-androidid:$affise_version")Even after deleting application Affice device Id will be preserved and will restore on next installation
Second mode is convenient for testing. By removing dependency or disabling module programmatically, a new Affice device Id will be generated for each new installation.
To match users with events and data library is sending, these ProviderType identifiers are collected:
AFFISE_APP_IDAFFISE_PKG_APP_NAMEAFF_APP_NAME_DASHBOARDAPP_VERSIONAPP_VERSION_RAWSTORETRACKER_TOKENTRACKER_NAMEFIRST_TRACKER_TOKENFIRST_TRACKER_NAMELAST_TRACKER_TOKENLAST_TRACKER_NAMEOUTDATED_TRACKER_TOKENINSTALLED_TIMEFIRST_OPEN_TIMEINSTALLED_HOURFIRST_OPEN_HOURINSTALL_FIRST_EVENTINSTALL_BEGIN_TIMEINSTALL_FINISH_TIMEREFERRER_INSTALL_VERSIONREFERRAL_TIMEREFERRER_CLICK_TIMEREFERRER_CLICK_TIME_SERVERREFERRER_GOOGLE_PLAY_INSTANTCREATED_TIMECREATED_TIME_MILLICREATED_TIME_HOURUNINSTALL_TIMEREINSTALL_TIMELAST_SESSION_TIMECPU_TYPEHARDWARE_NAMEDEVICE_MANUFACTURERDEEPLINK_CLICKDEVICE_ATLAS_IDAFFISE_DEVICE_IDAFFISE_ALT_DEVICE_IDREFTOKENREFTOKENSREFERRERREFERRER_UPDATEDUSER_AGENTMCCODEMNCODEREGIONCOUNTRYLANGUAGEDEVICE_NAMEDEVICE_TYPEOS_NAMEPLATFORMSDK_PLATFORMAPI_LEVEL_OSAFFISE_SDK_VERSIONOS_VERSIONRANDOM_USER_IDAFFISE_SDK_POSTIMEZONE_DEVAFFISE_EVENT_NAMEAFFISE_EVENT_TOKENLAST_TIME_SESSIONTIME_SESSIONAFFISE_SESSION_COUNTLIFETIME_SESSION_COUNTAFFISE_DEEPLINKAFFISE_PART_PARAM_NAMEAFFISE_PART_PARAM_NAME_TOKENAFFISE_APP_TOKENLABELAFFISE_SDK_SECRET_IDUUIDAFFISE_APP_OPENEDPUSHTOKENPUSHTOKEN_SERVICEAFFISE_EVENTS_COUNTAFFISE_SDK_EVENTS_COUNTAFFISE_METRICS_EVENTS_COUNTAFFISE_INTERNAL_EVENTS_COUNTIS_ROOTEDIS_EMULATOR
GAID_ADIDGAID_ADID_MD5ADIDALTSTR_ADIDFIREOS_ADIDCOLOROS_ADIDAD_PERSONALIZATION
ANDROID_IDANDROID_ID_MD5
OAIDOAID_MD5
META
MAC_SHA1MAC_MD5CONNECTION_TYPEPROXY_IP_ADDRESS
NETWORK_TYPEISP
There are two ways to send events
- Cache event to later scheduled send in batch
AddToCartEvent()
.send()- Send event right now
AddToCartEvent()
.sendNow({
// handle event send success
}) { errorResponse ->
// handle event send failed
// π₯Warning:π₯ event is NOT cached for later send
}Demo app DefaultEventsFactory.kt
For example, we want to track what items usually user adds to shopping cart. To send event first create it with following code
class Presenter {
fun onUserAddsItemsToCart(userData: String) {
AddToCartEvent(userData)
.send() // Send event
}
}For java use:
class Presenter {
void onUserAddsItemsToCart(String userData) {
new AddToCartEvent(userData)
.send(); // Send event
}
}With above example you can implement other events:
AchieveLevelAddPaymentInfoAddToCartAddToWishlistAdRevenueClickAdvCompleteRegistrationCompleteStreamCompleteTrialCompleteTutorialContactContentItemsViewCustomizeProductDeepLinkedDonateFindLocationInitiateCheckoutInitiatePurchaseInitiateStreamInviteLastAttributedTouchLeadListViewLoginOpenedFromPushNotificationOrderOrderItemAddedOrderItemRemoveOrderCancelOrderReturnRequestOrderReturnRequestCancelPurchaseRateReEngageReserveSalesScheduleSearchShareSpendCreditsStartRegistrationStartTrialStartTutorialSubmitApplicationSubscribeTravelBookingUnlockAchievementUnsubscribeUpdateViewAdvViewCartViewContentViewItemViewItemsInitialSubscriptionInitialTrialInitialOfferConvertedTrialConvertedOfferTrialInRetryOfferInRetrySubscriptionInRetryRenewedSubscriptionFailedSubscriptionFromRetryFailedOfferFromRetryFailedTrialFromRetryFailedSubscriptionFailedOfferiseFailedTrialReactivatedSubscriptionRenewedSubscriptionFromRetryConvertedOfferFromRetryConvertedTrialFromRetryUnsubscription
Use any of custom events if default doesn't fit your scenario:
CustomId01CustomId02CustomId03CustomId04CustomId05CustomId06CustomId07CustomId08CustomId09CustomId10
If above event functionality still limits your usecase, you can use UserCustomEvent
UserCustomEvent("MyCustomNameEvent")
.addPredefinedParameter(PredefinedString.DESCRIPTION, "best before 2029")
.addPredefinedParameter(PredefinedObject.CONTENT, JSONObject().apply {
put("collection", "Greatest Hits")
})
.send() // Send eventTo enrich your event with another dimension, you can use predefined parameters for most common cases. Add it to any event:
class Presenter {
fun onUserAddsItemsToCart(userData: String) {
AddToCartEvent(userData)
.addPredefinedParameter(PredefinedString.DESCRIPTION, "best before 2029")
.addPredefinedParameter(PredefinedObject.CONTENT, JSONObject().apply {
put("collection", "Greatest Hits")
})
.addPredefinedParameter(PredefinedListObject.CONTENT_LIST, listOf(
JSONObject().apply {
put("content", "songs, videos")
}
))
.send() // Send event
}
}For java use:
class Presenter {
void onUserAddsItemsToCart(String userData) {
JSONObject json = new JSONObject()
.put("collection", "Greatest Hits");
JSONObject jsonContent = new JSONObject()
.put("content", "songs, videos");
List<JSONObject> jsonList = Collections.singletonList(jsonContent);
new AddToCartEvent(userData, System.currentTimeMillis())
.addPredefinedParameter(PredefinedString.DESCRIPTION, "best before 2029")
.addPredefinedParameter(PredefinedFloat.PRICE, 2.19f)
.addPredefinedParameter(PredefinedObject.CONTENT, json)
.addPredefinedParameter(PredefinedListObject.CONTENT_LIST, jsonList)
.send(); // Send event
}
}In examples above PredefinedString.DESCRIPTION and PredefinedFloat.PRICE is used, but many others is available:
| PredefinedParameter | Type |
|---|---|
| PredefinedString | String |
| PredefinedLong | Long |
| PredefinedFloat | Float |
| PredefinedObject | JSONObject |
| PredefinedListObject | List<JSONObject> |
| PredefinedListString | List<String> |
ACHIEVEMENT_IDADREV_AD_TYPEBRANDBRICKCAMPAIGN_IDCATALOGUE_IDCHANNEL_TYPECITYCLASSCLICK_IDCONTENT_IDCONTENT_NAMECONTENT_TYPECONVERSION_IDCOUNTRYCOUPON_CODECURRENCYCUSTOMER_SEGMENTCUSTOMER_TYPECUSTOMER_USER_IDDEEP_LINKDESCRIPTIONDESTINATION_ADESTINATION_BDESTINATION_LISTEVENT_NAMENEW_VERSIONNETWORKOLD_VERSIONORDER_IDPARAM_01PARAM_02PARAM_03PARAM_04PARAM_05PARAM_06PARAM_07PARAM_08PARAM_09PARAM_10PAYMENT_INFO_AVAILABLEPIDPLACEMENTPREFERRED_NEIGHBORHOODSPRODUCT_IDPRODUCT_NAMEPURCHASE_CURRENCYRECEIPT_IDREGIONREGISTRATION_METHODREVIEW_TEXTSEARCH_STRINGSEGMENTSOURCESTATUSSUBSCRIPTION_IDSUCCESSSUGGESTED_DESTINATIONSSUGGESTED_HOTELSTUTORIAL_IDUNITUTM_CAMPAIGNUTM_MEDIUMUTM_SOURCEVALIDATEDVERTICALVIRTUAL_CURRENCY_NAMEVOUCHER_CODE
AMOUNTDATE_ADATE_BDEPARTING_ARRIVAL_DATEDEPARTING_DEPARTURE_DATEHOTEL_SCORELEVELMAX_RATING_VALUENUM_ADULTSNUM_CHILDRENNUM_INFANTSPREFERRED_NUM_STOPSPREFERRED_STAR_RATINGSQUANTITYRATING_VALUERETURNING_ARRIVAL_DATERETURNING_DEPARTURE_DATESCORETRAVEL_STARTTRAVEL_ENDUSER_SCOREEVENT_STARTEVENT_END
PREFERRED_PRICE_RANGEPRICEREVENUELATLONG
CONTENT
CONTENT_LIST
CONTENT_IDS
Affise library will send any pending events with first opportunity, but if there is no network connection or device is disabled, events are kept locally for 7 days before deletion.
Note
Requires Affise Advertising Module
Advertising Identifier (google) tracking is supported automatically, no actions needed
Note
Requires Affise Huawei Module
Open Advertising Identifier is supported automatically, no actions needed
Install referrer tracking is supported automatically, no actions needed
To let affise track push token you need to receive it from your push service provider, and pass to Affise library. First add firebase integration to your app completing these steps: Firebase Docs
After you have done with firebase integration, add to your cloud messaging service onNewToken method Affise.addPushToken(token)
Example PushService.kt:
class FirebaseCloudMessagingService : FirebaseMessagingService() {
override fun onNewToken(token: String) {
// New token generated
Affise.addPushToken(token)
}
}Affise automatically track reinstall events by using silent-push technology, to make this feature work, pass push token when it is recreated by user and on you application starts up
See example Push token tracking
SDK is also supports scenario when APK is installed not from one of application markets, such as google play, huawei appgallery or amazon appstore
To use this feature, create file with name partner_key in your app assets directory, and write unique identifier inside, this key will be passed to our backend so you can track events by partner later in your Affise console.
Caution
π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯
Deeplinks support only CUSTOM scheme NOT http or https
For http or https read how to setup AppLinks
π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯
To integrate deeplink support you need:
- Add intent filter to one of your activities
- Add custom scheme (NOT
httporhttps) and host to filter
Example: YOUR_SCHEME://YOUR_DOMAIN
Example: myapp://mydomain.com
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="YOUR_SCHEME" />
<data android:host="YOUR_DOMAIN" />
</intent-filter>- Register deeplink callback right after
Affise.settings(..).start(..)
for kotlin:
Affise.settings(affiseAppId, secretKey).start(context) // Start Affise SDK
Affise.registerDeeplinkCallback { value ->
// full uri "scheme://host/path?parameters"
val deeplink = value.deeplink
// separated for convenience
val scheme = value.scheme
val host = value.host
val path = value.path
val queryParametersMap = value.parameters
if(queryParametersMap["<your_uri_key>"].contains("<your_uri_key_value>")) {
// handle value
}
}for java:
Affise.registerDeeplinkCallback(value -> {
// full uri "scheme://host/path?parameters"
String deeplink = value.getDeeplink();
// separated for convenience
String scheme = value.getScheme();
String host = value.getHost();
String path = value.getPath();
Map<String, List<String>> queryParametersMap = value.getParameters();
if (queryParametersMap.get("your_uri_key").contains("your_uri_key_value")) {
// handle value
}
});Test DeepLink via terminal command:
adb shell am start -a android.intent.action.VIEW -d "YOUR_SCHEME://YOUR_DOMAIN/somepath?param=1\&list=some\&list=other\&list="
Caution
π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯
You must own website domain.
And has ability to add file https://yoursite/.well-known/assetlinks.json
π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯
To integrate applink support you need:
- Add intent filter to one of your activities
- Add
httpsorhttpscheme and host to filter
Example: https://YOUR_DOMAIN
Example: https://mydomain.com
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="YOUR_DOMAIN" />
</intent-filter>-
Associate your app with your website. Read Google instructions
Details
How To Associate your app with your website
After setting up URL support for your app, the App Links Assistant generates a Digital Assets Links file you can use to associate your website with your app.
As an alternative to using the Digital Asset Links file, you can associate your site and app in Search Console.
If you're using Play App Signing for your app, then the certificate fingerprint produced by the App Links Assistant usually doesn't match the one on users' devices. In this case, you can find the correct Digital Asset Links JSON snippet for your app in your Play Console developer account under Release > Setup > App signing.
To associate your app and your website using the App Links Assistant, click Open Digital Asset Links File Generator from the App Links Assistant and follow these steps:
Figure 2. Enter details about your site and app to generate a Digital Asset Links file.
-
Enter your Site domain and your Application ID.
-
To include support in your Digital Asset Links file for One Tap sign-in, select Support sharing credentials between the app and the website and enter your site's sign-in URL.This adds the following string to your Digital Asset Links file declaring that your app and website share sign-in credentials:
delegate_permission/common.get_login_creds. -
Specify the signing config or select a keystore file.
Make sure you select the right release config or keystore file for the release build or the debug config or keystore file for the debug build of your app. If you want to set up your production build, use the release config. If you want to test your build, use the debug config.
- Click Generate Digital Asset Links file.
- Once Android Studio generates the file, click Save file to download it.
- Upload the
assetlinks.jsonfile to your site, with read access for everyone, athttps://yoursite/.well-known/assetlinks.json.
[!IMPORTANT]
The system verifies the Digital Asset Links file via the encrypted HTTPS protocol. Make sure that the assetlinks.json file is accessible over an HTTPS connection, regardless of whether your app's intent filter includes https.
- Click Link and Verify to confirm that you've uploaded the correct Digital Asset Links file to the correct location.
Learn more about associating your website with your app through the Digital Asset Links file in Declare website associations.
-
- Register deeplink callback right after
Affise.settings(..).start(..)
for kotlin:
Affise.settings(affiseAppId, secretKey).start(context) // Start Affise SDK
Affise.registerDeeplinkCallback { value ->
// full uri "scheme://host/path?parameters"
val deeplink = value.deeplink
// separated for convenience
val scheme = value.scheme
val host = value.host
val path = value.path
val queryParametersMap = value.parameters
if(queryParametersMap["<your_uri_key>"].contains("<your_uri_key_value>")) {
// handle value
}
}for java:
Affise.registerDeeplinkCallback(value -> {
// full uri "scheme://host/path?parameters"
String deeplink = value.getDeeplink();
// separated for convenience
String scheme = value.getScheme();
String host = value.getHost();
String path = value.getPath();
Map<String, List<String>> queryParametersMap = value.getParameters();
if (queryParametersMap.get("your_uri_key").contains("your_uri_key_value")) {
// handle value
}
});Test AppLinks via terminal command:
adb shell am start -a android.intent.action.VIEW -d "https://YOUR_DOMAIN/somepath?param=1\&list=some\&list=other\&list="
Note
Requires Affise Status Module
Use the next public method of SDK
Affise.getDeferredDeeplink { deferredDeeplink ->
// handle deferred deeplink
}Note
Requires Affise Status Module
Use the next public method of SDK to get referrer parameter by
Affise.getDeferredDeeplinkValue(ReferrerKey.CLICK_ID) { deferredDeeplinkValue ->
// handle deferred deeplink value
}In some scenarios you would want to limit Affise network usage, to pause that activity call anywhere in your application following code after Affise init:
Affise.settings(affiseAppId, secretKey).start(context) // Start Affise SDK
Affise.setOfflineModeEnabled(true) // to enable offline mode
Affise.setOfflineModeEnabled(false) // to disable offline modeWhile offline mode is enabled, your metrics and other events are kept locally, and will be delivered once offline mode is disabled. Offline mode is persistent as Application lifecycle, and will be disabled with process termination automatically. To check current offline mode status call:
Affise.isOfflineModeEnabled() // returns true or false describing current tracking stateTo disable any tracking activity, storing events and gathering device identifiers and metrics call anywhere in your application following code after Affise init:
Affise.settings(affiseAppId, secretKey).start(context) // Start Affise SDK
Affise.setTrackingEnabled(true) // to enable tracking
Affise.setTrackingEnabled(false) // to disable trackingBy default tracking is enabled.
While tracking mode is disabled, metrics and other identifiers is not generated locally. Keep in mind that this flag is persistent until app reinstall, and don't forget to reactivate tracking when needed. To check current status of tracking call:
Affise.isTrackingEnabled() // returns true or false describing current tracking stateTo disable any background tracking activity, storing events and gathering device identifiers and metrics call anywhere in your application following code after Affise init:
Affise.settings(affiseAppId, secretKey).start(context) // Start Affise SDK
Affise.setBackgroundTrackingEnabled(true) // to enable background tracking
Affise.setBackgroundTrackingEnabled(false) // to disable background trackingBy default background tracking is enabled.
While background tracking mode is disabled, metrics and other identifiers is not generated locally. Background tracking mode is persistent as Application lifecycle, and will be re-enabled with process termination automatically. To check current status of background tracking call:
Affise.isBackgroundTrackingEnabled() // returns true or false describing current background tracking stateUnder the EU's General Data Protection Regulation (GDPR): An individual has the right to have their personal data erased. To provide this functionality to user, as the app developer, you can call
Affise.settings(affiseAppId, secretKey).start(context) // Start Affise SDK
Affise.forget() // to forget users dataAfter processing such request our backend servers will delete all users data. To prevent library from generating new events, disable tracking just before calling Affise.forget:
Affise.settings(affiseAppId, secretKey).start(context) // Start Affise SDK
Affise.setTrackingEnabled(false)
Affise.forget() // to forget users dataUse the next public method of SDK
To get Install referrer by installing from RuStore include module
RuStore
To get Install referrer by installing from AppGallery include module
Huawei
For kotlin:
Affise.getReferrerUrl { referrer ->
// handle referrer
}For java:
Affise.getReferrerUrl(referrer -> {
// handle referrer
});Use the next public method of SDK to get referrer parameter by
To get Install referrer by installing from RuStore include module
RuStore
To get Install referrer by installing from AppGallery include module
Huawei
For kotlin:
Affise.getReferrerUrlValue(ReferrerKey.CLICK_ID) { value ->
// handle referrer value
}For java:
Affise.getReferrerUrlValue(ReferrerKey.CLICK_ID, value -> {
// handle referrer value
});In examples above ReferrerKey.CLICK_ID is used, but many others is available:
AD_IDCAMPAIGN_IDCLICK_IDAFFISE_ADAFFISE_AD_IDAFFISE_AD_TYPEAFFISE_ADSETAFFISE_ADSET_IDAFFISE_AFFC_IDAFFISE_CHANNELAFFISE_CLICK_LOOK_BACKAFFISE_COST_CURRENCYAFFISE_COST_MODELAFFISE_COST_VALUEAFFISE_DEEPLINKAFFISE_KEYWORDSAFFISE_MEDIA_TYPEAFFISE_MODELAFFISE_OSAFFISE_PARTNERAFFISE_REFAFFISE_SITE_IDAFFISE_SUB_SITE_IDAFFISE_SUB_1AFFISE_SUB_2AFFISE_SUB_3AFFISE_SUB_4AFFISE_SUB_5AFFCPIDSUB_1SUB_2SUB_3SUB_4SUB_5
Caution
π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯
Required Module Status
π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯
Get state of the module:
For kotlin:
Affise.Module.getStatus(AffiseModules.Status) { response ->
// handle response
}For java:
Affise.Module.getStatus(AffiseModules.Status, response -> {
// handle response
});Use the next public method of SDK
For kotlin:
Affise.getRandomUserId()Caution
π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯
Return 11111111-1111-1111-1111-111111111111 if Affise SDK not initialized
Return 22222222-2222-2222-2222-222222222222 if no valid methods to retrieve id for current device
AffiseError.UUID_NOT_INITIALIZED == 11111111-1111-1111-1111-111111111111
AffiseError.UUID_NO_VALID_METHOD == 22222222-2222-2222-2222-222222222222
π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯
Note
Use Affise AndroidId Module to make device id more persistent on application reinstall
Note
Read more about Persistent data and Reinstall tracking
Use the next public method of SDK
For kotlin:
Affise.getRandomDeviceId()Caution
π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯
Return 11111111-1111-1111-1111-111111111111 if Affise SDK not initialized
Return 22222222-2222-2222-2222-222222222222 if no valid methods to retrieve id for current device
AffiseError.UUID_NOT_INITIALIZED == 11111111-1111-1111-1111-111111111111
AffiseError.UUID_NO_VALID_METHOD == 22222222-2222-2222-2222-222222222222
π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯
Returns providers map with ProviderType as key
val providers: Map<ProviderType, Any?> = Affise.getProviders()
val key = ProviderType.AFFISE_APP_TOKEN
val value = providers[key]Caution
π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯
Return Empty Map if Affise SDK not initialized
π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯
Use the next public method of SDK
For kotlin:
Affise.isFirstRun()To integrate the library into the JavaScript environment, we added a bridge between JavaScript and the native SDK. Now you can send events and use the functionality of the native library directly from WebView. Here are step by step instructions:
// retrieve WebView from view hierarchy
val webView = findViewById<WebView>(R.Id.your_webview_id)
// make sure javascript is enabled
webView.javaScriptEnabled = true
// initialize WebView with Affise native library
Affise.registerWebView(webView)Other Javascript environment features is described below.
Demo app index.html
After WebView is initialized you send events from JavaScript environment
let data = { card: 4138, type: 'phone' };
new AddPaymentInfoEvent({
userData: 'taxi',
})
.addPredefinedParameter(PredefinedString.PURCHASE_CURRENCY, 'USD')
.addPredefinedParameter(PredefinedObject.CONTENT, data)
.addPredefinedParameter(PredefinedFloat.PRICE, 2.19)
.send(); // Send eventJust like with native SDK, javascript environment also provides default events that can be passed from WebView:
AchieveLevelEventAddPaymentInfoEventAddToCartEventAddToWishlistEventAdRevenueEventClickAdvEventCompleteRegistrationEventCompleteStreamEventCompleteTrialEventCompleteTutorialEventContactEventContentItemsViewEventCustomId01EventCustomId02EventCustomId03EventCustomId04EventCustomId05EventCustomId06EventCustomId07EventCustomId08EventCustomId09EventCustomId10EventCustomizeProductEventDeepLinkedEventDonateEventFindLocationEventInitiateCheckoutEventInitiatePurchaseEventInitiateStreamEventInviteEventLastAttributedTouchEventLeadEventListViewEventLoginEventOpenedFromPushNotificationEventOrderEventOrderItemAddedEventOrderItemRemoveEventOrderCancelEventOrderReturnRequestEventOrderReturnRequestCancelEventPurchaseEventRateEventReEngageEventReserveEventSalesEventScheduleEventSearchEventShareEventSpendCreditsEventStartRegistrationEventStartTrialEventStartTutorialEventSubmitApplicationEventSubscribeEventTravelBookingEventUnlockAchievementEventUnsubscribeEventUpdateEventViewAdvEventViewCartEventViewContentEventViewItemEventViewItemsEventInitialSubscriptionEventInitialTrialEventInitialOfferEventConvertedTrialEventConvertedOfferEventTrialInRetryEventOfferInRetryEventSubscriptionInRetryEventRenewedSubscriptionEventFailedSubscriptionFromRetryEventFailedOfferFromRetryEventFailedTrialFromRetryEventFailedSubscriptionEventFailedOfferiseEventFailedTrialEventReactivatedSubscriptionEventRenewedSubscriptionFromRetryEventConvertedOfferFromRetryEventConvertedTrialFromRetryEventUnsubscriptionEvent
Each event can be extended with custom event parameters. By calling addPredefinedParameter function you can pass predefined parameters
For example:
let event = ...
event
.addPredefinedParameter(PredefinedString.PURCHASE_CURRENCY, 'USD')
.addPredefinedParameter(PredefinedFloat.PRICE, 2.19)
.addPredefinedParameter(PredefinedLong.QUANTITY, 1)
.addPredefinedParameter(PredefinedObject.CONTENT, { card: 4138, type: 'phone' })
.addPredefinedParameter(PredefinedListObject.CONTENT_LIST, [{content:'songs'}, {content:'videos'}])
.send(); // Send eventIf above event functionality still limits your use case, you can always extend Event class to override fields you are missing
class MyCustomEvent extends Event {
constructor(args) {
super('MyCustom', args)
}
}Adds 3 PredefinedString values: PredefinedString.CONVERSION_ID, PredefinedString.ORDER_ID, PredefinedString.PRODUCT_ID
CONVERSION_ID=ORDER_ID_PRODUCT_ID
val event = AddToCartEvent()
val conversionId = event.customPredefined().conversionId("ORDER_ID", "PRODUCT_ID")
event.send() // Send eventFor more information how to setup, please check official docs
var rewardedAd: RewardedAd? = null
val adRequest = AdRequest.Builder().build()
RewardedAd.load(this,"AD_UNIT_ID", adRequest, object : RewardedAdLoadCallback() {
override fun onAdLoaded(ad: RewardedAd) {
rewardedAd = ad
// Set paid event listener
rewardedAd.onPaidEventListener = OnPaidEventListener { adValue ->
val loadedAdapterResponseInfo = ad.responseInfo.loadedAdapterResponse
// Send AdRevenue info
AffiseAdRevenue(AffiseAdSource.ADMOB)
.setRevenue(adValue.valueMicros / 1000000, adValue.currencyCode)
.setNetwork(loadedAdapterResponseInfo.adSourceName)
.setUnit(ad.adUnitId)
.send()
}
}
})For more information how to setup, please check official docs
override fun onAdRevenuePaid(ad: MaxAd)
{
// Send AdRevenue info
AffiseAdRevenue(AffiseAdSource.APPLOVIN_MAX)
.setRevenue(ad.revenue, "USD")
.setNetwork(ad.networkName)
.setUnit(ad.adUnitId)
.setPlacement(ad.placement)
.send()
}For more information how to setup, please check official docs
val ilrdObserver = object: HeliumIlrdObserver {
override fun onImpression(impData: HeliumImpressionData) {
val json: JSONObject = impData.ilrdInfo
val revenue = json.getDouble("ad_revenue")
val currency = json.getString("currency_type")
// Send AdRevenue info
AffiseAdRevenue(AffiseAdSource.HELIUM_CHARTBOOST)
.setRevenue(revenue, currency)
.setNetwork(json.optString("network_name"))
.setUnit(json.optString("placement_name"))
.setPlacement(json.optString("line_item_name"))
.send()
}
}For more information how to setup, please check official docs
fun onImpressionSuccess(impressionData: ImpressionData) {
// Send AdRevenue info
AffiseAdRevenue(AffiseAdSource.IRONSOURCE)
.setRevenue(impressionData.revenue, "USD")
.setNetwork(impressionData.adNetwork)
.setUnit(impressionData.adUnit)
.setPlacement(impressionData.placement)
.send()
}For more information how to setup, please check official docs
fun onAdRevenuePaid(impressionData: AdMostImpressionData) {
// Send AdRevenue info
AffiseAdRevenue(AffiseAdSource.ADMOST)
.setRevenue(impressionData.Revenue, impressionData.Currency)
.setNetwork(impressionData.Network)
.setUnit(impressionData.AdUnitId)
.setPlacement(impressionData.PlacementId)
.send()
}Caution
π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯
Debug methods WON'T work on Production
π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯π₯
Validate your credentials by receiving ValidationStatus values:
VALID- your credentials are validINVALID_APP_ID- your app id is not validINVALID_SECRET_KEY- your SDK secretKey is not validPACKAGE_NAME_NOT_FOUND- your application package name not foundNOT_WORKING_ON_PRODUCTION- you using debug method on productionNETWORK_ERROR- network or server not available (for exampleAiroplane modeis active)
Affise
.settings(
affiseAppId = "Your appId",
secretKey = "Your SDK secretKey"
)
.setProduction(false) //To enable debug methods set Production to false
.start(this) // Start Affise SDK
Affise.Debug.validate { status ->
// Handle validation status
}Get Affise library version
Affise.Debug.version()