# Basic methods

{% hint style="danger" %}
**This generation of SDK is deprecated and is no longer supported.**\
Information about the [current version can be found here](https://docs.devtodev.com/integration/integration-of-sdk-v2/setting-up-events/basic-methods).
{% endhint %}

[Expert tips](https://docs.devtodev.com/integration/expert-tips/what-to-track) before integrating the events.

## **Onboarding (tutorial)**

The Tutorial steps event allows you to evaluate the effectiveness of the tutorial steps system. The event should be sent at the end of each tutorial step indicating the number of every passed step as a parameter.

Use the following constants to specify basic events of tutorial steps:

{% tabs %}
{% tab title="iOS" %}

* **Start** or **-1** - at the beginning, before the first step is completed;
* **Finish** or **-2** - instead of the final step number;
* **Skipped** or **0** - in case а user skipped the tutorial.
  {% endtab %}

{% tab title="Android" %}

* DevToDev.TutorialState.**Start** or **-1** - at the beginning, before the first step is completed;
* DevToDev.TutorialState.**Finish** or **-2** - instead of the last step number;
* DevToDev.TutorialState.**Skipped** or **0** - if a user skipped the tutorial.
  {% endtab %}

{% tab title="Windows 8.1 and 10" %}

* DevToDev.TutorialState.**Start** or **-1** - at the beginning, before the first step is completed;
* DevToDev.TutorialState.**Finish** or **-2** - instead of the last step number;
* DevToDev.TutorialState.**Skipped** or **0** - if a user skipped the tutorial.
  {% endtab %}

{% tab title="Web" %}

* **-1** - Start the tutorial (at the beginning, before the first step is completed)
* **-2** - Tutorial finished (instead of the last step number)
* **0** - Tutorial skipped (if a user skipped the tutorial).
  {% endtab %}

{% tab title="Unity" %}

* DevToDev.TutorialState.**Start** or **-1** - at the beginning, before the first step is completed;
* DevToDev.TutorialState.**Finish** or **-2** - instead of the last step number;
* DevToDev.TutorialState.**Skipped** or **0** - if a user skipped the tutorial.
  {% endtab %}

{% tab title="Mac OS" %}

* **Start** or **-1** - at the beginning, before the first step is completed;
* **Finish** or **-2** - instead of the final step number;
* **Skipped** or **0** - in case a user skipped the tutorial.
  {% endtab %}

{% tab title="Adobe Air" %}

* TutorialState.**START** or **-1** - at the beginning, before the first step is completed;
* TutorialState.**FINISH** or **-2** - instead of the last step number;
* TutorialState.**SKIPPED** or **0** - if a user skipped the tutorial.
  {% endtab %}

{% tab title="UE4" %}

* **-1 (Start)** - at the beginning, before the first step is completed;
* **-2 (Finish)** - instead of the number of the last step;
* **0 (Skipped)** - in case a user skipped the tutorial.
  {% endtab %}
  {% endtabs %}

In other cases use step numbers. Make sure you use numbers above 0 to enumerate the steps.

{% hint style="warning" %}
The logic of the use of the **Skipped** constant in the Tutorial steps event is provided only in case a user has completely refused to pass the tutorial. After **Skipped** is used, no other values of the Tutorial steps event must be received.&#x20;
{% endhint %}

{% tabs %}
{% tab title="iOS" %}

```objectivec
/**
* The event allowing to track the stage of tutorial a player is on.
* @param NSUInteger tutorialStep - the latest successfully completed tutorial step.
*/
[DevToDev tutorialCompleted: (NSUInteger) tutorialStep];
```

{% endtab %}

{% tab title="Android" %}

```java
/**
* The event allowing to track the stage of tutorial a player is on.
* @param int tutorialStep - the latest successfully completed tutorial step.
*/
DevToDev.tutorialCompleted(int tutorialStep);
```

{% endtab %}

{% tab title="Windows 8.1 and 10" %}

```csharp
/**
*  <param name="state"> The latest successfully completed tutorial step </param>
*/
DevToDev.SDK.Tutorial(int state)
```

{% endtab %}

{% tab title="Web" %}

```javascript
/**
* The event allowing to track the stage of tutorial a player is on.
* @param {number} tutorialStep - the latest successfully completed tutorial step.
*/
devtodev.tutorialCompleted(tutorialStep);
```

{% endtab %}

{% tab title="Unity" %}

```csharp
/// <summary> The event allowing to track the stage of tutorial a player is on. </summary>
/// <param name="tutorialStep"> The latest successfully completed tutorial step </param>
DevToDev.Analytics.Tutorial(int tutorialStep);
```

{% endtab %}

{% tab title="Mac OS" %}

```objectivec
/**
* The event allowing to track the stage of tutorial a player is on.
* @param NSUInteger tutorialStep - the latest successfully completed tutorial step.
*/
[DevToDev tutorialCompleted: (NSUInteger) tutorialStep];
```

{% endtab %}

{% tab title="Adobe Air" %}

```javascript
/**
* The event allowing to track the stage of tutorial a player is on.
* @param tutorialStep - the latest successfully completed tutorial step.
*/
DevToDev.tutorialCompleted(tutorialStep:int);
```

{% endtab %}

{% tab title="UE4" %}
**Blueprint**

![](https://blobscdn.gitbook.com/v0/b/gitbook-28427.appspot.com/o/assets%2F-LnBolWcwPO33iga2rY2%2F-LnTASe7tY_8XGfgeRsv%2F-LnTAVQIcZXYkBhcsAJX%2F142-basicmethods-0.png?generation=1567095664522623\&alt=media)

| Field | Type  | Description                                     |
| ----- | ----- | ----------------------------------------------- |
| Step  | int32 | The latest successfully completed tutorial step |

**Code**

```
// The event allowing to track the stage of tutorial a player is on.
// int32 step - the latest successfully completed tutorial step.

UDevToDevBlueprintFunctionLibrary::TutorialCompleted(int32 step);
```

{% endtab %}
{% endtabs %}

## **Leveling up**

This event is for games only.

You can analyze the distribution of the players over the levels. The event should be sent right after the player reached the next level. You can find more information on what is the right moment to use LevelUp event [here](https://docs.devtodev.com/expert-tips/what-to-track#if-users-in-your-project-become-more-experienced-and-raise-their-level).

{% tabs %}
{% tab title="iOS" %}

```objectivec
/**
* Player has reached a new level
* @param NSInteger level - level reached by the player.
*/
[DevToDev levelUp: (NSInteger) level];
```

{% endtab %}

{% tab title="Android" %}

```java
/**
* Player has reached a new level
* @param int level - level reached by the player.
*/
DevToDev.levelUp(int level);
```

{% endtab %}

{% tab title="Windows 8.1 and 10" %}

```csharp
/**
* <param name="level"> Level reached by the player </param>
*/
DevToDev.SDK.Level(int level);
```

{% endtab %}

{% tab title="Web" %}

```javascript
/**
* Player has reached a new level
* @param {number} level - level reached by the player.
*/

devtodev.levelUp(level);
```

{% endtab %}

{% tab title="Unity" %}

```csharp
/// <summary> Player has reached a new level </summary>
/// <param name="level"> Level reached by the player </param>
DevToDev.Analytics.LevelUp(int level);
```

{% endtab %}

{% tab title="Mac OS" %}

```objectivec
/**
* Player has reached a new level
* @param NSUInteger level - level reached by the player.
*/
[DevToDev levelUp: (NSUInteger) level];
```

{% endtab %}

{% tab title="Adobe Air" %}

```javascript
/**
* Player has reached a new level
* @param level - level reached by the player.
*/
DevToDev.levelUp(level:int);
```

{% endtab %}

{% tab title="UE4" %}

### Blueprint

![](https://2105883905-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnGcP_ZeRJ1ipj9O8dF%2F-LnlShMa3E6SgK1lXtjO%2F-LnlSi7nFoLb80mawRaA%2F142-basicmethods-1.png?generation=1567419258559855\&alt=media)

| Field | Type  | Description                 |
| ----- | ----- | --------------------------- |
| Level | int32 | level reached by the player |

**Code**

```cpp
// Player has reached a new level
// int32 level - level reached by the player.

UDevToDevBlueprintFunctionLibrary::LevelUp(int32 level);
```

{% endtab %}
{% endtabs %}

To track the average account balance of in-game currency by the end of each level, please provide the list of currency names and amounts.

{% tabs %}
{% tab title="iOS" %}

```objectivec
/**
* Player has reached a new level
* @param NSInteger level - level reached by the player.
* @param NSDictionary resources - dictionary with the currency names and amounts
*/
NSDictionary * resources = @{@"Currency name 1" : @100, @"Currency name 2" : @10};
[DevToDev levelUp: (NSUInteger) level withResources: withResources: (NSDictionary *) resources];
```

{% endtab %}

{% tab title="Android" %}

```java
/**
* @param int level - level reached by the player
* @param HashMap resources - hashmap with the currency names and amounts
*/
HashMap resources = new HashMap<String, Integer>();
resources.put("Currency name 1", 1000);
resources.put("Currency name 2", 10);
DevToDev.levelUp(level, resources);
```

{% endtab %}

{% tab title="Windows 8.1 and 10" %}

```csharp
/**
* <param name="level"> Player level </param>
* <param name="resources">Dictionary with the currency names and amounts</param>
*/
Dictionary<string, int> resources = new Dictionary<string, int>();
resources.Add("Currency name 1", 1000);
resources.Add("Currency name 2", 10);
DevToDev.SDK.Level(level, resources);
```

{% endtab %}

{% tab title="Web" %}

```javascript
/**
* @param {number} level - player/character's "level"
* @param {Object} resources - Object with data about currencies. Optional.
* @param {Object[]} resources.balance -  Account balance of in-game currency by the end of level. * Optional.
* @param {Object[]} resources.balance[].currency - Game currency name
* @param {Object[]} resources.balance[].amount - Game currency amount
* @param {Object[]} resources.earned - Game currency earned during the level. Optional. 
* @param {Object[]} resources.earned[].currency - Game currency name
* @param {Object[]} resources.earned[].amount - Game currency amount
* @param {Object[]} resources.spent - Game currency amount spent during the level. Optional.
* @param {Object[]} resources.spent[].currency - Game currency name
* @param {Object[]} resources.spent[].amount - Game currency amount
* @param {Object[]} resources.bought - Game currency amount bought during the level. Optional.
* @param {Object[]} resources.bought[].currency - Game currency name
* @param {Object[]} resources.bought[].amount - Game currency amount 
*/

devtodev.levelUp(level, resources);
```

{% endtab %}

{% tab title="Unity" %}

```csharp
/// <summary> Player has reached a new level</summary>
/// <param name="level"> Player level </param>
/// <param name="resources"> Dictionary with the currency names and amounts </param>
/// <example>
/// 
///    Dictionary<string, int> resources = new Dictionary<string, int>();
///    resources.Add("Currency name 1", 1000);
///    resources.Add("Currency name 2", 10);
/// 
/// </example>
DevToDev.Analytics.LevelUp(level, resources);
```

{% endtab %}

{% tab title="Mac OS" %}

```objectivec
/**
* Player has reached a new level
* @param NSInteger level - level reached by the player.
* @param NSDictionary resources - dictionary with the currency names and amounts
*/
NSDictionary * resources = @{@"Currency name 1" : @100, @"Currency name 2" : @10};
[DevToDev levelUp: (NSUInteger) level withResources: withResources: (NSDictionary *) resources];
```

{% endtab %}

{% tab title="Adobe Air" %}

```javascript
/**
* Player has reached a new level
* @param level - level reached by the player.
* @param resources - dictionary with the currency names and amounts
*/
var resources: Dictionary = new Dictionary();
resources["Currency name 1"] = 1000;
resources["Currency name 2"] = 10;
DevToDev.levelUpWithResources(level:int, resources:Dictionary);
```

{% endtab %}

{% tab title="UE4" %}
**Blueprint**

![](https://2105883905-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnGcP_ZeRJ1ipj9O8dF%2F-LnlShMa3E6SgK1lXtjO%2F-LnlSi7yLjdnsXuFgGba%2F142-basicmethods-2.png?generation=1567419252980127\&alt=media)

| Field | Type  | Description                 |
| ----- | ----- | --------------------------- |
| Level | int32 | level reached by the player |

```cpp
// Player has reached a new level
// int32 level - level reached by the player.
// TArray<FAnalyticsEventAttr> Attributes - dictionary with the currency names and amounts

UDevToDevBlueprintFunctionLibrary::LevelUpWithAttributes(int32 level,
                                                         const TArray<FAnalyticsEventAttr>& Attributes);
```

{% endtab %}
{% endtabs %}

To track the average amount of in-game currency earned during a level, it is necessary to send a special event after each time an in-game account is replenished.

{% tabs %}
{% tab title="iOS" %}

```objectivec
/* *
* @param NSString * currencyName - currency name (max. 24 symbols)
* @param NSInteger amount - the amount an account has been credited with.
* @param AccrualType accrualType - the way the currency was obtained: earned or purchased
*/
[DevToDev currencyAccrual: (NSInteger) amount withCurrencyName: (nonnull NSString *) currencyName
 andCurrencyType: (AccrualType) accrualType];
```

{% endtab %}

{% tab title="Android" %}

```java
/**
* @param String currencyName - currency name (max. 24 symbols)
* @param float currencyAmount - the amount an account has been credited with
* @param AccrualType accrualType - the way the currency was obtained: earned or purchased
*/
DevToDev.currencyAccrual(currencyName, currencyAmount, accrualType);
```

{% endtab %}

{% tab title="Windows 8.1 and 10" %}

```csharp
/**
* <param name="currencyName">Currency name (max. 24 symbols)</param>
* <param name="currencyAmount ">The amount an account has been credited with</param>
* <param name="accrualType">The way the currency was obtained: earned or purchased</param>
*/
DevToDev.SDK.CurrencyAccrual(string currencyName, float currencyAmount, AccrualType accrualType);
```

{% endtab %}

{% tab title="Web" %}

{% endtab %}

{% tab title="Unity" %}

```csharp
/// <param name="currencyName"> Currency name (max. 24 symbols) </param>
/// <param name="currencyAmount "> The amount an account has been credited with </param>
/// <param name="accrualType"> The way the currency was obtained: earned or purchased </param>
DevToDev.Analytics.CurrencyAccrual(int amount, string currencyName, AccrualType accrualType);
```

{% endtab %}

{% tab title="Mac OS" %}

```objectivec
/**
* @param NSString * currencyName - currency name (max. 24 symbols)
* @param float amount - the amount an account has been credited with.
* @param AccrualType accrualType - the way the currency was obtained: earned or purchased
*/
/* *
* @param NSString * currencyName - currency name (max. 24 symbols)
* @param NSInteger amount - the amount an account has been credited with.
* @param AccrualType accrualType - the way the currency was obtained: earned or purchased
*/
[DevToDev currencyAccrual: (NSInteger) amount withCurrencyName: (nonnull NSString *) currencyName
 andCurrencyType: (AccrualType) accrualType];
```

{% endtab %}

{% tab title="Adobe Air" %}

```javascript
/**
* @param currencyName - currency name (max. 24 symbols)
* @param currencyAmount - the amount an account has been credited with
* @param accrualType - the way the currency was obtained: earned or purchased
*/
DevToDev.currencyAccrual(currencyName:String, currencyAmount:Number, accrualType:AccrualType);
```

{% endtab %}

{% tab title="UE4" %}

### Blueprint

![](https://2105883905-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnGcP_ZeRJ1ipj9O8dF%2F-LnlShMa3E6SgK1lXtjO%2F-LnlSi88D1on0dEqfmNi%2F142-basicmethods-3.png?generation=1567419253628332\&alt=media)

| Field                | **Type** | **Description**                                           |
| -------------------- | -------- | --------------------------------------------------------- |
| Game Currency Type   | FString  | Currency name (max. 24 symbols)                           |
| Game Currency Amount | int32    | The amount an account has been credited with.             |
| accrualType          | Enum     | Can take one of following values: "Earned" or "Purchased" |

Code

```cpp
FAnalytics::Get().GetDefaultConfiguredProvider()->RecordCurrencyGiven(const FString& GameCurrencyType,
                                                   int GameCurrencyAmount,
                                                   const TArray<FAnalyticsEventAttribute>& EventAttrs);
```

{% endtab %}
{% endtabs %}

AccrualType can take one of the following values:

{% tabs %}
{% tab title="iOS" %}

```objectivec
typedef enum {
Earned,
Purchased
} AccrualType ;
```

{% endtab %}

{% tab title="Android" %}

```java
public enum AccrualType {
                          Earned,
                          Purchased
                        };
```

{% endtab %}

{% tab title="Windows 8.1 and 10" %}

```csharp
public enum AccrualType {
                          Earned,
                          Purchased
};
```

{% endtab %}

{% tab title="Web" %}

{% endtab %}

{% tab title="Unity" %}

```csharp
public enum AccrualType {
    Earned,
    Purchased
};
```

{% endtab %}

{% tab title="Mac OS" %}

```objectivec
typedef enum {
              Earned,
              Purchased
} AccrualType;
```

{% endtab %}

{% tab title="Adobe Air" %}

```java
AccrualType.EARNED;
AccrualType.PURCHASED;
```

{% endtab %}

{% tab title="UE4" %}

{% endtab %}
{% endtabs %}

## Real-World Currency Payment

To track payments, add this event right after the platform confirms that a payment went through.

{% tabs %}
{% tab title="iOS" %}

```objectivec
/**
* Register transactions made through the platform's payment system.
*
* @param NSString * paymentId - transaction ID  (max. 64 symbols)
* @param float inAppPrice - product price (in user's currency)
* @param NSString * inAppName - product name
* @param NSString * inAppCurrencyISOCode - transaction currency (ISO 4217 format)
*/
[DevToDev realPayment: (NSString *) transactionId withInAppPrice:(float) inAppPrice 
andInAppName: (NSString *) inAppName andInAppCurrencyISOCode: (NSString *) inAppCurrencyISOCode];
```

A unique order identifier is a value of a *transactionIdentifier* property in SKPaymentTransaction object inside the receipt of completed transaction.

{% hint style="warning" %}
devtodev server does not process transactions with previously used transaction IDs. Also, the server validates identifiers in appearance to avoid evident cheat transactions.\
To avoid adding cheat payments into reports completely, use devtodev anti-cheat service before creating a realPayment even&#x74;*.*
{% endhint %}
{% endtab %}

{% tab title="Android" %}

```java
/**
* Register transactions made through the platform's payment system.
*
* @param String paymentId - transaction ID (max. 64 symbols)
* @param float inAppPrice - product price (in user's currency)
* @param String inAppName - product name
* @param String inAppCurrencyISOCode - transaction currency 
* (ISO 4217 format http://www.iso.org/iso/home/standards/currency_codes.htm Exapmle: "USD")
*/
DevToDev.realPayment(String paymentId, float inAppPrice, String inAppName, 
                     String inAppCurrencyISOCode);
```

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.

{% hint style="warning" %}
devtodev server does not process transactions with previously used transaction IDs. Also, the server validates the identifiers in appearance to avoid evident cheat transactions. To avoid completely the entering of cheat payments from GooglePlay in reports, use devtodev anticheat service before creating realPayment event.&#x20;
{% endhint %}
{% endtab %}

{% tab title="Windows 8.1 and 10" %}

```csharp
/**
* Register transactions made through the platform's payment system.
*  <param name="orderId"> Transaction id </param>
*  <param name="price"> Product price (in user's currency) </param>
*  <param name="productId"> Product id (product name) </param>
*  <param name="currencyCode"> Transaction currency (ISO 4217 format)</param>
*/
DevToDev.SDK.RealPayment(string orderId, float price, string productId, string currencyCode)
```

Example:

```csharp
DevToDev.SDK.RealPayment("1836535032137741465" , 2.99f , "productId" , "USD" );
```

{% endtab %}

{% tab title="Web" %}

```javascript
/**
* Register transactions made through the platform's payment system.
*
* @param {string} transactionId - transaction ID
* @param {number} productPrice - product price (in user's currency)
* @param {string} productName - product name
* @param {string} transactionCurrencyISOCode - transaction currency (ISO 4217 format)
*/

devtodev.realPayment(transactionId, productPrice, productName, transactionCurrencyISOCode);
```

Example:

```javascript
devtodev.realPayment("12345", 9.99, "Currency pack 2", "USD");
```

{% endtab %}

{% tab title="Unity" %}

```csharp
/// <summary> Register transactions made through the platform's payment system. </summary>
/// <param name="paymentId"> Transaction id </param>
/// <param name="inAppPrice"> Product price (in user's currency) </param>
/// <param name="inAppName"> Product id (product name) </param>
/// <param name="inAppCurrencyISOCode"> Transaction currency (ISO 4217 format)</param>
DevToDev.Analytics.RealPayment(string paymentId, float inAppPrice, string inAppName,
                               string inAppCurrencyISOCode);
```

{% endtab %}

{% tab title="Mac OS" %}

```objectivec
/**
* Register transactions made through the platform's payment system.
*
* @param NSString * paymentId - transaction ID
* @param float inAppPrice - product price (in user's currency)
* @param NSString * inAppName - product name
* @param NSString * inAppCurrencyISOCode - transaction currency (ISO 4217 format)
*/
[DevToDev realPayment: (NSString *) transactionId withInAppPrice:(float) inAppPrice 
         andInAppName: (NSString *) inAppName andInAppCurrencyISOCode: (NSString *) inAppCurrencyISOCode];
```

{% endtab %}

{% tab title="Adobe Air" %}

```javascript
/**
* Register transactions made through the platform's payment system.
* @param paymentId - transaction ID
* @param inAppPrice - product price (in user's currency)
* @param inAppName - product name
* @param inAppCurrencyISOCode - transaction currency (ISO 4217 format)
*/
DevToDev.realPayment(paymentId:String, inAppPrice:Number, inAppName:String,
                     inAppCurrencyISOCode:String);
```

**How to find the transaction ID in iTunes transaction?**

Unique order identifier is a value of "transactionIdentifier" property in SKPaymentTransaction object inside the receipt of completed transaction.

**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.

{% hint style="warning" %}
devtodev server does not process transactions with previously used transaction IDs. Also the server validates the identifiers in appearance, to avoid evident cheat transactions. To avoid the entering of cheat payments in reports completely, use devtodev anticheat service before creating realPayment event.&#x20;
{% endhint %}
{% endtab %}

{% tab title="UE4" %}
**Blueprint**

![](https://2105883905-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnGcP_ZeRJ1ipj9O8dF%2F-LnlShMa3E6SgK1lXtjO%2F-LnlSi8d2kr26vtPAC08%2F142-basicmethods-4.png?generation=1567419258948929\&alt=media)

| **Field**               | **type** | **Description**                        |
| ----------------------- | -------- | -------------------------------------- |
| Transaction Id          | FString  | Unique transaction ID                  |
| In  AppPrice            | float    | Product price (in user's currency)     |
| In App Name             | FString  | Product name                           |
| In App Currency ISOCode | FString  | Transaction currency (ISO 4217 format) |

Code

```cpp
// Register transactions made through the platform's payment system.
// FString transactionId - transaction ID
// float inAppPrice - product price (in user's currency)
// FString inAppName - product name
// FString inAppCurrencyISOCode - transaction currency (ISO 4217 format)

UDevToDevBlueprintFunctionLibrary::RealPayment(const FString& transactionId,
                                               float inAppPrice,
                                               const FString& inAppName,
                                               const FString& inAppCurrencyISOCode);
```

{% endtab %}
{% endtabs %}

## Virtual Currency Payment

This event is for games only.

To track expenditures of in-game currency and popularity of products, add this event right after the purchase.

{% tabs %}
{% tab title="iOS" %}

```objectivec
/**
* In-app purchase with a definite article ID.
*
* @param NSString purchaseId - unique purchase Id or name (max. 32 symbols)
* @param NSString purchaseType - purchase type or group (max. 96 symbols)
* @param NSInteger purchaseAmount - count of purchased goods
* @param NSInteger purchasePrice - cost of purchased goods (total cost -if several goods were purchased)
* @param NSString purchaseCurrency - currency name (max. 24 symbols)
*/
[DevToDev inAppPurchase: (NSString *) purchaseId withPurchaseType: (NSString *) purchaseType 
andPurchaseAmount: (NSInteger) purchase Amount andPurchasePrice: (NSInteger) purchaseprice 
andPurchaseCurrency: (NSString *) purchaseCurrency];
```

In case a product is bought for several game currencies at once, it is necessary to make a dictionary that includes the names and amounts of the paid currencies.

```objectivec
NSMutableDictionary * resources = [[NSMutableDictionary alloc] init];
[resources setObject:@100 forKey:@"currency1"];
[resources setObject:@10 forKey:@"currency2"];
//...and so on...

[DevToDev inAppPurchase:(NSString )purchaseId withPurchaseType:(NSString )purchaseType
 andPurchaseAmount:(NSInteger)purchaseAmount andResources: (NSDictionary *) resources];
```

{% endtab %}

{% tab title="Android" %}

```java
/**
* In-app purchase with a definite article ID.
*
* @param purchaseId - unique purchase Id or name (max. 32 symbols)
* @param purchaseType - purchase type or group (max. 96 symbols)
* @param purchaseAmount - count of purchased goods
* @param purchasePrice - cost of purchased goods (total cost - if several goods were purchased)
* @param purchaseCurrency - currency name (max. 24 symbols)
*/
DevToDev.inAppPurchase(String purchaseId, String purchaseType, int purchaseAmount, 
                       int purchasePrice, String purchaseCurrency);
```

In case a product was bought for several game currencies at once, it is necessary to make a hashmap that includes the names and amounts of the paid currencies.

```java
HashMap resources = new HashMap();
resources.put("currency_1", 120);
resources.put("currency_2", 29);
```

…and so on…

```java
DevToDev.inAppPurchase(String purchaseId, String purchaseType, int purchaseAmount, HashMap resources);
```

{% endtab %}

{% tab title="Windows 8.1 and 10" %}

```csharp
/**
* <param name="purchaseId"> Unique purchase ID or name (max. 32 symbols)</param>
* <param name="purchaseType"> Purchase type or group (max. 96 symbols)</param>
* <param name="purchaseAmount"> Number of purchased goods </param>
* <param name="purchasePrice"> Cost of purchased goods (total cost - if several goods were purchased)</param>
* <param name="purchasePriceCurrency"> Currency name (max. 24 symbols)</param>
*/
DevToDev.SDK.InAppPurchase(string purchaseId, string purchaseType, int purchaseAmount,
                           int purchasePrice, string purchasePriceCurrency)
```

Example:

```csharp
DevToDev.SDK.InAppPurchase("sword", "weapons", 1, 200, "coins");
```

In case a product was bought for several game currencies at once, it is necessary to make a hashmap including the names and amounts of the paid currencies.

```csharp
Dictionary<string, int> resources = new Dictionary<string, int>();
resources.Add("currency_1", 120);
resources.Add("currency_2", 29);
//...and so on...

DevToDev.SDK.InAppPurchase(string purchaseId, string purchaseType, int purchaseAmount, 
                           Dictionary<string, int> resources);
```

{% endtab %}

{% tab title="Web" %}

```javascript
/**
* Tracks in-app purchases.
*
* @param {string} purchaseId - unique purchase Id or name (max. 32 symbols)
* @param {string} purchaseType - purchase type or group (max. 96 symbols)
* @param {number} purchaseAmount - count of purchased goods
* @param {Object[]} purchasePrice - array including the names and amounts of
* the paid currencies (total cost - if several goods were purchased)
* @param {string} purchasePrice[].currency - game currency name
* @param {number} purchasePrice[].amount - currency amount
*/

devtodev.inAppPurchase(purchaseId, purchaseType, purchaseAmount, purchasePrice);
```

Example:

```javascript
var purchasePrice = [
    {
        “currency” : "coins", //game currency name
        “amount” : 1000 //game currency amount 
    },
    {
        “currency” : "gold", //game currency name
        “amount” : 10 //game currency amount
    }
];

devtodev.inAppPurchase(“cloak”, “clothes”, 1, purchasePrice);
```

{% endtab %}

{% tab title="Unity" %}

```csharp
/// <summary> In-app purchase with a definite ID. </summary>
/// <param name="purchaseId"> Unique purchase ID  or name (max. 32 symbols)</param>
/// <param name="purchaseType"> Purchase type or group (max. 96 symbols)</param>
/// <param name="purchaseAmount"> Number of purchased goods </param>
/// <param name="purchasePrice"> Cost of purchased goods (total cost - if several goods were purchased)</param>
/// <param name="purchasePriceCurrency"> Currency name (max. 24 symbols)</param>
DevToDev.Analytics.InAppPurchase(string purchaseId, string purchaseType, int purchaseAmount,
                                 int purchasePrice, string purchaseCurrency);
```

In case a product was bought for several game currencies at once, it is necessary to make a dictionary including the names and amounts of the paid currencies.

```csharp
Dictionary<string, int> resources = new Dictionary<string, int>();
resources.Add("currency_1", 120);
resources.Add("currency_2", 29);
//...and so on...

DevToDev.Analytics.InAppPurchase(string purchaseId, string purchaseType, int purchaseAmount,
                                 Dictionary<string, int> resources);
```

{% endtab %}

{% tab title="Mac OS" %}

```objectivec
/**
* In-app purchase with a definite article ID.
*
* @param purchaseId - unique purchase Id or name (max. 32 symbols)
* @param purchaseType - purchase type or group (max. 96 symbols)
* @param purchaseAmount - count of purchased goods
* @param purchasePrice - cost of purchased goods (total cost -if several goods were purchased)
* @param purchaseCurrency - currency name (max. 24 symbols)
*/
[DevToDev inAppPurchase: (NSString *) purchaseId withPurchaseType: (NSString *) purchaseType
      andPurchaseAmount: (NSInteger) purchase Amount andPurchasePrice: (NSInteger) purchaseprice 
    andPurchaseCurrency: (NSString *) purchaseCurrency];
```

In case a product was bought for several game currencies at once, it is necessary to make a dictionary including the names and amounts of the paid currencies.

```objectivec
NSMutableDictionary * resources = [[NSMutableDictionary alloc] init];
[resources setObject:@100 forKey:@"currency1"];
[resources setObject:@10 forKey:@"currency2"];
//...and so on...

[DevToDev inAppPurchase:(NSString )purchaseId withPurchaseType:(NSString )purchaseType 
      andPurchaseAmount:(NSInteger)purchaseAmount andResources: (NSDictionary *) resources];
```

{% endtab %}

{% tab title="Adobe Air" %}

```javascript
/**
* In-app purchase with a definite article ID.
* @param purchaseId - unique purchase Id or name (max. 32 symbols)
* @param purchaseType - purchase type or group (max. 96 symbols)
* @param purchaseAmount - count of purchased goods
* @param purchasePrice - cost of purchased goods (total cost - if several goods were purchased)
* @param purchaseCurrency - currency name (max. 24 symbols)
*/
DevToDev.inAppPurchase(purchaseId:String, purchaseType:String, purchaseAmount:int, purchasePrice:int,
                       purchaseCurrency:String);
```

In case a product was bought for several game currencies at once, it is necessary to make a hashmap including the names and amounts of the paid currencies.

```javascript
var resources: Dictionary = new Dictionary();
resources["currency_1"] = 120;
resources["currency_2"] = 29;
//...and so on...

DevToDev.inAppPurchaseWithResources(purchaseId:String, purchaseType:String, purchaseAmount:int,
                                    resources:Dictionary);
```

{% endtab %}

{% tab title="UE4" %}
**Blueprint**

![](https://2105883905-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnGcP_ZeRJ1ipj9O8dF%2F-LnlShMa3E6SgK1lXtjO%2F-LnlSi9QC0ZIJXCM2D6i%2F142-basicmethods-5.png?generation=1567419254312249\&alt=media)

Notice! If the purchase is done by more than one currency, then the method should be called as many times as many currencies were used, but the amount of purchase should be set only in one of the times.

Use the method “Record Simple Item Purchase with Attributes” from Analytics Blueprint Library.

| **Field**     | **Type** | **Description**                              |
| ------------- | -------- | -------------------------------------------- |
| Item Id       | FString  | Unique purchase Id or name (max. 32 symbols) |
| Item Quantity | int32    | Count of purchased goods                     |

**Item Id** field is the identifier of purchased item, **Item Quantity** is the amount of purchased item. Attributes array should contain the following obligatory information:

| **Field**        | **Type** | **Description**                                                       |
| ---------------- | -------- | --------------------------------------------------------------------- |
| purchaseType     | FString  | Purchase type or group (max. 96 symbols)                              |
| purchasePrice    | int32    | Cost of purchased goods (total cost -if several goods were purchased) |
| purchaseCurrency | FString  | Currency name (max. 24 symbols)                                       |

Code

```cpp
// In-app purchase with a definite article ID.
// FString ItemId - unique purchase Id or name (max. 32 symbols)
// int32 ItemQuantity - count of purchased goods
//
// FString purchaseType - purchase type or group (max. 96 symbols)
// int32 purchasePrice - cost of purchased goods (total cost -if several goods were purchased)
// FString purchaseCurrency - currency name (max. 24 symbols)

FAnalytics::Get().GetDefaultConfiguredProvider()->RecordItemPurchase(const FString& ItemId,
                                                   int ItemQuantity,
                                                   const TArray<FAnalyticsEventAttribute>& Attributes);
```

{% endtab %}
{% endtabs %}

{% hint style="warning" %}
Please keep in mind that there is a limit for the number of unique values of the "purchaseCurrency" parameter - 30 currencies per project. Currencies cannot be deleted or renamed.
{% endhint %}

## **Custom Events**

If you want to count the events that are not among basic, use custom events.

{% hint style="warning" %}
Attention! We strongly recommend that you do not use custom event properties to transfer and store data that fits the definition of [personal data](https://gdpr-info.eu/issues/personal-data/)!
{% endhint %}

The event must have a unique name and can include up to 20 parameters. The maximum length of the event name is 72 symbols.

Every parameter inside one event must have a unique name. The maximum length of the parameter name is 32 symbols.

The values of parameters can be string or number type (int, long, float, double). The maximum length of the parameter value is 255 symbols.

{% hint style="warning" %}
No more than 300 variants of custom event names can be used for one project. Try to enlarge events in meaning by using event parameters. Events that didn't get into the limit of unique event names will be discarded.&#x20;
{% endhint %}

For a string parameter, it is acceptable to use not more than 50,000 unique values for the whole event history. In case the limit of unique values is exceeded, the parameter is ignored.

Therefore, we recommend not to set user IDs and Unix time as parameter values of custom events. Try to integrate parameter values if they have a very large variability. Otherwise, it will be very difficult to analyze the data or after some time it may be even ignored.

We strongly recommend not to change the type of data transferred in the parameter over time. In case you change the data type in parameter, it will be duplicated with the same name and different data types in devtodev database which will result in more complicated report building.

{% tabs %}
{% tab title="iOS" %}

```objectivec
/**
* @param NSString eventName - event name
*/
[DevToDev customEvent: (NSString *) eventName];
```

20 parameter names may be associated with any event:

```objectivec
CustomEventParams * params_1 = [[CustomEventParams alloc] init];
[params_1 putParam:@"double" withDouble:123.1231231231231];
[params_1 putParam:@"float" withFloat:123.123123f];
[params_1 putParam:@"int" withInt:123];
[params_1 putParam:@"long" withLong:6152437L];
[param_1 putParam:@"string" withString:@"string"];
```

Then use method:

```objectivec
/**
* @param NSString eventName - event name
* @param CustomEventParams params - event parameters
*/
[DevToDev customEvent: (NSString *) eventName withParams: (CustomEventParams *) params];
```

{% endtab %}

{% tab title="Android" %}

```java
/**
* Simple custom event
* @param String eventName - event name
*/
DevToDev.customEvent(eventName);
```

20 parameter names may be associated with any event:

```java
CustomEventParams params = new CustomEventParams();
params.putDouble("double", 1.12);
params.putFloat("float", 9.99f);
params.putInteger("int", 145);
params.putLong("long", 123L);
params.putString("string","start");
```

Then use method:

```java
/**
* Custom event with params
* @param String eventName - event name
* @param CustomEventParams params - event parameters
*/
DevToDev.customEvent(eventName, params);
```

{% endtab %}

{% tab title="Windows 8.1 and 10" %}

```csharp
/**
* <param name="eventName"> Event name </param>
*/
DevToDev.SDK.CustomEvent(string eventName);
```

Example:

```csharp
DevToDev.SDK.CustomEvent("bonus_used");
```

20 parameter names may be associated with any event:

```csharp
/**
* <param name="eventName">Event name</param>
* <param name="eventParams">Event parameters</param>
*/
DevToDev.SDK.CustomEvent(string eventName, CustomEventParams eventParams)
```

Example:

```csharp
var cep = new CustomEventParams();
cep.AddParam("bonus_name", "your_awesome_bonus");
DevToDev.SDK.CustomEvent("bonus_used", cep);
```

{% endtab %}

{% tab title="Web" %}

```javascript
/**
* Tracks custom events.
* @param {string} eventName - event name
**/

devtodev.customEvent(eventName);
```

20 parameter names may be associated with any event:

Then use method:

```javascript
/**
* Tracks custom events.
* @param {string} eventName - event name (max. 72 symbols)
* @param {Object[]} params - array of event parameters. Up to 20 params.
* @param {string} params[].name - parameter name (max. 32 symbols)
* @param {string} params[].type - parameter value type. Can be "double" or "string".
* @param {string|number} params[].value - parameter value. (max. 255 symbols)
**/

devtodev.customEvent(eventName, params);
```

Example:

```javascript
var params = [
    {
        "name": "score",
        "type": "double",
        "value": 100500,
    },
    {
        "name": "type",
        "type": "string",
        "value": "fatality",
    },
    … //up to 10 parameters.
];

devtodev.customEvent("win", params);
```

{% endtab %}

{% tab title="Unity" %}

```csharp
/// <param name="eventName"> Event name </param>
DevToDev.Analytics.CustomEvent(string eventName);
```

20 parameter names may be associated with any event:

```csharp
DevToDev.CustomEventParams customEventParams = new DevToDev.CustomEventParams();
customEventParams.AddParam("double", 1.12);
customEventParams.AddParam("int", 145);
customEventParams.AddParam("long", 123L);
customEventParams.AddParam("string","start");
```

Then use method:

```csharp
/// <param name="eventName">Event name</param>
/// <param name="eventParams">Event parameters</param>
DevToDev.Analytics.CustomEvent(string eventName, DevToDev.CustomEventParams eventParams);
```

{% endtab %}

{% tab title="Mac OS" %}

```objectivec
/**
* @param String eventName - event name
*/
[DevToDev customEvent: (NSString *) eventName];
```

20 parameter names may be associated with any event:

```objectivec
CustomEventParams * params_1 = [[CustomEventParams alloc] init];
[params_1 putParam:@"date" withDate:[NSDate date]];
[params_1 putParam:@"double" withDouble:123.1231231231231];
[params_1 putParam:@"float" withFloat:123.123123f];
[params_1 putParam:@"int" withInt:123];
[params_1 putParam:@"long" withLong:6152437L];
[param_1 putParam:@"string" withString:@"string"];
```

Then use method:

```objectivec
/**
* @param String eventName - event name
* @param CustomEventParams params - event parameters
*/
[DevToDev customEvent: (NSString *) eventName withParams: (CustomEventParams *) params];
```

{% endtab %}

{% tab title="Adobe Air" %}

```javascript
/**
* Simple custom event
* @param String eventName - event name
*/
DevToDev.customEvent(eventName:String);
```

20 parameter names may be associated with any event:

```javascript
var params:CustomEventParams = new CustomEventParams();
/**
* String type custom event parameter
* @param paramName - parameter name
* @param value - parameter value
*/
params.putString(paramName:String , value:String);
//Integer type custom event parameter
params.putInt(paramName:String, 145:int);
//Number type custom event parameter
params.putFloat(paramName:String, 9.99:Number);
```

Then use method:

```javascript
/**
* Custom event with params
* @param eventName - event name
* @param params - event parameters
*/
DevToDev.customEventsWithParams(eventName:String, params:CustomEventParams);
```

{% endtab %}

{% tab title="UE4" %}
![](https://2105883905-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnGcP_ZeRJ1ipj9O8dF%2F-LnlShMa3E6SgK1lXtjO%2F-LnlSiAP3Dij5ICprOkV%2F142-basicmethods-6.png?generation=1567419255818350\&alt=media)

| Field      | **Type** | **Description**   |
| ---------- | -------- | ----------------- |
| Event Name | FString  | Custom event name |

20 parameter names may be associated with any event. Use "Record Event With Attributes".

![](https://2105883905-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnGcP_ZeRJ1ipj9O8dF%2F-LnlShMa3E6SgK1lXtjO%2F-LnlSiAU0NsgTfXN1xnV%2F142-basicmethods-7.png?generation=1567419258564084\&alt=media)

**Code**

```
FAnalytics::Get().GetDefaultConfiguredProvider()->RecordEvent(const FString& EventName,
                                                 const TArray<FAnalyticsEventAttribute>& Attributes);
```

{% endtab %}
{% endtabs %}

## Progression event

This event is for games only.

First of all, a Progression event is used for games with short (within one game session) locations/game levels. The event allows you to gather data on passing the locations and get statistics on parameters that vary during the location passing.

Developer must use the following two methods:

{% tabs %}
{% tab title="iOS" %}

1. Method startProgressionEvent when entering the location:

   ```objectivec
   /**
   * The method have to be used when entering the location.
   * @param String locationName - the name of location user entered.
   * @param LocationEventParams params - instance of location parameters class
   */
   [DevToDev startProgressionEvent: locationName withParameters: params];
   ```
2. Method endProgressionEvent when exiting (no matter if completed or not) the location:

   ```objectivec
   /**
   * The method have to be used when the location passing is over.
   * @param String locationName - the name of location user left.
   * @param LocationEventParams params - instance of location parameters class
   */
   [DevToDev endProgressionEvent: locationName withParameters: params];
   ```

   LocationEventParams class methods:

   ```objectivec
     /**
     * Location level of difficulty (optional).
     * @param NSInteger difficultyLevel - level of difficulty
     */
     [params setDifficulty: difficultyLevel];

     /**
     * Previously visited location (optional).
     * @param NSString* locationName -  previously visited location name
     */
     [params setSource: locationName];

     /**
     * State/result of the location passing (required).
     * @param BOOL isCompleted -  true if location is successfuly passed
     */
     [params setIsSuccess: isCompleted];

     /**
     * Time spent in the location (optional).
     * In case the parameter is not specified by the developer, it will be automatically calculated
     * as the date difference between startProgressionEvent and endProgressionEvent method calls.
     * @param NSNumber* duration - time in seconds
     */
     [params setDuration: duration];

     /**
     * User spendings  within the location passing (optional).
     * @ param NSDictionary* spent - user spendings. Key length max. 24 symbols.
     */
     [params setSpent: spent];

     /**
     * User earnings  within the location passing (optional).
     * @param NSDictionary* earned - user earnings. Key length max. 24 symbols.
     */
     [params setEarned: earned];
   ```

{% hint style="warning" %}
The user can be only in one location at the same time. When moving to another location (including embedded), the previous location must be completed. Information on locations, the passing of which was not completed by calling endProgressionEvent method during the game session (the call of endProgressionEvent method is not integrated; user unloaded the application from the device memory; there was an application crash), do not fall in the statistics.&#x20;
{% endhint %}

Let’s look at the example of event integration for a match3 game with a location map:

```objectivec
// Player comes to the third location on the map "Village" while following the game map. 
// Create a parameters object
LocationEventParams* params = [[LocationEventParams alloc] init];

// Specify the known location parameters:
// Passing on the first level of difficulty.
[params setDifficulty:1];

// Before entering this location gamer passed the third location on the map â&#128;&#156;Villageâ&#128;&#157; (optional).
[params setSource: @"Vilage step 02"];

//The location passing starts (required).
[DevToDev startProgressionEvent:@"Vilage step 03" withParameters:params];

// ... Player passing the location.

// Player finishes passing of the third location on the map â&#128;&#156;Villageâ&#128;&#157;

// The location is passed successfully (required).
[params setIsSuccess: YES];

// The passing took 189 seconds.
[params setDuration:@189];

// Location is passed for 54 turns. While the passing gamer used boost and bought extra 5 turns.
NSDictionary* spent = @{
    @"Turns" : @54,
    @"Boost Bomb" : @1,
    @"Extra 5 Turns" : @1
};
[params setSpent: spent];

// Gamer finished the passing with 3 stars and gained 5 coins and 1200 score.
NSDictionary* earned = @{
    @"Stars" : @3,
    @"Score" : @1200,
    @"Coins" : @5
};
[params setEarned: earned]; 

// The location passing is over (required).
[DevToDev endProgressionEvent: @"Vilage step 03" withParameters: params];
```

{% endtab %}

{% tab title="Android" %}

1. Method startProgressionEvent when enetring the location

   ```java
   /**
   * The method have to be used when entering the location.
   * @param String locationName - the name of location user entered.
   * @param LocationEventParams params - instance of location parameters class
   */
   DevToDev.startProgressionEvent(locationName, params);
   ```
2. Method endProgressionEvent when exiting (no matter if completed or not) the location

   ```java
   /**
   * The method have to be used when the location passing is over.
   * @param String locationName - the name of location user left.
   * @param LocationEventParams params - instance of location parameters class
   */
   DevToDev.endProgressionEvent(locationName, params);
   ```

   LocationEventParams class methods:

   ```java
   /**
     * Location level of difficulty (optional).
     * @param int difficultyLevel - level of difficulty
     */
     setDifficulty(difficultyLevel);

     /**
     * Previously visited location (optional).
     * @param String locationName -  previously visited location name
     */
     setSource(locationName);

     /**
     * State/result of the location passing (required).
     * @param boolean isCompleted -  true if location is successfuly passed
     */
     setSuccessfulCompletion(isCompleted);

     /**
     * Time spent in the location (optional).
     * In case the parameter is not specified by the developer, it will be automatically calculated
     * as the date difference between startProgressionEvent and endProgressionEvent method calls.
     * @param int duration - time in seconds
     */
     setDuration(duration);

     /**
     * User spendings within the location passing (optional).
     * @ param HashMap<String, Number> spent - user spendings. Key length max. 24 symbols.
     */
     setSpent(spent);

     /**
     * User earnings within the location passing (optional).
     * @param HashMap<String, Number> earned - user earnings. Key length max. 24 symbols.
     */
     setEarned(earned);
   ```

{% hint style="warning" %}
The user can be only in one location at the same time. When moving to another location (including embedded), the previous location must be completed. Information on locations, the passing of which was not completed by calling endProgressionEvent method during the game session (the call of endProgressionEvent method is not integrated; user unloaded the application from the device memory; there was an application crash) do not fall in the statistics.&#x20;
{% endhint %}

Let’s analyse the example of event integration on match3 game with location map:

```java
// Player comes to the third location on the map "Village" while following the game map. 
// Create a parameters object
LocationEventParams params = new LocationEventParams();

// Specify the known location parameters:
// Passing on the first level of difficulty.
params.setDifficulty(1);

// Before entering this location gamer passed the third location on the map “Village” (optional).
params.setSource("Vilage step 02");

//The location passing starts (required).
DevToDev.startProgressionEvent("Vilage step 03", params);

// ... Player passing the location.

// Player finishes passing of the third location on the map “Village”

// The location is passed successfully (required).
params.setSuccessfulCompletion(true);

// The passing took 189 seconds.
params.setDuration(189);

// Location is passed for 54 turns. While the passing gamer used boost and bought extra 5 turns.
HashMap<String, Number> spent = new HashMap<String, Number>();
spent.put("Turns", 54);
spent.put("Boost Bomb", 1);
spent.put("Extra 5 Turns", 1);
params.setSpent(spent);

// Gamer finished the passing with 3 stars and gained 5 coins and 1200 score.
HashMap<String, Number> earned = new HashMap<String, Number>();
earned.put("Stars", 3);
earned.put("Score", 1200 );
earned.put("Coins", 5);
params.setEarned(earned); 

// The location passing is over (required).
DevToDev.endProgressionEvent("Vilage step 03", params);
```

{% endtab %}

{% tab title="Windows 8.1 and 10" %}

1. Method StartProgressionEvent when enetring the location

   ```csharp
   /**
   * <param name="locationName">The name of location user entered</param>
   * <param name="locationParams">Instance of location parameters class</param>
   */
   DevToDev.SDK.StartProgressionEvent(string locationName, LocationEventParams locationParams);
   ```
2. Method EndProgressionEvent when exiting (no matter if completed or not) the location

   ```csharp
   /**
   * <param name="locationName">The name of location user entered</param>
   * <param name="locationParams">Instance of location parameters class</param>
   */
   DevToDev.SDK.EndProgressionEvent(string locationName, LocationEventParams locationParams);
   ```

   LocationEventParams class methods:

   ```csharp
     /**
     * Location level of difficulty (optional).
     * <param name="difficultyLevel">Level of difficulty</param>
     */
     SetDifficulty(int difficultyLevel);

     /**
     * Previously visited location (optional).
     * <param name="locationName">Previously visited location name</param>
     */
     SetSource(string locationName);

     /**
     * State/result of the location passing (required).
     * <param name="isCompleted">True if location is successfuly passed</param>
     */
     SetSuccessfulCompletion(bool isCompleted);

     /**
     * Time spent in the location (optional).
     * In case the parameter is not specified by the developer, it will be automatically calculated
     * as the date difference between StartProgressionEvent and EndProgressionEvent method calls.
     * <param name="duration">Time in seconds</param>
     */
     SetDuration(long duration);

     /**
     * User spendings within the location passing (optional). Key (currency name) length max. 24 symbols.
     * <param name="spent">User spendings</param>
     */
     SetSpent(Dictionary<string, int> spent);

     /**
     * User earnings within the location passing (optional). Key (currency name) length max. 24 symbols.
     * <param name="earned">User earnings</param>
     */
     SetEarned(Dictionary<string, int> earned);
   ```

{% hint style="warning" %}
The user can be only in one location at the same time. When moving to another location (including embedded), the previous location must be completed. Information on locations, the passing of which was not completed by calling EndProgressionEvent method during the game session (the call of EndProgressionEvent method is not integrated; user unloaded the application from the device memory; there was an application crash) do not fall in the statistics.&#x20;
{% endhint %}

Let’s analyse the example of event integration on match3 game with location map:

```csharp
// Player comes to the third location on the map "Village" while following the game map. 
// Create a parameters object
LocationEventParams locationParams = new LocationEventParams();

// Specify the known location parameters:
// Passing on the first level of difficulty.
locationParams.SetDifficulty(1);

// Before entering this location gamer passed the third location on the map “Village” (optional).
locationParams.SetSource("Vilage step 02");

//The location passing starts (required).
DevToDev.SDK.StartProgressionEvent("Vilage step 03", locationParams);

// ... Player passing the location.

// Player finishes passing of the third location on the map “Village”
LocationEventParams locationParams = new LocationEventParams();

// The location is passed successfully (required).
locationParams.SetSuccessfulCompletion(true);

// The passing took 189 seconds.
locationParams.SetDuration(189);

// Location is passed for 54 turns. While the passing gamer used boost and bought extra 5 turns.
Dictionary<string, int> spent = new Dictionary<string, int>();
spent["Turns"] = 54;
spent["Boost Bomb"] = 1;
spent["Extra 5 Turns"] = 1;
locationParams.SetSpent(spent);

// Gamer finished the passing with 3 stars and gained 5 coins and 1200 score.
Dictionary<string, int> earned = new Dictionary<string, int>();
earned["Stars"] = 3;
earned["Score"] = 1200;
earned["Coins"] = 5;
locationParams.SetEarned(earned); 

// The location passing is over (required).
DevToDev.SDK.EndProgressionEvent("Vilage step 03", locationParams);
```

{% endtab %}

{% tab title="Web" %}

1. Method startProgressionEvent when enetring the location

   ```javascript
   /**
   * The method have to be used when entering the location.
   * @param {string} locationName - the name of location user entered.
   * @param {Object} startParams - location parameters object
   */
   devtodev.startProgressionEvent(locationName, startParams);
   ```
2. Method endProgressionEvent when exiting (no matter if completed or not) the location

   ```javascript
   /**
   * The method have to be used when the location passing is over.
   * @param {string} locationName - the name of location user left.
   * @param {Object} endParams - location parameters object
   */
   devtodev.endProgressionEvent(locationName, endParams);
   ```

   Location parameters object contains:

   ```javascript
     var params = {
         // Previously visited location (optional).
         "source" : "locationSource",

         // Location level of difficulty (optional).
         "difficulty" : 1,

         // Time spent in the location (optional).
         // In case the parameter is not specified by the developer, it will be automatically calculated
         // as the date difference between startProgressionEvent and endProgressionEvent method calls.
         "duration" : 80,

         // State/result of the location passing (required).
         "success" : true,

         //User spendings within the location passing (optional).
         "spent" : [
             {
                 "currency": "currency 1 name", // Currency name length max. 24 symbols.
                 "amount": 1   // objects with amount value less than 1 are ignored
             },
             {
                 "currency": "currency 2 name",
                 "amount": 2
             }
         ],

         // User earnings within the location passing (optional).
         "earned" : [
             {
                 "currency": "currency 1 name",
                 "amount": 1 // objects with amount value less than 1 are ignored
             },
             {
                 "currency": "currency 2 name",
                 "amount": 2
             }
         ]
     };
   ```

{% hint style="warning" %}
The user can be only in one location at the same time. When moving to another location (including embedded), the previous location must be completed. Information on locations, the passing of which was not completed by calling endProgressionEvent method during the game session (the call of endProgressionEvent method is not integrated; user unloaded the application from the device memory; there was an application crash) do not fall in the statistics.&#x20;
{% endhint %}

Let’s analyse the example of event integration on match3 game with location map:

```javascript
// Player comes to the third location on the map "Village" while following the game map. 
// Create a parameters object
var params = {};

// Specify the known location parameters:
// Passing on the first level of difficulty.
params["difficulty"] = 1;

// Before entering this location gamer passed the third location on the map “Village” (optional).
params["source"] = "Vilage step 02";

//The location passing starts (required).
devtodev.startProgressionEvent("Vilage step 03", params);

// ... Player passing the location.

// Player finishes passing of the third location on the map “Village”

// The location is passed successfully (required).
params["success"] = true;

// The passing took 189 seconds.
params["duration"] = 189;

// Location is passed for 54 turns. While the passing gamer used boost and bought extra 5 turns.
params["spent"] = [
    {
        "currency": "Turns",
        "amount": 54
    },
    {
        "currency": "Boost Bomb",
        "amount": 1
    },
    {
        "currency": "Extra 5 Turns",
        "amount": 1
    }
];

// Gamer finished the passing with 3 stars and gained 5 coins and 1200 score.
params["earned"] = [
    {
        "currency": "Stars",
        "amount": 3
    },
    {
        "currency": "Score",
        "amount": 1200
    },
    {
        "currency": "Coins",
        "amount": 5
    }
];

// The location passing is over (required).
devtodev.endProgressionEvent("Vilage step 03", params);
```

{% endtab %}

{% tab title="Unity" %}

1. Method StartProgressionEvent when enetring the location

   ```csharp
   /// <param name="eventId"> The name of location user entered </param>
   /// <param name="eventParams"> Instance of progression parameters class </param>
   DevToDev.Analytics.StartProgressionEvent(string eventId, ProgressionEventParams eventParams);
   ```
2. Method EndProgressionEvent when exiting (no matter if completed or not) the location

   ```csharp
   /// <param name="eventId"> The name of location user left </param>
   /// <param name="eventParams"> Instance of progression parameters class </param>
   DevToDev.Analytics.EndProgressionEvent(string eventId, ProgressionEventParams eventParams);
   ```

   ProgressionEventParams class methods:

   ```csharp
     /// <summary> Location level of difficulty (optional). </summary>
     /// <param name="difficultyLevel"> Level of difficulty </param>
     SetDifficulty(int difficultyLevel);

     /// <summary> Previously visited location (optional). </summary>
     /// <param name="locationName"> Previously visited location name </param>
     SetSource(string locationName);

     /// <summary> State/result of the location passing (required). </summary>
     /// <param name="isCompleted"> True if location is successfuly passed </param>
     SetSuccessfulCompletion(bool isCompleted);

     /// <summary>Time spent in the location (optional).
     /// <para>In case the parameter is not specified by the developer, it will be automatically calculated
     /// as the date difference between StartProgressionEvent and EndProgressionEvent method calls.</para>
     /// </summary>
     /// <param name="duration"> Time in seconds </param>
     SetDuration(long duration);

     /// <summary> User spendings within the location passing (optional). Dictionary key max.length is 24 symbols.</summary>
     /// <param name="spent"> User spendings </param>
     SetSpent(Dictionary<string, int> spent);

     /// <summary> User earnings within the location passing (optional). </summary>
     /// <param name="earned"> User earnings </param>
     SetEarned(Dictionary<string, int> earned);
   ```

{% hint style="warning" %}
The user can be only in one location at the same time. When moving to another location (including embedded), the previous location must be completed. Information on locations, the passing of which was not completed by calling EndProgressionEvent method during the game session (the call of EndProgressionEvent method is not integrated; user unloaded the application from the device memory; there was an application crash) do not fall in the statistics.&#x20;
{% endhint %}

Let’s analyse the example of event integration on match3 game with location map:

```csharp
// Player comes to the third location on the map "Village" while following the game map. 
// Create a parameters object
ProgressionEventParams locationParams = new ProgressionEventParams();

// Specify the known location parameters:
// Passing on the first level of difficulty.
locationParams.SetDifficulty(1);

// Before entering this location gamer passed the third location on the map “Village” (optional).
locationParams.SetSource("Vilage step 02");

//The location passing starts (required).
DevToDev.Analytics.StartProgressionEvent("Vilage step 03", locationParams);

// ... Player passing the location.

// Player finishes passing of the third location on the map “Village”
// Create a parameters object
ProgressionEventParams locationParams = new ProgressionEventParams();

// The location is passed successfully (required).
locationParams.SetSuccessfulCompletion(true);

// The passing took 189 seconds.
locationParams.SetDuration(189);

// Location is passed for 54 turns. While the passing gamer used boost and bought extra 5 turns.
Dictionary<string, int> spent = new Dictionary<string, int>();
spent["Turns"] = 54;
spent["Boost Bomb"] = 1;
spent["Extra 5 Turns"] = 1;
locationParams.SetSpent(spent);

// Gamer finished the passing with 3 stars and gained 5 coins and 1200 score.
Dictionary<string, int> earned = new Dictionary<string, int>();
earned["Stars"] = 3;
earned["Score"] = 1200;
earned["Coins"] = 5;
locationParams.SetEarned(earned); 

// The location passing is over (required).
DevToDev.Analytics.EndProgressionEvent("Vilage step 03", locationParams);
```

{% endtab %}

{% tab title="Mac OS" %}

1. Method startProgressionEvent when enetring the location

   ```objectivec
   /**
   * The method have to be used when entering the location.
   * @param String locationName - the name of location user entered.
   * @param LocationEventParams params - instance of location parameters class
   */
   [DevToDev startProgressionEvent: locationName withParameters: params];
   ```
2. Method endProgressionEvent when exiting (no matter if completed or not) the location

   ```objectivec
   /**
   * The method have to be used when the location passing is over.
   * @param String locationName - the name of location user left.
   * @param LocationEventParams params - instance of location parameters class
   */
   [DevToDev endProgressionEvent: locationName withParameters: params];
   ```

   LocationEventParams class methods:

   ```objectivec
   /**
     * Location level of difficulty (optional).
     * @param NSInteger difficultyLevel - level of difficulty
     */
     [params setDifficulty: difficultyLevel];

     /**
     * Previously visited location (optional).
     * @param NSString* locationName -  previously visited location name
     */
     [params setSource: locationName];

     /**
     * State/result of the location passing (required).
     * @param BOOL isCompleted -  true if location is successfuly passed
     */
     [params setIsSuccess: isCompleted];

     /**
     * Time spent in the location (optional).
     * In case the parameter is not specified by the developer, it will be automatically calculated
     * as the date difference between startProgressionEvent and endProgressionEvent method calls.
     * @param NSNumber* duration - time in seconds
     */
     [params setDuration: duration];

     /**
     * User spendings  within the location passing (optional).
     * @ param NSDictionary* spent - user spendings. Key max.length is 24 symbols.
     */
     [params setSpent: spent];

     /**
     * User earnings  within the location passing (optional).
     * @param NSDictionary* earned - user earnings.  Key max.length is 24 symbols.
     */
     [params setEarned: earned];
   ```

{% hint style="warning" %}
The user can be only in one location at the same time. When moving to another location (including embedded), the previous location must be completed. Information on locations, the passing of which was not completed by calling endProgressionEvent method during the game session (the call of endProgressionEvent method is not integrated; user unloaded the application from the device memory; there was an application crash) do not fall in the statistics.&#x20;
{% endhint %}

Let’s analyse the example of event integration on match3 game with location map:

```objectivec
// Player comes to the third location on the map "Village" while following the game map. 
// Create a parameters object
LocationEventParams* params = [[LocationEventParams alloc] init];

// Specify the known location parameters:
// Passing on the first level of difficulty.
[params setDifficulty:1];

// Before entering this location gamer passed the third location on the map “Village” (optional).
[params setSource: @"Vilage step 02"];

//The location passing starts (required).
[DevToDev startProgressionEvent:@"Vilage step 03" withParameters:params];

// ... Player passing the location.

// Player finishes passing of the third location on the map “Village”

// The location is passed successfully (required).
[params setIsSuccess: YES];

// The passing took 189 seconds.
[params setDuration:@189];

// Location is passed for 54 turns. While the passing gamer used boost and bought extra 5 turns.
NSDictionary* spent = @{
    @"Turns" : @54,
    @"Boost Bomb" : @1,
    @"Extra 5 Turns" : @1
};
[params setSpent: spent];

// Gamer finished the passing with 3 stars and gained 5 coins and 1200 score.
NSDictionary* earned = @{
    @"Stars" : @3,
    @"Score" : @1200,
    @"Coins" : @5
};
[params setEarned: earned]; 

// The location passing is over (required).
[DevToDev endProgressionEvent: @"Vilage step 03" withParameters: params];
```

{% endtab %}

{% tab title="Adobe Air" %}

1. Method *StartProgressionEvent* when enetring the location

   ```javascript
   /**
   * The method have to be used when entering the location.
   * @param locationName - the name of location user entered.
   * @param params - instance of location parameters class
   */
   DevToDev.StartProgressionEvent(locationName:String, params:LocationEventParams);
   ```
2. Method *EndProgressionEvent* when exiting (no matter if completed or not) the location

   ```javascript
   /**
   * The method have to be used when the location passing is over.
   * @param locationName - the name of location user left.
   * @param params - instance of location parameters class
   */
   DevToDev.EndProgressionEvent(locationName:String, params:LocationEventParams);
   ```

   *LocationEventParams* class methods:

   ```javascript
     /**
     * Location level of difficulty (optional).
     * @param difficultyLevel - level of difficulty
     */
     SetDifficulty(difficultyLevel:int);

     /**
     * Previously visited location (optional).
     * @param locationName -  previously visited location name
     */
     SetSource(locationName:String);

     /**
     * State/result of the location passing (required).
     * @param isCompleted -  true if location is successfuly passed
     */
     SetSuccessfulCompletion(isCompleted:Boolean);

     /**
     * Time spent in the location (optional).
     * In case the parameter is not specified by the developer, it will be automatically calculated
     * as the date difference between StartProgressionEvent and EndProgressionEvent method calls.
     * @param duration - time in seconds
     */
     SetDuration(duration:int);

     /**
     * User spendings within the location passing (optional).
     * @ param spent - user spendings. Key max.length is 24 symbols.
     */
     SetSpent(spent:Dictionary);

     /**
     * User earnings within the location passing (optional).
     * @param earned - user earnings. Key max.length is 24 symbols.
     */
     SetEarned(earned:Dictionary);
   ```

{% hint style="warning" %}
The user can be only in one location at the same time. When moving to another location (including embedded), the previous location must be completed. Information on locations, the passing of which was not completed by calling EndProgressionEvent method during the game session (the call of EndProgressionEvent method is not integrated; user unloaded the application from the device memory; there was an application crash) do not fall in the statistics.&#x20;
{% endhint %}

Let’s analyse the example of event integration on match3 game with location map:

```javascript
// Player comes to the third location on the map "Village" while following the game map. 
// Create a parameters object
var params:LocationEventParams = new LocationEventParams();

// Specify the known location parameters:
// Passing on the first level of difficulty.
params.SetDifficulty(1);

// Before entering this location gamer passed the third location on the map “Village” (optional).
params.SetSource("Vilage step 02");

//The location passing starts (required).
DevToDev.StartProgressionEvent("Vilage step 03", params);

// ... Player passing the location.

// Player finishes passing of the third location on the map “Village”
var params:LocationEventParams = new LocationEventParams();

// The location is passed successfully (required).
params.SetSuccessfulCompletion(true);

// The passing took 189 seconds.
params.SetDuration(189);

// Location is passed for 54 turns. While the passing gamer used boost and bought extra 5 turns.
var spent:Dictionary = new Dictionary();
spent["Turns"] = 54;
spent["Boost Bomb"] = 1;
spent["Extra 5 Turns"] = 1;
params.SetSpent(spent);

// Gamer finished the passing with 3 stars and gained 5 coins and 1200 score.
var earned:Dictionary = new Dictionary();
earned["Stars"] = 3;
earned["Score"] = 1200;
earned["Coins"] = 5;
params.SetEarned(earned); 

// The location passing is over (required).
DevToDev.EndProgressionEvent("Vilage step 03", params);
```

{% endtab %}

{% tab title="UE4" %}

1. Method StartProgressionEvent when enetring the location

   **Blueprint**\
   ![](https://2105883905-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnGcP_ZeRJ1ipj9O8dF%2F-LnlShMa3E6SgK1lXtjO%2F-LnlSiCcCcs5hJ2SNgbP%2F142-basicmethods-8.png?generation=1567419258161433\&alt=media)

   | Field        | Type                         | Description                       |
   | ------------ | ---------------------------- | --------------------------------- |
   | locationName | FString                      | The name of location user entered |
   | Attributes   | TArray\<FAnalyticsEventAttr> | Location parameters               |

   **Code**

   ```cpp
   // The method have to be used when entering the location.
   // FString locationName  - the name of location user entered.
   // TArray<FAnalyticsEventAttr> Attributes - location parameters
   UDevToDevBlueprintFunctionLibrary::StartProgressionEvent(const FString& locationName,
                                                            const TArray<FAnalyticsEventAttr>& Attributes);
   ```
2. Method EndProgressionEvent when exiting (no matter if completed or not) the location**Blueprint**

   ![](https://2105883905-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnGcP_ZeRJ1ipj9O8dF%2F-LnlShMa3E6SgK1lXtjO%2F-LnlSiChfoNzrTZU-LWT%2F142-basicmethods-9.png?generation=1567419254862628\&alt=media)

   | Field        | Type                         | Description                                                                           |
   | ------------ | ---------------------------- | ------------------------------------------------------------------------------------- |
   | locationName | FString                      | The name of location user left                                                        |
   | Attributes   | TArray\<FAnalyticsEventAttr> | Location parameters                                                                   |
   | Earned       | TArray\<FAnalyticsEventAttr> | User earnings within the location passing (optional). Key max. length is 24 symbols.  |
   | Spent        | TArray\<FAnalyticsEventAttr> | User spendings within the location passing (optional). Key max. length is 24 symbols. |

   Location parameters

   | Key        | Type    | Description                                                                                                                                                                                                                        |
   | ---------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
   | success    | bool    | State/result of the location passing (required).                                                                                                                                                                                   |
   | source     | FString | Previously visited location (optional).                                                                                                                                                                                            |
   | difficulty | int32   | Location level of difficulty (optional).                                                                                                                                                                                           |
   | duration   | int32   | Time spent in the location (optional). In case the parameter is not specified by the developer, it will be automatically сalculated as the date difference between Start Progression Event and End Progression Event method calls. |

   **Code**

   ```cpp
   // The method have to be used when the location passing is over.
   // FString locationName  - the name of location user left.
   // TArray<FAnalyticsEventAttr> Attributes - location parameters
   // TArray<FAnalyticsEventAttr> Earned - user earnings within the location passing (optional)
   // TArray<FAnalyticsEventAttr> Spent - user spendings within the location passing (optional).
   UDevToDevBlueprintFunctionLibrary::EndProgressionEvent(const FString& locationName,
                                                          const TArray<FAnalyticsEventAttr>& Attributes,
                                                          const TArray<FAnalyticsEventAttr>& Earned,
                                                          const TArray<FAnalyticsEventAttr>& Spent);
   ```

{% hint style="warning" %}
The user can be only in one location at the same time. When moving to another location (including embedded), the previous location must be completed. Information on locations, the passing of which was not completed by calling endProgressionEvent method during the game session (the call of endProgressionEvent method is not integrated; user unloaded the application from the device memory; there was an application crash) do not fall in the statistics.&#x20;
{% endhint %}

**Let’s analyse the example of event integration on match3 game with location map:**

Player comes to the third location on the map “Village” while following the game map. Passing on the first level of difficulty. Before entering this location gamer passed the third location on the map “City”. *.. Player passing the location.* Player finishes passing of the third location on the map “Village”. The location is passed successfully. The passing took 389 seconds. Gamer finished the passing with 3 stars and gained 70 coins. While the passing gamer used boost and bought extra 5 turns.![](https://blobscdn.gitbook.com/v0/b/gitbook-28427.appspot.com/o/assets%2F-LnBolWcwPO33iga2rY2%2F-LnTASe7tY_8XGfgeRsv%2F-LnTAVQpI5nBbFhOLA7I%2F142-basicmethods-10.png?generation=1567095661652472\&alt=media)[  <br>](https://took.gitbook.io/1234/integration/ue4/analytics-integration)
{% endtab %}
{% endtabs %}
