Basic methods
Please take a look at our Expert tips before integrating the events.
Real Payment
To track payments in a real currency, dispatch this event right after the system validates that the payment went through successfully. The event is fundamental and mandatory for all the app metrics related to monetization.
DTDAnalytics.realCurrencyPayment(orderId: "Order ID",
price: 12.5,
productId: "Product ID",
currencyCode: "USD")
orderId
string
from 1 to 65 symbols
A unique transaction ID. Use transactionIdentifier
property value in SKPaymentTransaction
object in a complete transaction receipt.
price
double
from Double.min to Double.max
The item price in the transaction currency.
productId
string
from 1 to 255 symbols
Item name. We recommend using a bundle or names in the same language.
[DTDAnalytics realCurrencyPaymentWithOrderId:@"Order ID"
price:12.5
productId:@"Product ID"
currencyCode:@"USD"];
orderId
NSString
from 1 to 65 symbols
A unique transaction ID. Use transactionIdentifier
property value in SKPaymentTransaction
object in a complete transaction receipt.
price
double
from Double.min to Double.max
The item price in the transaction currency.
productId
NSString
from 1 to 255 symbols
Item name. We recommend using a bundle or names in the same language.
DTDAnalytics.realCurrencyPayment(
orderId = "Order ID",
price = 12.5,
productId = "Product ID",
currencyCode = "USD"
)
orderId
string
from 1 to 65 symbols
A unique transaction ID.
price
double
from Double.min to Double.max
The item price in the transaction currency.
productId
string
from 1 to 255 symbols
Item name. We recommend using a bundle or names in the same language.
How to find the transaction ID in GooglePlay transaction?
Find the INAPP_PURCHASE_DATA object In the JSON fields that are returned in the response data for a purchase order. A unique transaction identifier is the value of orderId property in INAPP_PURCHASE_DATA object. If the order is a test purchase made via the In-app Billing Sandbox, orderId property will be empty.
DTDAnalytics.INSTANCE.realCurrencyPayment(
"Order ID",
12.5,
"Product ID",
"USD"
);
orderId
string
from 1 to 65 symbols
A unique transaction ID.
price
double
from Double.min to Double.max
The item price in the transaction currency.
productId
string
from 1 to 255 symbols
Item name. We recommend using a bundle or names in the same language.
How to find the transaction ID in GooglePlay transaction?
Find the INAPP_PURCHASE_DATA object In the JSON fields that are returned in the response data for a purchase order. A unique transaction identifier is the value of orderId property in INAPP_PURCHASE_DATA object. If the order is a test purchase made via the In-app Billing Sandbox, orderId property will be empty.
DTDAnalytics.RealCurrencyPayment(
orderId: "Order ID",
price: 12.5,
productId: "Product ID",
currencyCode: "USD");
orderId
string
from 1 to 65 symbols
A unique transaction ID.
price
double
from double.MinValue to double.MaxValue
The item price in the transaction currency.
productId
string
from 1 to 255 symbols
Item name. We recommend using a bundle or names in the same language.
DTDAnalytics.RealCurrencyPayment(
orderId: "Order ID",
price: 12.5,
productId: "Product ID",
currencyCode: "USD");
orderId
string
from 1 to 65 symbols
A unique transaction ID.
price
double
from Double.MinValue to Double.MaxValue
The item price in the transaction currency.
productId
string
from 1 to 255 symbols
Item name. We recommend using a bundle or names in the same language.
window.devtodev.realCurrencyPayment(
orderId,
price,
productId,
currencyCode)
orderId
string
from 1 to 65 symbols
A unique transaction ID.
price
double
from Number.MIN_VALUE to Number.MAX_VALUE
The item price in the transaction currency.
productId
string
from 1 to 255 symbols
Item name. We recommend using a bundle or names in the same language.
orderId
FString
from 1 to 65 symbols
A unique transaction ID.
price
float
from float.MinValue to float.MaxValue
The item price in the transaction currency.
productId
FString
from 1 to 255 symbols
Item name. We recommend using a bundle or names in the same language.
1UDTDAnalyticsBPLibrary::RealCurrencyPayment("OrderId", 12.5, "ProductId", "USD");
DTDAnalytics.RealCurrencyPayment("orderId", 9.99, "productId", "USD")
orderId
String
from 1 to 65 symbols
A unique transaction ID.
price
Float
from Double.min to Double.max
The item price in the transaction currency.
productId
String
from 1 to 255 symbols
Item name. We recommend using a bundle or names in the same language.
By default (easy to change in the app’s settings) devtodev server invalidates transactions with previously-used identifiers. Besides, the server performs identifier checks by its outer appearance in order to avoid obvious fraud.
If you want to exclude fraud payments from your reports altogether, before creating ‘Real Currency Payment’ event, use devtodev anti-cheat feature.
Custom Events
If you want to track non-basic events, you can create custom events of your own. How you are going to apply them, depends solely on you.
Attention! We strongly recommend that you do not use custom event properties to transfer and store data that fits the definition of personal data!
DTDAnalytics.customEvent(eventName: "Event name")
If you want to pass custom parameters, use DTDCustomEventParameters
class instance.
let parameters = DTDCustomEventParameters()
parameters.add(key: "key for string value", value: "string value")
parameters.add(key: "key for int value", value: 10)
parameters.add(key: "key for bool value", value: true)
parameters.add(key: "key for double value", value: 12.5)
DTDAnalytics.customEvent(eventName: "Event name", parameters: parameters)
eventName
string
from 1 to 72 symbols
Custom event name.
parameters
DTDCustomEventParameters
key - from 1 to 32 symbols
value - see below
Custom event parameters.
The following data types can be passed using the DTDCustomEventParameters
object:
int
from Int64.min to Int64.max
string
from 1 to 255 symbols
bool
true/false
double
from Double.min to Double.max
[DTDAnalytics customEvent:@"Event name"];
If you want to pass custom parameters, use DTDCustomEventParameters
class instance.
DTDCustomEventParameters *parameters = [[DTDCustomEventParameters alloc] init];
[parameters addString:@"key for string value" value:@"string value"];
[parameters addInt:@"key for int value" value:10];
[parameters addBool:@"key for bool value" value:true];
[parameters addDouble:@"key for double value" value:12.5];
[DTDAnalytics customEvent:@"Event name" withParameters:parameters];
eventName
NSString
from 1 to 72 symbols
Custom event name.
parameters
DTDCustomEventParameters
key - from 1 to 32 symbols
value - see below
Custom event parameters.
The following data types can be passed using the DTDCustomEventParameters
object:
int
from Int64.min to Int64.max
string
from 1 to 255 symbols
bool
true/false
double
from Double.min to Double.max
DTDAnalytics.customEvent(eventName = "Event name")
If you want to pass custom parameters, use DTDCustomEventParameters
class instance.
let parameters = DTDCustomEventParameters()
parameters.add(key = "key for string value", value = "string value")
parameters.add(key = "key for int value", value = 10)
parameters.add(key = "key for bool value", value = true)
parameters.add(key = "key for double value", value = 12.5)
DTDAnalytics.customEvent(
eventName = "Event name",
customEventParameters = parameters
)
eventName
string
from 1 to 72 symbols
Custom event name.
parameters
DTDCustomEventParameters
key - from 1 to 32 symbols
value - see below
Custom event parameters.
The following data types can be passed using the DTDCustomEventParameters
object:
Long
from Long.min to Long.max
String
from 1 to 255 symbols
Boolean
true/false
Double
from Double.min to Double.max
DTDAnalytics.INSTANCE.customEvent("Event name");
If you want to pass custom parameters, use DTDCustomEventParameters
class instance.
DTDCustomEventParameters parameters = new DTDCustomEventParameters();
parameters.add("key for string value", "string value");
parameters.add("key for int value", 10);
parameters.add("key for bool value", true);
parameters.add("key for double value", 12.5);
DTDAnalytics.INSTANCE.customEvent("Event name", parameters);
eventName
string
from 1 to 72 symbols
Custom event name.
parameters
DTDCustomEventParameters
key - from 1 to 32 symbols
value - see below
Custom event parameters.
The following data types can be passed using the DTDCustomEventParameters
object:
Long
from Long.min to Long.max
String
from 1 to 255 symbols
Boolean
true/false
Double
from Double.min to Double.max
DTDAnalytics.CustomEvent(eventName: "Event name");
If you want to pass custom parameters, use DTDCustomEventParameters
class instance.
var parameters = new DTDCustomEventParameters();
parameters.Add(key: "key for string value", value: "string value");
parameters.Add(key: "key for int value", value: 10);
parameters.Add(key: "key for bool value", value: true);
parameters.Add(key: "key for double value", value: 12.5);
DTDAnalytics.CustomEvent(eventName: "Event name", parameters: parameters);
eventName
string
from 1 to 72 symbols
Custom event name.
parameters
DTDCustomEventParameters
key - from 1 to 32 symbols
value - see below
Custom event parameters.
The following data types can be passed using the DTDCustomEventParameters
object:
long
from long.MinValue to long.MaxValue
string
from 1 to 255 symbols
bool
true/false
double
from double.MinValue to double.MaxValue
DTDAnalytics.CustomEvent(eventName: "Event name");
If you want to pass custom parameters, use DTDCustomEventParameters
class instance.
var parameters = new DTDCustomEventParameters();
parameters.Add(key: "key for string value", value: "string value");
parameters.Add(key: "key for int value", value: 10);
parameters.Add(key: "key for bool value", value: true);
parameters.Add(key: "key for double value", value: 12.5);
DTDAnalytics.CustomEvent(eventName: "Event name", parameters: parameters);
eventName
string
from 1 to 72 symbols
Custom event name.
parameters
DTDCustomEventParameters
key - from 1 to 32 symbols
value - see below
Custom event parameters.
The following data types can be passed using the DTDCustomEventParameters
object:
long
from Int64.MinValue to Int64.MaxValue
string
from 1 to 255 symbols
bool
true/false
double
from Double.MinValue to Double.MaxValue
window.devtodev.customEvent(eventName, parameters)
If you want to pass custom parameters, use an object with parameters.
window.devtodev.customEvent("Event name", {
"key for string value" : "string value",
"key for int value": 10,
"key for bool value": true,
"key for double value": 12.5
})
eventName
string
from 1 to 72 symbols
Custom event name.
parameters
object
key - from 1 to 32 symbols
value - see below
Custom event parameters.
The following data types can be passed using parameters object:
long
from Number.MIN_SAFE_INTEGER to Number.MAX_SAFE_INTEGER
string
from 1 to 255 symbols
bool
true/false
double
from Number.MIN_VALUE to Number.MAX_VALUE
eventName
FString
from 1 to 72 symbols
Custom event name.
UDTDAnalyticsBPLibrary::CustomEvent("EventName");
If you want to pass custom parameters, use:
eventName
FString
from 1 to 72 symbols
Custom event name.
parameters
FDTDCustomEventParams
StringParameters (TMap<FString, FString>)
IntParameters (TMap<FString, int64>)
FloatParameters (TMap<FString, float>)
BoolParameters (TMap<FString, bool>)
key - from 1 to 32 symbols
value - see below
Custom event parameters.
Warning: avoid duplicate keys in all dictionaries. Because dictionaries are combined into a generic dictionary [string: any] in native code.
The following data types can be passed using the DTDCustomEventParameters object:
int64
from int64.MinValue to int64.MaxValue
FString
from 1 to 255 symbols
bool
true/false
float
from float.MinValue to float.MaxValue
FDTDCustomEventParams params;
params.BoolParameters.Add("BoolKey", true);
params.FloatParameters.Add("FloatKey", 3.3);
params.IntParameters.Add("IntKey");
params.StringParameters.Add("StringKey", "StringValue");
UDTDAnalyticsBPLibrary::CustomEventWithParams("EventName", params);
DTDAnalytics.CustomEvent("CustomEvent")
If you want to pass custom parameters, use GDDTDCustomEventParameters
class instance.
var parameters = GDDTDCustomEventParams.new()
parameters.AddStringValue("str_key", "str_value")
parameters.AddBoolValue("bool_key", true)
parameters.AddIntegerValue("int_key", 100)
parameters.AddFloatValue("float_key", 0.0015)
DTDAnalytics.CustomEventWithParams("CustomEventWithParams", parameters)
eventName
string
from 1 to 72 symbols
Custom event name.
parameters
GDDTDCustomEventParams
key - from 1 to 32 symbols
value - see below
Custom event parameters.
The following data types can be passed using the GDDTDCustomEventParameters
object:
int
from Int64.min to Int64.max
String
from 1 to 255 symbols
bool
true/false
Float
from Float.min to Float.max
devtodev supports no more than 300 custom event names in a single project. Events that exceed the limit of custom event names will be discarded. Try to integrate the tracked actions by type to the event name level, and move the characteristic tags in the parameters.
For example, if you need to track purchasing “Paper” and “Pen” items, then you don’t need to create two events with the names “Paper Purchase” and “Pen Purchase”. Create a “Purchase” event and add an “Item” parameter to it with the appropriate “Paper” or “Pen” value. This way, you can use just one event to track many items.
For a string parameter, you can use no more than 50,000 unique values for the entire history of events. If the number of unique values exceeds the limit, the parameter gets locked by the system and gets discarded from the received data. Therefore, we don’t recommend using highly variable parameters like user IDs or time as string values (moreover, they are automatically added to the event).
We strongly recommend that you do not change the data type passed in the same parameter. If you change the data type in a parameter, it will be duplicated with the same name, which may cause issues while processing reports.
Subscriptions
The described method is available beginning with version 2.1.0!
Tracking of subscriptions is now available for Apple App Store and Google Play only.
Please note that in order to track subscriptions, you need to do the following:
Call the
subscriptionPayment
method (described below)
To track your income from subscriptions, you need to call the following method at the moment of the subscription purchase even if the user signed up for a trial subscription: func subscriptionPayment(transaction: SKPaymentTransaction, product: SKProduct).
For example:
extension Purchases: SKPaymentTransactionObserver {
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction in transactions {
switch transaction.transactionState {
case .purchased:
// Your code ...
if let product = products?[transaction.payment.productIdentifier] {
DTDAnalytics.subscriptionPayment(transaction: transaction, product: product)
}
case .restored:
// Your code ...
case .failed:
// Your code ...
default:
// Your code ...
}
}
}
}
Further user actions - renewal, unsubscription, etc. are tracked by using the data received from AppStore in the server-server format. You will need the corresponding setting for it.
Also, if you want to track changes in the status of the subscriptions purchased before devtodev SDK 2.0 integration, you need to transfer your history of previously purchased subscriptions to devtodev.
The SDK monitors the need for historical data to avoid sending out excessive queries to App Store. Use the DTDAnalytics.isRestoreTransactionHistoryRequired
method to check whether or not there is a need in sending out the information about the previously purchased subscriptions to devtodev. The method returns BOOL value.
An example of a purchase history query with verification of the need for it:
DTDAnalytics.isRestoreTransactionHistoryRequired { isNeedRestore in
if isNeedRestore {
DispatchQueue.main.async {
SKPaymentQueue.default().restoreCompletedTransactions()
}
}
}
Use the DTDAnalytics.subscriptionHistory
method to transfer the list of previously purchased subscriptions received from App Store.
If your project accounts users by user ID (not by device ID) and the device is used by more than one user, you need to filter the transaction history so that it will contain only those transactions that belong to the active user. Otherwise, subscriptions of all device users will be attributed to the user who was the first to launch the app after the integration of subscription tracking.
extension Purchases: SKPaymentTransactionObserver {
func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
// Your code ...
let restoredTransactions = queue.transactions.filter { $0.transactionState == .restored }
DTDAnalytics.subscriptionHistory(transactions: restoredTransactions)
}
}
To recover the purchase history, the user should be logged in with his Apple ID. Be mindful of this before starting the recovering process.
Please note that in order to track subscriptions, you need to do the following:
Call the
subscriptionPayment
method (described below)
To track your income from subscriptions, you need to call the following method at the moment of the subscription purchase even if the user signed up for a trial subscription: func subscriptionPayment(transaction: Transaction, product: Product).
For example:
func purchase(_ product: Product) async throws {
let result = try await product.purchase()
switch result {
case let .success(.verified(transaction)):
// Successful purchase
await transaction.finish()
DTDAnalytics.subscriptionPayment(transaction: transaction, product: product)
case let .success(.unverified(_, error)):
// Successful purchase but transaction/receipt can't be verified
// Could be a jailbroken phone
print(error)
case .pending:
// Transaction waiting on SCA (Strong Customer Authentication) or
// approval from Ask to Buy
break
case .userCancelled:
// Do nothing
break
@unknown default:
break
}
}
Fork with Transaction.updates:
private func listenForTransactions() -> Task<Void, Error> {
return Task.detached {
// Iterate through any transactions that don't come from a direct call to `purchase()`.
for await verificationResult in Transaction.updates {
guard let case .verified(let transaction) = verificationResult else { return }
if let revocationDate = transaction.revocationDate {
// Remove access to the product identified by transaction.productID.
// Transaction.revocationReason provides details about
// the revoked transaction.
} else if let expirationDate = transaction.expirationDate,
expirationDate < Date() {
// Do nothing, this subscription is expired.
return
} else if transaction.isUpgraded {
// Do nothing, there is an active transaction
// for a higher level of service.
return
} else {
// Provide access to the product identified by
// transaction.productID.
if let product = self.products.first(where: { $0.id == transaction.productID }) {
DTDAnalytics.subscriptionPayment(transaction: transaction, product: product)
}
}
}
}
}
Further user actions - renewal, unsubscription, etc. are tracked by using the data received from AppStore in the server-server format. You will need the corresponding setting for it.
Also, if you want to track changes in the status of the subscriptions purchased before devtodev SDK 2.0 integration, you need to transfer your history of previously purchased subscriptions to devtodev.
The SDK monitors the need for historical data to avoid sending out excessive queries to App Store. Use the DTDAnalytics.isRestoreTransactionHistoryRequired
method to check whether or not there is a need in sending out the information about the previously purchased subscriptions to devtodev. The method returns BOOL value.
An example of a purchase history query with verification of the need for it:
DTDAnalytics.isRestoreTransactionHistoryRequired { [weak self] flag in
if flag {
Task {
await self?.restoreTransactions()
}
}
}
Use the DTDAnalytics.subscriptionHistory
method to transfer the list of previously purchased subscriptions received from App Store.
If your project accounts users by user ID (not by device ID) and the device is used by more than one user, you need to filter the transaction history so that it will contain only those transactions that belong to the active user. Otherwise, subscriptions of all device users will be attributed to the user who was the first to launch the app after the integration of subscription tracking.
extension Purchases: SKPaymentTransactionObserver {
func restoreTransactions() async {
var transactions: [Transaction] = []
for await transaction in Transaction.all {
if case let .verified(verifiedTransaction) = transaction {
transactions.append(verifiedTransaction)
}
}
DTDAnalytics.subscriptionHistory(transactions: transactions)
}
To recover the purchase history, the user should be logged in with his Apple ID. Be mindful of this before starting the recovering process.
Please note that in order to track subscriptions, you need to do the following:
Call the
subscriptionPayment
method (described below)
To track your income from subscriptions, you need to call the following method at the moment of the subscription purchase even if the user signed up for a trial subscription:
(void)subscriptionPaymentWithTransaction:(SKPaymentTransaction * _Nonnull)transaction product:(SKProduct * _Nonnull)product;
For example:
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions{
for(SKPaymentTransaction *transaction in transactions) {
switch(transaction.transactionState){
case SKPaymentTransactionStatePurchasing: {
// Your code ...
break;
}
case SKPaymentTransactionStatePurchased: {
// Your code ...
SKProduct *product = [_products objectForKey:transaction.payment.productIdentifier];
if (product != nil) {
[DTDAnalytics subscriptionPaymentWithTransaction:transaction product:product];
}
break;
}
case SKPaymentTransactionStateRestored: {
// Your code ...
break;
}
case SKPaymentTransactionStateFailed: {
// Your code ...
break;
}
case SKPaymentTransactionStateDeferred: {
// Your code ...
break;
}
}
}
}
Further user actions - renewal, unsubscription, etc. are tracked by using the data received from AppStore in the server-server format. You will need the corresponding setting for it.
Also, if you want to track changes in the status of the subscriptions purchased before devtodev SDK 2.0 integration, you need to transfer your history of previously purchased subscriptions to devtodev.
The SDK monitors the need for historical data to avoid sending out excessive queries to App Store. Use the (void)isRestoreTransactionHistoryRequiredWithCompletionHandler:( void (^ _Nonnull)(BOOL))completionHandler;
method to check whether or not there is a need in sending out the information about the previously purchased subscriptions to devtodev. The method returns BOOL value.
An example of a purchase history query with verification of the need for it:
[DTDAnalytics isRestoreTransactionHistoryRequiredWithCompletionHandler:^(BOOL isNeedRestore){
if (isNeedRestore == true) {
dispatch_async(dispatch_get_main_queue(), ^{
[SKPaymentQueue.defaultQueue restoreCompletedTransactions];
});
}
}];
Use the (void)subscriptionHistoryWithTransactions:(NSArray<SKPaymentTransaction *> * _Nonnull)transactions;
method to transfer the list of previously purchased subscriptions received from App Store.
If your project accounts users by user ID (not by device ID) and the device is used by more than one user, you need to filter the transaction history so that it will contain only those transactions that belong to the active user. Otherwise, subscriptions of all device users will be attributed to the user who was the first to launch the app after the integration of subscription tracking.
-(void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue {
NSMutableArray *restoredTransactions = [NSMutableArray new];
for (SKPaymentTransaction *transaction in queue.transactions) {
if (transaction.transactionState == SKPaymentTransactionStateRestored) {
[restoredTransactions addObject:transaction];
}
}
[DTDAnalytics subscriptionHistoryWithTransactions:restoredTransactions];
}
To recover the purchase history, the user should be logged in with his Apple ID. Be mindful of this before starting the recovering process.
Please note that in order to track subscriptions, you need to do the following:
Call the
subscriptionPayment
method (described below)
Before sending a request for subscription from your app, during the creation of BillingFlowParams
, to the setObfuscatedAccountId
function of the BillingFlowParams.newBuilder()
object insert obfuscatedAccountId
obtained from DTDAnalytics.getObfuscatedAccountId
.
Attention! The obfuscated identifier is returned asynchronously, outside of the calling thread!
Example:
DTDAnalytics.getObfuscatedAccountId { obfuscatedAccountId ->
val flowParams: BillingFlowParams = BillingFlowParams.newBuilder()
.setObfuscatedAccountId(obfuscatedAccountId)
.build()
val result = billingClient.launchBillingFlow(activity, flowParams)
}
To track your subscriptions, add this event immediately after the platform confirms that the subscription was approved by the user.
DTDAnalytics.subscriptionPayment(orderId: String,
price: Double,
productId: String,
currencyCode: String);
Parameter
Type
Restrictions
Description
orderId
string
from 1 to 65 symbols
A unique transaction identifier.
price
double
from Double.min to Double.max
The item price in the transaction currency.
productId
string
from 1 to 255 symbols
Item name. We recommend using a bundle or names in the same language.
How to find the transaction ID in GooglePlay transaction?
Find the INAPP_PURCHASE_DATA object In the JSON fields that are returned in the response data for a purchase order. A unique transaction identifier is the value of orderId property in INAPP_PURCHASE_DATA object. If the order is a test purchase made via the In-app Billing Sandbox, orderId property will be empty.
Further user actions - renewal, unsubscription, etc. are tracked by using the data received from Google Play in the server-server format. You will need the corresponding setting for it.
The subscriptionHistory
method is used for matching users with subscribers who purchased their subscriptions before the SDK 2.0 integration. Otherwise, it will be impossible to establish the affiliation when it gets renewed or cancelled.
To get a list of active subscriptions call billingClient.queryPurchasesAsync
. After successfully receiving a response from Google Play Services, pass it to DTDAnalytics.subscriptionHistory(purchaseList: List<String>).
purchaseList: List<String> purchaseList
- a string containing list of json objects is passed to the DTDAnalytics.subscriptionHistory
method. For the event to run, the json object must contain the following keys:
orderID
- a unique transaction identifierproductID
- a unique product identifier
The SDK monitors the need for historical data to avoid sending out excessive queries. Use the DTDAnalytics.isRestoreTransactionHistoryRequired
method to check whether or not there is a need in sending out the information about the previously purchased subscriptions to devtodev. The method returns a Boolean value.
Attention! DTDAnalytics.isRestoreTransactionHistoryRequired
is returned asynchronously, outside of the calling thread!
Example:
DTDAnalytics.isRestoreTransactionHistoryRequired { isNeedRestore ->
if(isNeedRestore) {
billingClient.queryPurchasesAsync(BillingClient.SkuType.SUBS) { billingResult, purchaseList ->
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
val purchases = mutableListOf<String>()
purchaseList.forEach { purchase -> purchases.add(purchase.originalJson) }
DTDAnalytics.subscriptionHistory(purchases)
}
}
}
}
If your project accounts users by user ID (not by device ID) and the device is used by more than one user, you need to filter the transaction history so that it will contain only those transactions that belong to the active user. Otherwise, subscriptions of all device users will be attributed to the user who was the first to launch the app after the integration of subscription tracking.
Please note that in order to track subscriptions, you need to do the following:
Call the
subscriptionPayment
method (described below)
Before sending a request for subscription from your app, during the creation of BillingFlowParams
, to the setObfuscatedAccountId
function of the BillingFlowParams.newBuilder()
object insert obfuscatedAccountId
obtained from DTDAnalytics.INSTANCE.getObfuscatedAccountId.
Attention! The obfuscated identifier is returned asynchronously, outside of the calling thread!
Example:
DTDAnalytics.INSTANCE.getObfuscatedAccountId(obfuscatedAccountId -> {
BillingFlowParams flowParams = BillingFlowParams.newBuilder()
.setObfuscatedAccountId(obfuscatedAccountId)
.build();
billingClient.launchBillingFlow(activity, flowParams);
return null;
}
);
To track your subscriptions, add this event immediately after the platform confirms that the subscription was approved by the user.
DTDAnalytics.INSTANCE.subscriptionPayment(orderId: String, price: Double, productId: String, currencyCode: String);
Parameter
Type
Restrictions
Description
orderId
string
from 1 to 65 symbols
A unique transaction identifier.
price
double
from Double.min to Double.max
The item price in the transaction currency.
productId
string
from 1 to 255 symbols
Item name. We recommend using a bundle or names in the same language.
How to find the transaction ID in GooglePlay transaction?
Find the INAPP_PURCHASE_DATA object In the JSON fields that are returned in the response data for a purchase order. A unique transaction identifier is the value of orderId property in INAPP_PURCHASE_DATA object. If the order is a test purchase made via the In-app Billing Sandbox, orderId property will be empty.
Further user actions - renewal, unsubscription, etc. are tracked by using the data received from Google Play in the server-server format. You will need the corresponding setting for it.
The subscriptionHistory
method is used for matching users with subscribers who purchased their subscriptions before the SDK 2.0 integration. Otherwise, it will be impossible to establish the affiliation when it gets renewed or cancelled.
To get a list of active subscriptions call billingClient.queryPurchasesAsync
. After successfully receiving a response from Google Play Services, pass it to DTDAnalytics.subscriptionHistory(purchaseList: List<String>).
purchaseList: List<String> purchaseList
- a string containing list of json objects is passed to the DTDAnalytics.INSTANCE.subscriptionHistory
method. For the event to run, the json object must contain the following keys:
orderID
- a unique transaction identifierproductID
- a unique product identifier
The SDK monitors the need for historical data to avoid sending out excessive queries. Use the DTDAnalytics.INSTANCE.isRestoreTransactionHistoryRequired
method to check whether or not there is a need in sending out the information about the previously purchased subscriptions to devtodev. The method returns a Boolean value.
Attention! DTDAnalytics.INSTANCE.isRestoreTransactionHistoryRequired
is returned asynchronously, outside of the calling thread!
Example:
DTDAnalytics.INSTANCE.isRestoreTransactionHistoryRequired(isNeedRestore -> {
if (isNeedRestore) {
billingClient.queryPurchasesAsync(BillingClient.ProductType.SUBS, (billingResult, purchaseList) -> {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
ArrayList<String> purchases = new ArrayList<>();
purchaseList.forEach(purchase ->
purchases.add(purchase.getOriginalJson())
);
DTDAnalytics.INSTANCE.subscriptionHistory(purchases);
}
});
}
return null;
});
If your project accounts users by user ID (not by device ID) and the device is used by more than one user, you need to filter the transaction history so that it will contain only those transactions that belong to the active user. Otherwise, subscriptions of all device users will be attributed to the user who was the first to launch the app after the integration of subscription tracking.
In order to work with Unity subscriptions, you need to integrate the subscription module to your project. You can do it by manually importing the unitypackage.
Integration by importing the unitypackage
Download the latest version of devtodev package from the repository: https://github.com/devtodev-analytics/Unity-sdk-3.0/releases/latest
Import DTDAnalytics.unitypackage to your project
Import DTDSubscriptions.unitypackage to your project.
For the DTDSubscriptions
module to function you need the DTDAnalytics
and Unity IAP modules.
You also need to create an AppleTangle
file (only for iOS). Open the Unity editor menu and choose Window → Unity IAP → Receipt Validation Obfuscator (pic. 1).
In case you don’t use the IAP receipt validation, clear the input field under “2. Paste the key here:” and click Obfuscate Google Play Licence Key (pic. 2).
Initialize the
DTDAnalytics
module (see our instruction manual).Add
DTDSubscriptions.Initialize(IStoreController controller)
to the OnInitialized method.
/// <summary>
/// Your IStoreListener implementation of OnInitialized.
/// </summary>
public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
{
DTDSubscriptions.Initialize(controller);
}
Restore purchase history in order for the module to function correctly.
If you use Google Play, after successful IAP initialization call the
DTDSubscriptions.History()
method.
To avoid excessive restoring of subscription history, use the DTDSubscriptions.IsRestoreTransactionHistoryRequired(Action<bool> resultCallback)
method. If the resultCallback returns true, call the DTDSubscriptions.History()
method.
Example:
public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
{
#if UNITY_ANDROID
DTDSubscriptions.Initialize(controller);
DTDSubscriptions.IsRestoreTransactionHistoryRequired((b) =>
{
if(b) DTDSubscriptions.History();
});
#endif
}
If you use Apple App Store, first set the
DTDSubscriptions.IsRestoring
property to true (this will filter out unwanted transactions). After restoring IAP transactions, call theDTDSubscriptions.History()
method. After that, set theDTDSubscriptions.IsRestoring propert
y to false.
Example:
public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
{
DTDSubscriptions.Initialize(controller);
if UNITY_STANDALONE_OSX || UNITY_IOS
DTDSubscriptions.IsRestoring = true;
extensions.GetExtension<IAppleExtensions>().RestoreTransactions(result =>
{
if (result)
{
DTDSubscriptions.IsRestoreTransactionHistoryRequired((b) =>
{
if (b) DTDSubscriptions.History();
});
}
DTDSubscriptions.IsRestoring = false;
});
#endif
}
Add a
DTDSubscriptions.Payment(Product product)
call to theProcessPurchase
method.
public PurchaseProcessingResult ProcessPurchase (PurchaseEventArgs e)
{
var product = e.purchasedProduct;
DTDSubscriptions.Payment(product);
return PurchaseProcessingResult.Complete;
}
Below you can see an example of the entire script:
using DevToDev.Subscriptions;
using UnityEngine;
using UnityEngine.Purchasing;
public class MyIAPManager : IStoreListener
{
public IStoreController StoreController { get; private set; }
public void InitializeIAPManager()
{
var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
builder.AddProduct("example", ProductType.Subscription);
UnityPurchasing.Initialize(this, builder);
}
/// <summary>
/// Called when Unity IAP is ready to make purchases.
/// </summary>
public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
{
StoreController = controller;
DTDSubscriptions.Initialize(controller);
#if UNITY_ANDROID
DTDSubscriptions.IsRestoreTransactionHistoryRequired((b) =>
{
if (b) DTDSubscriptions.History();
});
#elif UNITY_STANDALONE_OSX || UNITY_IOS
DTDSubscriptions.IsRestoring = true;
extensions.GetExtension<IAppleExtensions>().RestoreTransactions(result =>
{
if (result)
{
DTDSubscriptions.IsRestoreTransactionHistoryRequired((b) =>
{
if (b) DTDSubscriptions.History();
});
}
DTDSubscriptions.IsRestoring = false;
});
#endif
}
/// <summary>
/// Called when Unity IAP encounters an unrecoverable initialization error.
///
/// Note that this will not be called if Internet is unavailable; Unity IAP
/// will attempt initialization until it becomes available.
/// </summary>
public void OnInitializeFailed(InitializationFailureReason error)
{
Debug.Log($"IAP initialization error {error.ToString()}");
}
/// <summary>
/// Called when a purchase completes.
///
/// May be called at any time after OnInitialized().
/// </summary>
public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs e)
{
var product = e.purchasedProduct;
DTDSubscriptions.Payment(product);
return PurchaseProcessingResult.Complete;
}
/// <summary>
/// Called when a purchase fails.
/// </summary>
public void OnPurchaseFailed(Product i, PurchaseFailureReason p)
{
Debug.Log(p.ToString());
}
}
Onboarding (tutorial)
The event allows you to track tutorial completion and identify the stages where you lose new users.
We recommend tracking the starting point (value -1) before beginning the first tutorial stage, then passing the counting number of every completed stage after its completion (integers larger than 0), and at the end, marking the moment of the last tutorial stage completion (value -2).
If your app has an option of skipping the tutorial and the user has used it, then it’s necessary to send a refusal value (value 0) only.
DTDAnalytics.tutorial(step: 1)
The method takes on the step value with an integer type.
0
The user skipped the tutorial
-1
The value defines the beginning of the tutorial
1..int
Counting number of completed tutorial stage
-2
The value defines the completion of the tutorial
[DTDAnalytics tutorialStep:1];
The method takes on the step value with an integer type.
0
The user skipped the tutorial
-1
The value defines the beginning of the tutorial
1..int
Counting number of completed tutorial stage
-2
The value defines the completion of the tutorial
DTDAnalytics.tutorial(step = 1)
The method takes on the step value with an integer type.
0
The user skipped the tutorial
-1
The value defines the beginning of the tutorial
1..int
Counting number of completed tutorial stage
-2
The value defines the completion of the tutorial
DTDAnalytics.INSTANCE.tutorial(1);
The method takes on the step value with an integer type.
0
The user skipped the tutorial
-1
The value defines the beginning of the tutorial
1..int
Counting number of completed tutorial stage
-2
The value defines the completion of the tutorial
DTDAnalytics.Tutorial(1);
The method takes on the step value with an integer type.
0
The user skipped the tutorial
-1
The value defines the beginning of the tutorial
1..int
Counting number of completed tutorial stage
-2
The value defines the completion of the tutorial
DTDAnalytics.Tutorial(1);
The method takes on the step value with an int base type.
0
The user skipped the tutorial
-1
The value defines the beginning of the tutorial
1..int
Counting number of completed tutorial stage
-2
The value defines the completion of the tutorial
window.devtodev.tutorial(1)
The method takes on the step value with an integer type.
0
The user skipped the tutorial
-1
The value defines the beginning of the tutorial
1..int
Counting number of completed tutorial stage
-2
The value defines the completion of the tutorial
step
int32
From 1 to int32.MaxValue - 1
Tutorial step
UDTDAnalyticsBPLibrary::Tutorial(1);
The method takes on the step value with an int32 base type.
0
The user skipped the tutorial
-1
The value defines the beginning of the tutorial
1..int32
Counting number of completed tutorial stage
-2
The value defines the completion of the tutorial
DTDAnalytics.Tutorial(1)
The method takes on the step value with an integer type.
0
The user skipped the tutorial
-1
The value defines the beginning of the tutorial
1..int
Counting number of completed tutorial stage
-2
The value defines the completion of the tutorial
Level up
This event is for games only. It is worthwhile to integrate this event into a game type project, as specified in the application settings. In projects with the “app” type, game events will not be tracked and displayed in the interface, even if they are integrated. You can verify and change the project type in Settings → General settings.
The event allows you to analyze the distribution of players over different game levels, monitor the in-game currency balance by levels. You can find more information about the right moment to use LevelUp
event here.
The event should be dispatched right after the level-up. The number of the level reached is passed to the level
parameter.
DTDAnalytics.levelUp(level: 2)
To monitor the average account balance of in-game currency by the end of each level, dispatch in-game currencies (resources) names and their amounts to the method signature:
let balance: [String: Int] = ["Currency name 1": 100, "Currency name 2": 10]
DTDAnalytics.levelUp(level: 2, balances: balance)
Attention! The number of tracked in-game currencies or resources (their unique names) should not exceed 30 at all times.
level
int
From 1 to Int32.max - 1
Level reached
balances
[String:Int]
String - from 1 to 24 symbols
Int - from Int64.min to int64.max
Resources’ names and number at the time of level up
The event should be dispatched right after the level-up. The number of the level reached is passed to the level
parameter.
[DTDAnalytics levelUp:2];
To monitor the average account balance of in-game currency by the end of each level, dispatch in-game currencies (resources) names and their amounts to the method signature:
NSDictionary *balance = @{@"Currency name 1": @100, @"Currency name 2": @10};
[DTDAnalytics levelUp:2 withBalances:balance];
Attention! The number of tracked in-game currencies or resources (their unique names) should not exceed 30 at all times.
level
NSInteger
From 1 to Int32.max - 1
Level reached
balances
NSDictionary<NSString *,NSNumber *>
String - from 1 to 24 symbols
Int - from Int64.min to int64.max
Resources’ names and number at the time of level up
The event should be dispatched right after the level-up. The number of the level reached is passed to the level
parameter.
DTDAnalytics.levelUp(level = 2)
To monitor the average account balance of in-game currency by the end of each level, dispatch in-game currencies (resources) names and their amounts to the method signature:
val resources = mapOf("Currency name 1" to 100L, "Currency name 2" to 10L)
DTDAnalytics.levelUp(
level = 2,
resource = resources
)
Attention! The number of tracked in-game currencies or resources (their unique names) should not exceed 30 at all times.
level
int
From 1 to Int.max - 1
Level reached
balances
Map<String,Long>
String - from 1 to 24 symbols
Long - from Long.min to Long.max
Resources’ names and number at the time of level up
The event should be dispatched right after the level-up. The number of the level reached is passed to the level
parameter.
DTDAnalytics.INSTANCE.levelUp(2);
To monitor the average account balance of in-game currency by the end of each level, dispatch in-game currencies (resources) names and their amounts to the method signature:
Map<String, Long> resources = new HashMap<>();
resources.put("Currency name 1", 100L);
resources.put("Currency name 2", 10L);
DTDAnalytics.INSTANCE.levelUp(2, resources);
Attention! The number of tracked in-game currencies or resources (their unique names) should not exceed 30 at all times.
level
int
From 1 to Int.max - 1
Level reached
balances
Map<String,Long>
String - from 1 to 24 symbols
Long - from Long.min to Long.max
Resources’ names and number at the time of level up
The event should be dispatched right after the level-up. The number of the level reached is passed to the level
parameter.
DTDAnalytics.LevelUp(2);
To monitor the average account balance of in-game currency by the end of each level, dispatch in-game currencies (resources) names and their amounts to the method signature:
var balance = new Dictionary<string, long>();
balance.Add("Currency name 1", 100);
balance.Add("Currency name 2", 200);
DTDAnalytics.LevelUp(2, balance);
Attention! The number of tracked in-game currencies or resources (their unique names) should not exceed 30 at all times.
level
int
From 1 to int.MaxValue - 1
Level reached
balances
[string: long]
String - from 1 to 24 symbols
Long - from long.MinValue to long.MaxValue
Resources’ names and number at the time of level up
The event should be dispatched right after the level-up. The number of the level reached is passed to the level
parameter.
DTDAnalytics.LevelUp(level: 2)
To monitor the average account balance of in-game currency by the end of each level, dispatch in-game currencies (resources) names and their amounts to the method signature:
var balance = new Dictionary<string, long>();
balance.Add("Currency name 1", 100);
balance.Add("Currency name 2", 200);
DTDAnalytics.LevelUp(level: 2, resources: balance);
Attention! The number of tracked in-game currencies or resources (their unique names) should not exceed 30 at all times.
level
int
From 1 to int32.MaxValue - 1
Level reached
balances
[string: long]
String - from 1 to 24 symbols
Long - from long64.MinValue to long64.MaxValue
Resources’ names and number at the time of level up
The event should be dispatched right after the level-up. The number of the level reached is passed to the level
parameter.
devtodev.levelUp(2)
You can send and track the following data along with the level values: an average amount of the in-game currency by the end of the level, user spendings on the level, and amounts of purchased or earned in-game currency/resources. Unfortunately, Web SDK doesn’t allow to automatically calculate spending and receiving of the in-game currency/resources while users are passing the level (data accumulation on the Web might be inaccurate as users might utilize multiple browsers and devices, as well as erase local browser data).
var balance = {
"Currency name 1" : 100,
"Currency name 2" : 200
}
var spent = {
"Currency name 2" : 1
}
var earned = {
"Currency name 1" : 5
}
var bought = {
"Currency name 1" : 50,
"Currency name 2" : 30
}
window.devtodev.levelUp(2, balance, spent, earned, bought)
Attention! The number of tracked in-game currencies or resources (their unique names) should not exceed 30 at all times.
level
int
From 1 to int.MaxValue - 1
Level reached
balances
[string: long]
String - from 1 to 24 symbols
Long - from long.MinValue to long.MaxValue
Resources’ names and number at the time of level up
spent
[string: long]
String - from 1 to 24 symbols Long - from 0 to Number.MAX_SAFE_INTEGER
Game currency amount spent during the level. Optional.
earned
[string: long]
String - from 1 to 24 symbols Long - from 0 to Number.MAX_SAFE_INTEGER
Game currency earned during the level. Optional.
bought
[string: long]
String - from 1 to 24 symbols Long - from 0 to Number.MAX_SAFE_INTEGER
Game currency amount bought during the level. Optional.
The event should be dispatched right after the level-up. The number of the level reached is passed to the level
parameter.
level
int32
From 1 to int32.MaxValue - 1
Level reached
UDTDAnalyticsBPLibrary::LevelUp(2);
To monitor the average account balance of in-game currency by the end of each level, dispatch in-game currencies (resources) names and their amounts to the method signature:
Attention! The number of tracked in-game currencies or resources (their unique names) should not exceed 30 at all times.
level
int32
From 1 to int32.MaxValue - 1
Level reached
balance
TMap<FString, int64>
FString - from 1 to 24 symbols
int64 - from int64.MinValue to int64.MaxValue
Resources’ names and number at the time of level up
TMap<FString, int64> balance;
balance.Add("CurrencyName", 123);
UDTDAnalyticsBPLibrary::LevelUpWithBalance(2, balance);
The event should be dispatched right after the level-up. The number of the level reached is passed to the level
parameter.
DTDAnalytics.LevelUp(2)
To monitor the average account balance of in-game currency by the end of each level, dispatch in-game currencies (resources) names and their amounts to the method signature:
var resources = GDDTDInt64Resources.new()
resources.AddValue("level_resource_1", 6000)
resources.AddValue("level_resource_2", 95001000)
DTDAnalytics.LevelUpWithBalance(2, resources)
Attention! The number of tracked in-game currencies or resources (their unique names) should not exceed 30 at all times.
level
int
From 1 to Int32.max - 1
Level reached
balances
GDDTDInt64Resources
String - from 1 to 24 symbols
Int - from Int64.min to int64.max
Resources’ names and number at the time of level up
Current Balance
This event is for games only. It is worthwhile to integrate this event into a game type project, as specified in the application settings. In projects with the “app” type, game events will not be tracked and displayed in the interface, even if they are integrated. You can verify and change the project type in Settings → General settings.
To track the average balance of in-game currency disregarding the level up event, pass the list of in-game currency (resource) names and their amount to the method signature:
let balance: [String: Int] = ["Currency name 1": 100, "Currency name 2": 10]
DTDAnalytics.currentBalance(balance: balance)
NSDictionary *balance = @{@"Currency name 1": @100,
@"Currency name 2": @10};
[DTDAnalytics currentBalanceWithBalance:balance];
val balance = mapOf("Currency name 1" to 100L,
"Currency name 2" to 10L)
DTDAnalytics.currentBalance(
balance = balance
)
Map<String, Long> balance = new HashMap<>();
balance.put("Currency name 1", 100L);
balance.put("Currency name 2", 10L);
DTDAnalytics.INSTANCE.currentBalance(balance);
var balance = new Dictionary<string, long>();
balance.Add("Currency name 1", 100);
balance.Add("Currency name 2", 200);
DTDAnalytics.CurrentBalance(balance);
var balance = new Dictionary<string, long>();
balance.Add("Currency name 1", 100);
balance.Add("Currency name 2", 200);
DTDAnalytics.CurrentBalance(balance);
var balance = {
"Currency name 1" : 100,
"Currency name 2" : 10
}
window.devtodev.currentBalance(balance);
balance
TMap<FString, int64>
FString - from 1 to 24 symbols
int64 - from int64.MinValue to int64.MaxValue
Resources’ names and number
TMap<FString, int64> balance;
balance.Add("CurrencyName", 123);
UDTDAnalyticsBPLibrary::CurrentBalance(balance);
var resources = GDDTDInt64Resources.new()
resources.AddValue("current_balance_res_1", 222)
resources.AddValue("current_balance_res_2", 1500)
DTDAnalytics.CurrentBalance(resources)
Currency Accrual
This event is for games only. It is worthwhile to integrate this event into a game type project, as specified in the application settings. In projects with the “app” type, game events will not be tracked and displayed in the interface, even if they are integrated. You can verify and change the project type in Settings → General settings.
You need to dispatch the event after every game account balance refill if you want to track the average in-game currency amount acquired or earned by the players for a certain timeframe or during a level playthrough.
DTDAnalytics.currencyAccrual(currencyName: "Currency name 1",
currencyAmount: 100,
source: "Source name",
accrualType: .earned)
currencyName
string
from 1 to 24 symbols
In-game currency/resource name
currencyAmount
int
from 1 to Int32.max
Amount of currency in circulation
source
string
from 1 to 23 symbols
The sources of currency/resources. It can be used for breaking down income by its sources. For example, a city builder game may have some: “Rent” for the profit received from rental property, or “Bank” if the player has purchased some currency.
accrualType
DTDAccrualType (enum)
The currency/resource source type. The player can either gain resources during the game (earned
) or purchase them for money (bought
)
acrualType
can receive one of the following values:
public enum DTDAccrualType: Int {
case earned = 0
case bought = 1
}
[DTDAnalytics currencyName:@"Currency name 1"
currencyAmount:100
source:@"Source name"
accrualType:DTDAccrualTypeEarned];
currencyName
NSString
from 1 to 24 symbols
In-game currency/resource name
currencyAmount
NSInteger
from 1 to Int32.max
Amount of currency in circulation
source
NSString
from 1 to 23 symbols
The sources of currency/resources. It can be used for breaking down income by its sources. For example, a city builder game may have some: “Rent” for the profit received from rental property, or “Bank” if the player has purchased some currency.
accrualType
DTDAccrualType (enum)
The currency/resource source type. The player can either gain resources during the game (earned
) or purchase them for money (bought
)
acrualType
can receive one of the following values:
typedef enum DTDAccrualType: NSUInteger {
DTDAccrualTypeEarned = 0,
DTDAccrualTypeBought = 1,
} DTDAccrualType;
DTDAnalytics.currencyAccrual(
currencyName = "Currency name 1",
currencyAmount = 100,
source = "Source name",
DTDAccrualType = DTDAccrualType.Earned
)
currencyName
string
from 1 to 24 symbols
In-game currency/resource name
currencyAmount
int
from 1 to Int.max
Amount of currency in circulation
source
string
from 1 to 23 symbols
The sources of currency/resources. It can be used for breaking down income by its sources. For example, a city builder game may have some: “Rent” for the profit received from rental property, or “Bank” if the player has purchased some currency.
accrualType
DTDAccrualType (enum)
The currency/resource source type. The player can either gain resources during the game (earned
) or purchase them for money (bought
)
accrualType
can receive one of the following values:
enum class DTDAccrualType(val value: Long) {
Earned(0L),
Bought(1L);
}
DTDAnalytics.INSTANCE.currencyAccrual(
"Currency name 1",
100,
"Source name",
DTDAccrualType.Earned
);
currencyName
string
from 1 to 24 symbols
In-game currency/resource name
currencyAmount
int
from 1 to Int.max
Amount of currency in circulation
source
string
from 1 to 23 symbols
The sources of currency/resources. It can be used for breaking down income by its sources. For example, a city builder game may have some: “Rent” for the profit received from rental property, or “Bank” if the player has purchased some currency.
accrualType
DTDAccrualType (enum)
The currency/resource source type. The player can either gain resources during the game (earned
) or purchase them for money (bought
)
accrualType
can receive one of the following values:
public final enum class DTDAccrualType {
Earned;
Bought;
}a
DTDAnalytics.CurrencyAccrual(
currencyName: "Currency name 1",
currencyAmount: 100,
source: "Source name",
accrualType: DTDAccrualType.Earned);
currencyName
string
from 1 to 24 symbols
In-game currency/resource name
currencyAmount
int
from 1 to Int.MaxValue
Amount of currency in circulation
source
string
from 1 to 23 symbols
The sources of currency/resources. It can be used for breaking down income by its sources. For example, a city builder game may have some: “Rent” for the profit received from rental property, or “Bank” if the player has purchased some currency.
accrualType
DTDAccrualType (enum)
The currency/resource source type. The player can either gain resources during the game (earned
) or purchase them for money (bought
)
AccrualType
can receive one of the following values:
enum DTDAccrualType : long
{
Earned = 0L,
Bought = 1L
}
DTDAnalytics.CurrencyAccrual(currencyName: "Currency name 1",
currencyAmount: 100,
source: "Source name",
accrualType: DTDAccrualType.Earned)
currencyName
string
from 1 to 24 symbols
In-game currency/resource name
currencyAmount
int
from 1 to Int32.MaxValue
Amount of currency in circulation
source
string
from 1 to 23 symbols
The sources of currency/resources. It can be used for breaking down income by its sources. For example, a city builder game may have some: “Rent” for the profit received from rental property, or “Bank” if the player has purchased some currency.
accrualType
DTDAccrualType (enum)
The currency/resource source type. The player can either gain resources during the game (earned
) or purchase them for money (bought
)
AccrualType
can receive one of the following values:
public enum DTDAccrualType
{
Earned = 0,
Bought = 1
}
window.devtodev.currencyAccrual(
currencyName,
currencyAmount,
source,
accrualType)
currencyName
string
from 1 to 24 symbols
In-game currency/resource name
currencyAmount
int
from 1 to Int.max
Amount of currency in circulation
source
string
from 1 to 23 symbols
The sources of currency/resources. It can be used for breaking down income by its sources. For example, a city builder game may have some: “Rent” for the profit received from rental property, or “Bank” if the player has purchased some currency.
accrualType
int
The currency/resource source type. The player can either gain resources during the game (0
) or purchase them for money (1
)
Example:
window.devtodev.currencyAccrual(
"Currency name 1",
100,
"Source name",
0)
currencyName
FString
from 1 to 24 symbols
In-game currency/resource name
currencyAmount
int32
from 1 to Int32.MaxValue
Amount of currency in circulation
source
FString
from 1 to 23 symbols
The sources of currency/resources. It can be used for breaking down income by its sources. For example, a city builder game may have some: “Rent” for the profit received from rental property, or “Bank” if the player has purchased some currency.
accrualType
EDTDAccrualType
The currency/resource source type. The player can either gain resources during the game (earned
) or purchase them for money (bought
)
UDTDAnalyticsBPLibrary::CurrencyAccrual("CurrencyName", 12, "Source", EDTDAccrualType::Bought);
DTDAnalytics.CurrencyAccrual("currencyName_1", 500, "store", GDDTDAccrualType.Bought)
DTDAnalytics.CurrencyAccrual("currencyName_2", 10, "market", GDDTDAccrualType.Earned)
currencyName
String
from 1 to 24 symbols
In-game currency/resource name
currencyAmount
int
from 1 to Int32.max
Amount of currency in circulation
source
String
from 1 to 23 symbols
The sources of currency/resources. It can be used for breaking down income by its sources. For example, a city builder game may have some: “Rent” for the profit received from rental property, or “Bank” if the player has purchased some currency.
accrualType
GDDTDAccrualType (enum)
The currency/resource source type. The player can either gain resources during the game (earned
) or purchase them for money (bought
)
acrualType
can receive one of the following values:
enum AccrualType:
Earned = 0
Bought = 1
Virtual Currency Payment
This event is for games only. It is worthwhile to integrate this event into a game type project, as specified in the application settings. In projects with the “app” type, game events will not be tracked and displayed in the interface, even if they are integrated. You can verify and change the project type in Settings → General settings.
Pass this event after every purchase if you want to track in-game currency spends and items’ popularity. You can apply this event to both games and any apps with virtual currency.
DTDAnalytics.virtualCurrencyPayment(purchaseId: "Purchase ID",
purchaseType: "Purchase type",
purchaseAmount: 100,
purchasePrice: 10,
purchaseCurrency: "Purchase currency")
In case the item is sold for more than one currency/resource, you need to build a dictionary with all the names and amounts of the currencies/resources.
let resources: [String: Int] = ["Purchase currency name 1": 100,
"Purchase currency name 2": 10]
DTDAnalytics.virtualCurrencyPayment(purchaseId: "Purchase ID",
purchaseType: "Purchase Type",
purchaseAmount: 100,
resources: resources)
purchaseId
string
from 1 to 32 symbols
A unique purchase name or ID. Make sure that the names are always in the same language otherwise they will be listed as different items.
purchaseType
string
from 1 to 96 symbols
The name of a resource group. For example, for “Wood” it can be “Construction materials”.
purchaseAmount
int
from 1 to Int32.max
The number of units of goods purchased.
purchaseCurrency
string
from 1 to 24 symbols
The name of a currency used for the purchase.
purchasePrice
int
from 1 to Int32.max
The price of the purchased item in the specified in-game currency.
[DTDAnalytics virtualCurrencyPaymentWithPurchaseId:@"Purchase ID"
purchaseType:@"Purchase type"
purchaseAmount:100
purchasePrice:10
purchaseCurrency:@"Purchase currency"];
In case the item is sold for more than one currency/resource, you need to build a dictionary with all the names and amounts of the currencies/resources.
NSDictionary *resources = @{@"Purchase currency name 1": @100,
@"Purchase currency name 2": @10};
[DTDAnalytics virtualCurrencyPaymentWithPurchaseId:@"Purchase ID"
purchaseType:@"Purchase Type"
purchaseAmount:100
resources:resources];
purchaseId
NSString
from 1 to 32 symbols
A unique purchase name or ID. Make sure that the names are always in the same language otherwise they will be listed as different items.
purchaseType
NSString
from 1 to 96 symbols
The name of a resource group. For example, for “Wood” it can be “Construction materials”.
purchaseAmount
NSInteger
from 1 to Int32.max
The number of units of goods purchased.
purchaseCurrency
NSString
from 1 to 24 symbols
The name of a currency used for the purchase.
purchasePrice
NSInteger
from 1 to Int32.max
The price of the purchased item in the specified in-game currency.
DTDAnalytics.virtualCurrencyPayment(
purchaseId = "Purchase ID",
purchaseType = "Purchase type",
purchaseAmount = 100,
purchasePrice = 10,
purchaseCurrency = "Purchase currency"
)
In case the item is sold for more than one currency/resource, you need to build a dictionary with all the names and amounts of the currencies/resources.
val resources = mapOf(
"Purchase currency name 1" to 100,
"purchase Currency name 2" to 10
)
ot
DTDAnalytics.virtualCurrencyPayment(
purchaseId = "Purchase ID",
purchaseType = "Purchase Type",
purchaseAmount = 100,
map = resources
)
purchaseId
string
from 1 to 32 symbols
A unique purchase name or ID. Make sure that the names are always in the same language otherwise they will be listed as different items.
purchaseType
string
from 1 to 96 symbols
The name of a resource group. For example, for “Wood” it can be “Construction materials”.
purchaseAmount
int
from 1 to Int.max
The number of units of goods purchased.
purchaseCurrency
string
from 1 to 24 symbols
The name of a currency used for the purchase.
purchasePrice
int
from 1 to Int.max
The price of the purchased item in the specified in-game currency.
DTDAnalytics.INSTANCE.virtualCurrencyPayment(
"Purchase ID",
"Purchase type",
100,
10,
"Purchase currency"
);
In case the item is sold for more than one currency/resource, you need to build a dictionary with all the names and amounts of the currencies/resources.
Map<String, Integer> resources = new HashMap<>();
resources.put("Purchase currency name 1", 100);
resources.put("Purchase currency name 2", 10);
DTDAnalytics.INSTANCE.virtualCurrencyPayment(
"Purchase ID",
"Purchase Type",
100,
resources
);
purchaseId
string
from 1 to 32 symbols
A unique purchase name or ID. Make sure that the names are always in the same language otherwise they will be listed as different items.
purchaseType
string
from 1 to 96 symbols
The name of a resource group. For example, for “Wood” it can be “Construction materials”.
purchaseAmount
int
from 1 to Int.max
The number of units of goods purchased.
purchaseCurrency
string
from 1 to 24 symbols
The name of a currency used for the purchase.
purchasePrice
int
from 1 to Int.max
The price of the purchased item in the specified in-game currency.
DTDAnalytics.VirtualCurrencyPayment(
purchaseId: "Purchase ID",
purchaseType: "Purchase type",
purchaseAmount: 100,
purchasePrice: 10,
purchaseCurrency: "Purchase currency");
In case the item is sold for more than one currency/resource, you need to build a dictionary with all the names and amounts of the currencies/resources.
var resources = new Dictionary<string, int>
{
["Purchase currency name 1"] = 100,
["purchase Currency name 2"] = 10
};
DTDAnalytics.VirtualCurrencyPayment(
purchaseId: "Purchase ID",
purchaseType: "Purchase Type",
purchaseAmount: 100,
resources: resources);
purchaseId
string
from 1 to 32 symbols
A unique purchase name or ID. Make sure that the names are always in the same language otherwise they will be listed as different items.
purchaseType
string
from 1 to 96 symbols
The name of a resource group. For example, for “Wood” it can be “Construction materials”.
purchaseAmount
int
from 1 to int.MaxValue
The number of units of goods purchased.
purchaseCurrency
string
from 1 to 24 symbols
The name of a currency used for the purchase.
purchasePrice
int
from 1 to int.MaxValue
The price of the purchased item in the specified in-game currency.
DTDAnalytics.VirtualCurrencyPayment(purchaseId: "Purchase ID",
purchaseType: "Purchase type",
purchaseAmount: 100,
purchasePrice: 10,
purchaseCurrency: "Purchase currency")
In case the item is sold for more than one currency/resource, you need to build a dictionary with all the names and amounts of the currencies/resources.
var resources = new Dictionary<string, int>
{
["Purchase currency name 1"] = 100,
["purchase Currency name 2"] = 10
};
DTDAnalytics.VirtualCurrencyPayment(
purchaseId: "Purchase ID",
purchaseType: "Purchase Type",
purchaseAmount: 100,
resources: resources);
purchaseId
string
from 1 to 32 symbols
A unique purchase name or ID. Make sure that the names are always in the same language otherwise they will be listed as different items.
purchaseType
string
from 1 to 96 symbols
The name of a resource group. For example, for “Wood” it can be “Construction materials”.
purchaseAmount
int
from 1 to Int32.MaxValue
The number of units of goods purchased.
purchaseCurrency
string
from 1 to 24 symbols
The name of a currency used for the purchase.
purchasePrice
int
from 1 to Int32.MaxValue
The price of the purchased item in the specified in-game currency.
window.devtodev.virtualCurrencyPayment(
purchaseId,
purchaseType,
purchaseAmount,
purchasePrice,
purchaseCurrency)
In case the item is sold for more than one currency/resource, you need to build a dictionary with all the names and amounts of the currencies/resources.
var resources = {
"Purchase currency name 1": 100,
"purchase Currency name 2": 10
};
window.devtodev.virtualCurrencyPayment(
"Purchase ID",
"Purchase type",
100,
resources)
purchaseId
string
from 1 to 32 symbols
A unique purchase name or ID. Make sure that the names are always in the same language otherwise they will be listed as different items.
purchaseType
string
from 1 to 96 symbols
The name of a resource group. For example, for “Wood” it can be “Construction materials”.
purchaseAmount
int
from 1 to Number.MAX_SAFE_INTEGER
The number of units of goods purchased.
purchaseCurrency
string
from 1 to 24 symbols
The name of a currency used for the purchase.
purchasePrice
int
from 1 to Number.MAX_SAFE_INTEGER
The price of the purchased item in the specified in-game currency.
purchaseId
FString
from 1 to 32 symbols
A unique purchase name or ID. Make sure that the names are always in the same language otherwise they will be listed as different items.
purchaseType
FString
from 1 to 96 symbols
The name of a resource group. For example, for “Wood” it can be “Construction materials”.
purchaseAmount
int32
from 1 to Int32.MaxValue
The number of units of goods purchased.
purchaseCurrency
FString
from 1 to 24 symbols
The name of a currency used for the purchase.
purchasePrice
int32
from 1 to Int32.MaxValue
The price of the purchased item in the specified in-game currency.
UDTDAnalyticsBPLibrary::VirtualCurrencyPayment("PurchaseId", "PurchaseType", 2, 3, "CurrencyName");
In case the item is sold for more than one currency/resource, you need to build a dictionary with all the names (FString) and amounts of the currencies/resources (int32) .
purchaseId
FString
from 1 to 32 symbols
A unique purchase name or ID. Make sure that the names are always in the same language otherwise they will be listed as different items.
purchaseType
FString
from 1 to 96 symbols
The name of a resource group. For example, for “Wood” it can be “Construction materials”.
purchaseAmount
int32
from 1 to int32.MaxValue
The number of units of goods purchased.
resources
TMap<FString, int32>
FString - from 1 to 24 symbols
int32 - from 1 to int32.MaxValue
Map with resources.
var resources = new Dictionary<string, int>
{
["Purchase currency name 1"] = 100,
["purchase Currency name 2"] = 10
};
DTDAnalytics.VirtualCurrencyPayment(
purchaseId: "Purchase ID",
purchaseType: "Purchase Type",
purchaseAmount: 100,
resources: resources);
DTDAnalytics.VirtualCurrencyPayment("purchaseID", "purchaseType", 1000, 15, "resource_1")
In case the item is sold for more than one currency/resource, you need to build a dictionary with all the names and amounts of the currencies/resources.
var resources = GDDTDInt32Resources.new()
resources.AddValue("resource_1", 700)
resources.AddValue("resource_2", 100)
DTDAnalytics.VirtualCurrencyPaymentWithResources("purchaseID", "purchaseType", 500, resources)
purchaseId
String
from 1 to 32 symbols
A unique purchase name or ID. Make sure that the names are always in the same language otherwise they will be listed as different items.
purchaseType
String
from 1 to 96 symbols
The name of a resource group. For example, for “Wood” it can be “Construction materials”.
purchaseAmount
int
from 1 to Int32.max
The number of units of goods purchased.
purchaseCurrency
String
from 1 to 24 symbols
The name of a currency used for the purchase.
purchasePrice
int
from 1 to Int32.max
The price of the purchased item in the specified in-game currency.
Progression event
This event is for games only. It is worthwhile to integrate this event into a game type project, as specified in the application settings. In projects with the “app” type, game events will not be tracked and displayed in the interface, even if they are integrated. You can verify and change the project type in Settings → General settings.
First of all, the progression event is used in games with short (within one game session) areas/game levels, e.g. match 3 games. You can use the event to collect data on how well or how fast users complete levels, how difficult it is for them, how many resources they gained or spent, and other parameters.
There are two methods in working with progression event:
startProgressionEvent
finishProgressionEvent
When a player spawns at a location, the following method is called:
let parameters = DTDStartProgressionEventParameters()
parameters.source = "Source"
parameters.setDifficulty(difficulty: 10)
DTDAnalytics.startProgressionEvent(eventName: "Progression event name",
parameters: parameters)
eventName
string
from 1 to 40 symbols
The name of the event. It is usually the number or the name of the area.
DTDStartProgressionEventParameters
:
source
string
from 1 to 40 symbols
The name of the previous event used for connecting events together. E.g. a previous area visited by the player.
difficulty
int
from 0 to Int32.max
An optional difficulty value which is set using the value: setDifficulty(difficulty: Int)
Once the player completes the location successfully, the following method is called:
let parameters = DTDFinishProgressionEventParameters()
parameters.successfulCompletion = true
parameters.duration = 100
parameters.spent = ["currency name 1": 1000,
"currency name 2": 50]
parameters.earned = ["currency name 2": 100]
DTDAnalytics.finishProgressionEvent(eventName: "Progression event name",
parameters: parameters)
eventName
string
from 1 to 40 symbols
The name of the event. It is usually the number or the name of the area. It’s important to use the name that was specified at the area’s opening.
DTDFinishProgressionEventParameters
:
successfulCompletion
bool
true/false
The completion event result. ‘True’ if successful, ‘false’ if unsuccessful/lost.
duration
int
from 0 to Int64.max
Time in seconds taken to complete the area. If not specified, it is automatically calculated as the difference between startProgressionEvent
and finishProgressionEvent
method calls.
spent
[String: Int]
key - from 1 to 24 symbols
value - from 1 to Int64.max
Resources consumed during an area completion.
earned
[String: Int]
key - from 1 to 24 symbols
value - from 1 to Int64.max
Resources earned during an area completion.
There are two methods in working with progression event:
startProgressionEvent
finishProgressionEvent
When a player spawns at a location, the following method is called:
DTDStartProgressionEventParameters * parameters = [[DTDStartProgressionEventParameters alloc] init];
parameters.source = @"Source";
[parameters setDifficultyWithDifficulty:10];
[DTDAnalytics startProgressionEvent:@"Progression event name" withParameters:parameters];
eventName
NSString
from 1 to 40 symbols
The name of the event. It is usually the number or the name of the area.
DTDStartProgressionEventParameters
:
source
NSString
from 1 to 40 symbols
The name of the previous event used for connecting events together. E.g. a previous area visited by the player.
difficulty
NSInteger
from 0 to Int32.max
An optional difficulty value which is set using the value: setDifficulty(difficulty: Int)
Once the player completes the location successfully, the following method is called:
DTDFinishProgressionEventParameters *parameters = [[DTDFinishProgressionEventParameters alloc] init];
parameters.successfulCompletion = true;
parameters.duration = 100;
parameters.spent = @{@"currency name 1": @1000,
@"currency name 2": @50};
parameters.earned = @{@"currency name 2": @100};
[DTDAnalytics finishProgressionEvent:@"Progression event name" withParameters:parameters];
eventName
NSString
from 1 to 40 symbols
The name of the event. It is usually the number or the name of the area. It’s important to use the name that was specified at the area’s opening.
DTDFinishProgressionEventParameters
:
successfulCompletion
BOOL
true/false
The completion event result. ‘True’ if successful, ‘false’ if unsuccessful/lost.
duration
NSInteger
from 0 to Int64.max
Time in seconds taken to complete the area. If not specified, it is automatically calculated as the difference between startProgressionEvent
and finishProgressionEvent
method calls.
spent
NSDictionary<NSString *,NSNumber *>
key - from 1 to 24 symbols
value - from 1 to Int64.max
Resources consumed during an area completion.
earned
NSDictionary<NSString *,NSNumber *>
key - from 1 to 24 symbols
value - from 1 to Int64.max
Resources earned during an area completion.
There are two methods in working with progression event:
startProgressionEvent
finishProgressionEvent
When a player spawns at a location, the following method is called:
let parameters = DTDStartProgressionEventParameters()
parameters.source = "Source"
parameters.setDifficulty(difficulty = 10)
DTDAnalytics.startProgressionEvent(
eventName = "Progression event name",
parameters = parameters
)
eventName
string
from 1 to 40 symbols
The name of the event. It is usually the number or the name of the area.
DTDStartProgressionEventParameters
:
source
string
from 1 to 40 symbols
The name of the previous event used for connecting events together. E.g. a previous area visited by the player.
difficulty
int
from 0 to Int32.max
An optional difficulty value which is set using the value: setDifficulty(difficulty: Int)
Once the player completes the location successfully, the following method is called:
let parameters = DTDFinishProgressionEventParameters()
parameters.successfulCompletion = true
parameters.duration = 100
parameters.spent = ["currency name 1": 1000,
"currency name 2": 50]
parameters.earned = ["currency name 2": 100]
DTDAnalytics.finishProgressionEvent(
eventName = "Progression event name",
parameters = parameters
)
eventName
string
from 1 to 40 symbols
The name of the event. It is usually the number or the name of the area. It’s important to use the name that was specified at the area’s opening.
DTDFinishProgressionEventParameters
:
successfulCompletion
bool
true/false
The completion event result. ‘True’ if successful, ‘false’ if unsuccessful/lost.
duration
int
from 0 to Int64.max
Time in seconds taken to complete the area. If not specified, it is automatically calculated as the difference between startProgressionEvent
and finishProgressionEvent
method calls.
spent
Map<String, Long>
key - from 1 to 24 symbols
value - from 1 to Int64.max
Resources consumed during an area completion.
earned
Map<String, Long>
key - from 1 to 24 symbols
value - from 1 to Int64.max
Resources earned during an area completion.
There are two methods in working with progression event:
startProgressionEvent
finishProgressionEvent
When a player spawns at a location, the following method is called:
DTDStartProgressionEventParameters parameters = new DTDStartProgressionEventParameters();
parameters.setSource("Source");
parameters.setDifficulty(10);
DTDAnalytics.INSTANCE.startProgressionEvent("Progression event name", parameters);
eventName
string
from 1 to 40 symbols
The name of the event. It is usually the number or the name of the area.
DTDStartProgressionEventParameters
:
source
string
from 1 to 40 symbols
The name of the previous event used for connecting events together. E.g. a previous area visited by the player.
difficulty
int
from 0 to Int32.max
An optional difficulty value which is set using the value: setDifficulty(difficulty: Int)
Once the player completes the location successfully, the following method is called:
Map<String, Long> spendMap = new HashMap<>();
spendMap.put("currency name 1", 1000L);
spendMap.put("currency name 2", 100L);
Map<String, Long> earnedMap = new HashMap<>();
spendMap.put("currency name 2", 100L);
DTDFinishProgressionEventParameters param = new DTDFinishProgressionEventParameters();
param.setSuccessfulCompletion(true);
param.setDuration(100);
param.setSpent(spendMap);
param.setEarned(earnedMap);
DTDAnalytics.INSTANCE.finishProgressionEvent("Progression event name", param);
eventName
string
from 1 to 40 symbols
The name of the event. It is usually the number or the name of the area. It’s important to use the name that was specified at the area’s opening.
DTDFinishProgressionEventParameters
:
successfulCompletion
bool
true/false
The completion event result. ‘True’ if successful, ‘false’ if unsuccessful/lost.
duration
int
from 0 to Int64.max
Time in seconds taken to complete the area. If not specified, it is automatically calculated as the difference between startProgressionEvent
and finishProgressionEvent
method calls.
spent
Map<String, Long>
key - from 1 to 24 symbols
value - from 1 to Int64.max
Resources consumed during an area completion.
earned
Map<String, Long>
key - from 1 to 24 symbols
value - from 1 to Int64.max
Resources earned during an area completion.
There are two methods in working with progression event:
StartProgressionEvent
FinishProgressionEvent
When a player spawns at a location, the following method is called:
var parameters = new DTDStartProgressionEventParameters();
parameters.Source = "Source";
parameters.Difficulty = 10;
DTDAnalytics.StartProgressionEvent(
eventName: "Progression event name",
parameters: parameters);
eventName
string
from 1 to 40 symbols
The name of the event. It is usually the number or the name of the area.
DTDStartProgressionEventParameters
:
source
string
from 1 to 40 symbols
The name of the previous event used for connecting events together. E.g. a previous area visited by the player.
difficulty
int
from 0 to int.MaxValue
An optional difficulty value.
Once the player completes the location successfully, the following method is called:
var parameters = new DTDFinishProgressionEventParameters();
parameters.SuccessfulCompletion = true;
parameters.Duration = 100;
parameters.Spent = new Dictionary<string, long>
{
["currency name 1"] = 1000,
["currency name 2"] = 50
};
parameters.Earned = new Dictionary<string, long>
{
["currency name 2"] = 100
};
DTDAnalytics.FinishProgressionEvent(
eventName: "Progression event name",
parameters: parameters);
eventName
string
from 1 to 40 symbols
The name of the event. It is usually the number or the name of the area. It’s important to use the name that was specified at the area’s opening.
DTDFinishProgressionEventParameters
:
successfulCompletion
bool
true/false
The completion event result. ‘True
’ if successful, ‘false
’ if unsuccessful/lost.
duration
int
from 0 to int.MaxValue
Time in seconds taken to complete the area. If not specified, it is automatically calculated as the difference between StartProgressionEvent
and FinishProgressionEvent
method calls.
spent
[String: Int]
key - from 1 to 24 symbols
value - From 1 to int.MaxValue
Resources consumed during an area completion.
earned
[String: Int]
key - from 1 to 24 symbols
value - From 1 to int.MaxValue
Resources earned during an area completion.
There are two methods in working with progression event:
StartProgressionEvent
FinishProgressionEvent
When a player spawns at a location, the following method is called:
var parameters = new DTDStartProgressionEventParameters();
parameters.Source = "Source";
parameters.Difficulty = 10;
DTDAnalytics.StartProgressionEvent(
eventName: "Progression event name",
parameters: parameters);
eventName
string
from 1 to 40 symbols
The name of the event. It is usually the number or the name of the area.
DTDStartProgressionEventParameters
:
source
string
from 1 to 40 symbols
The name of the previous event used for connecting events together. E.g. a previous area visited by the player.
difficulty
int
from 0 to Int32.MaxValue
An optional difficulty value.
Once the player completes the location successfully, the following method is called:
var parameters = new DTDFinishProgressionEventParameters();
parameters.SuccessfulCompletion = true;
parameters.Duration = 100;
parameters.Spent = new Dictionary<string, long>
{
["currency name 1"] = 1000,
["currency name 2"] = 50
};
parameters.Earned = new Dictionary<string, long>
{
["currency name 2"] = 100
};
DTDAnalytics.FinishProgressionEvent(
eventName: "Progression event name",
parameters: parameters);
eventName
string
from 1 to 40 symbols
The name of the event. It is usually the number or the name of the area. It’s important to use the name that was specified at the area’s opening.
DTDFinishProgressionEventParameters
:
successfulCompletion
bool
true/false
The completion event result. ‘True
’ if successful, ‘false
’ if unsuccessful/lost.
duration
int
from 0 to Int64.MaxValue
Time in seconds taken to complete the area. If not specified, it is automatically calculated as the difference between StartProgressionEvent
and FinishProgressionEvent
method calls.
spent
[String: Int]
key - from 1 to 24 symbols
value - From 1 to Int64.MaxValue
Resources consumed during an area completion.
earned
[String: Int]
key - from 1 to 24 symbols
value - From 1 to Int64.MaxValue
Resources earned during an area completion.
There are two methods in working with progression event:
startProgressionEvent
finishProgressionEvent
When a player spawns at a location, the following method is called:
window.devtodev.startProgressionEvent(eventName, parameters)
eventName
string
from 1 to 40 symbols
The name of the event. It is usually the number or the name of the area.
parameters
object
see below
Location event parameters.
startProgressionEvent
event parameters:
source
string
from 1 to 40 symbols
The name of the previous event used for connecting events together. E.g. a previous area visited by the player.
difficulty
int
from 0 to Number.MAX_SAFE_INTEGER
An optional difficulty value.
Example:
window.devtodev.startProgressionEvent("Location 11", {
difficulty: 10,
source: "Location 10"
})
Once the player completes the location (instead of successfully or not), the following method is called:
window.devtodev.finishProgressionEvent("Progression event name", {
successfulCompletion,
duration,
spent,
earned
})
eventName
string
from 1 to 40 symbols
The name of the event. It is usually the number or the name of the area. It’s important to use the name that was specified at the area’s opening.
parameters
object
see below
Location event parameters.
startProgressionEvent
event parameters:
successfulCompletion
bool
true/false
The completion event result. ‘True’ if successful, ‘false’ if unsuccessful/lost.
duration
int
from 0 to Number.MAX_SAFE_INTEGER
Time in seconds taken to complete the area. If not specified, it is automatically calculated as the difference between startProgressionEvent
and finishProgressionEvent
method calls.
spent
[String: Int]
key - from 1 to 24 symbols
value - from 1 to Number.MAX_SAFE_INTEGER
Resources consumed during an area completion.
earned
[String: Int]
key - from 1 to 24 symbols
value - from 1 to Number.MAX_SAFE_INTEGER
Resources earned during an area completion.
Example:
window.devtodev.finishProgressionEvent("Location 11", {
true,
100,
spent: {
"currency name 1": 1000,
"currency name 2": 50
},
earned: {
"currency name 2": 100
}
})
There are two methods in working with progression event:
startProgressionEvent
finishProgressionEvent
When a player spawns at a location, the following method is called (one of them):
eventName
FString
from 1 to 72 symbols
Progression event name.
UDTDAnalyticsBPLibrary::StartProgressionEvent("EventName");
Start progression event with parameters:
eventName
FString
from 1 to 40 symbols
The name of the event. It is usually the number or the name of the area.
params
FDTDStartProgressionEventParams
see below
Start progression event parameters.
FDTDStartProgressionEventParams:
source
FString
from 1 to 40 symbols
The name of the previous event used for connecting events together. E.g. a previous area visited by the player.
difficulty
int32
from 0 to int32.MaxValue
An optional difficulty value.
Example:
StartProgressionEventParams params;
params.Difficulty = 3;
params.Source = "Source";
UDTDAnalyticsBPLibrary::StartProgressionEventWithParams("EventName", params);
Once the player completes the location (instead of successfully or not), the following method is called (one of them):
eventName
FString
from 1 to 72 symbols
Progression event name.
UDTDAnalyticsBPLibrary::FinishProgressionEvent("EventName");window.devtodev.finishProgressionEvent("Progression event name", {
Finish progression event with parameters:
eventName
FString
from 1 to 40 symbols
The name of the event. It is usually the number or the name of the area. It’s important to use the name that was specified at the area’s opening.
parameters
FDTDFinishProgressionEventParams
see below
Finish progression event parameters.
FDTDFinishProgressionEventParameters:TMap<FString, int64>
successfulCompletion
bool
true/false
The completion event result. ‘True’ if successful, ‘false’ if unsuccessful/lost.
duration
int32
from 0 to int32.MaxValue
Time in seconds taken to complete the area. If not specified, it is automatically calculated as the difference between startProgressionEvent
and finishProgressionEvent
method calls.
spent
TMap<FString, int64>
key - from 1 to 24 symbols
value - from 0 to int64.MaxValue
Resources consumed during an area completion.
earned
TMap<FString, int64>
key - from 1 to 24 symbols
value - from 0 to int64.MaxValue
Resources earned during an area completion.
Example:
FDTDFinishProgressionEventParams params;
params.Duration = 200;
params.SuccessfulCompletion = true;
params.Earned.Add("CurrencyName1", 1);
params.Spent.Add("CurrencyName2", 2);
UDTDAnalyticsBPLibrary::FinishProgressionEventWithParams("EventName", params);
There are two methods in working with progression event:
StartProgressionEvent
FinishProgressionEvent
When a player spawns at a location, the following method is called:
var params = GDDTDStartProgressionEventParams.new()
params.SetDifficulty(10)
params.SetSource("source_1")
DTDAnalytics.StartProgressionEventWithParams("ProgressionEventWithParams", params)
eventName
String
from 1 to 40 symbols
The name of the event. It is usually the number or the name of the area.
GDDTDStartProgressionEventParameters
:
source
String
from 1 to 40 symbols
The name of the previous event used for connecting events together. E.g. a previous area visited by the player.
difficulty
int
from 0 to Int32.max
An optional difficulty value which is set using the value: SetDifficulty()
Once the player completes the location successfully, the following method is called:
var earnedResources = GDDTDInt64Resources.new()
earnedResources.AddValue("resource_1", 200)
earnedResources.AddValue("resource_2", 1500)
var spentResources = GDDTDInt64Resources.new()
spentResources.AddValue("resource_1", 100)
spentResources.AddValue("resource_2", 600)
var params = GDDTDFinishProgressionEventParams.new()
params.SetSuccessfulCompletion(true)
params.SetEarnedResources(earnedResources)
params.SetSpentResources(spentResources)
params.SetDuration(2000)
DTDAnalytics.FinishProgressionEventWithParams("ProgressionEventWithParams", params)
eventName
string
from 1 to 40 symbols
The name of the event. It is usually the number or the name of the area. It’s important to use the name that was specified at the area’s opening.
GDDTDFinishProgressionEventParameters
:
successfulCompletion
bool
true/false
The completion event result. ‘True’ if successful, ‘false’ if unsuccessful/lost.
duration
int
from 0 to Int64.max
Time in seconds taken to complete the area. If not specified, it is automatically calculated as the difference between startProgressionEvent
and finishProgressionEvent
method calls.
spent
GDDTDInt64Resources
key - from 1 to 24 symbols
value - from 1 to Int64.max
Resources consumed during an area completion.
earned
GDDTDInt64Resources
key - from 1 to 24 symbols
value - from 1 to Int64.max
Resources earned during an area completion.
The user can only be in one area at a time. When moving to another area (including nested ones), the previous location must be completed. Information about events that have not been completed by calling the finishProgressionEvent
method during a game session (the finishProgressionEvent
method call is not integrated, or the user uses the cached app, or the app has crashed) is not included in the statistics.
If you want to use this event to track actions that take more than one game session, you can prepare the required data and call both methods when the action is completed (successfully or unsuccessfully). For example, you can use this event to track the main questline.
Last updated