# 3. Send in-game event data

To enable optimal ad display and model training, it is crucial to send sufficient in-game event and player attribute data to Airflux. This guide details the core principles and implementation steps for data collection using the Airflux SDK.

<figure><img src="/files/zol4mAdTLCVez07be1F6" alt=""><figcaption></figcaption></figure>

***

## Understanding Data Collection

Airflux collects data through three primary methods to make the most optimal ad display decisions.

{% hint style="success" %}
Each type of data is collected at a different **time** and for a different **purpose**, so you must provide **all three** to maximize the performance of the AI model.
{% endhint %}

1. In-game event data

   Records user actions such as `ORDER_COMPLETED` and `ACHIEVE_LEVEL`.
2. Player Attribute Data

   Records the player's current status, such as their `level` or `currency` balance.
3. Inference Parameters

   Records contextual information at the time of an ad request, such as `adType` or `adPlacementId`.

***

## 1. Send in-game event data

Use the `Airflux.trackEvent()` function to record key player actions within your game. The collected event data plays a crucial role in enabling the Airflux AI model to learn player behavior patterns and make optimal decisions.

### Detailed Event Guide with Code Examples

The following events are essential for model training. Clearly understand the purpose and timing of collecting each event, and ensure proper implementation for data transmission.

<details>

<summary>Ad Impression</summary>

Track this event immediately after an in-app ad is shown to the user. Collect relevant data such as ad type, revenue, and placement details.

{% hint style="danger" %}
The in-app ad revenue data must be collected using the client-side SDK through mediation platform integrations and sent to Airflux.
{% endhint %}

<table><thead><tr><th>Name</th><th width="235.9296875">Description</th><th>Required</th><th>Sample Value</th></tr></thead><tbody><tr><td><code>value</code></td><td>The amount of ad revenue.</td><td><strong>Required</strong></td><td><code>1.99</code></td></tr><tr><td><code>currency</code></td><td>The currency code for the ad revenue (ISO 4217).</td><td><strong>Required</strong></td><td><code>“USD”</code></td></tr><tr><td><code>adType</code></td><td>The type of ad. You <strong>must</strong> use one of the pre-defined strings from the list below.<br>• <code>"interstitial_ad"</code><br>• <code>"rewarded_ad"</code><br>• <code>“other”</code></td><td><strong>Required</strong></td><td><code>“interstitial_ad”</code></td></tr><tr><td><code>adPlacementID</code></td><td>A unique identifier for the ad placement.</td><td><strong>Required</strong></td><td><code>“placement_3”</code></td></tr><tr><td><code>adPlacementType</code></td><td>The type of ad placement. You <strong>must</strong> use one of the pre-defined strings from the list below.<br>• <code>"static"</code><br>• <code>"dynamic"</code></td><td><strong>Required</strong></td><td><code>“static”</code></td></tr><tr><td><code>adPlacementPosition</code></td><td>The position of the ad placement within the game. You <strong>must</strong> use one of the pre-defined strings from the list below<br>• <code>"stage_start"</code><br>• <code>"stage_middle"</code><br>• <code>"stage_end"</code><br>• <code>"non_stage"</code></td><td>Nullable (if the placement is dynamic)</td><td><code>“stage_start”</code></td></tr><tr><td><code>level</code></td><td>The player's or character's current level.</td><td>Nullable<br>(only if no level system)</td><td><code>10</code></td></tr><tr><td><code>stage</code></td><td>The stage number the user has played. If not in a game, this should be the last known result.</td><td>Nullable (if the game has no stages)</td><td><code>10</code></td></tr><tr><td><code>stageType</code></td><td>The type of stage where the user has played. If not in a game, this should be the last known result. You <strong>must</strong> use one of the pre-defined strings from the list below.<br>• <code>"primary_stage"</code><br>• <code>"secondary_stage"</code><br>• <code>"extra_stage"</code></td><td>Nullable (if the game has no stages)</td><td><code>"primary_stage"</code></td></tr><tr><td><code>totalFinishedStage</code></td><td>The total number of stages a player has finished. For games without stages, this should be the total play count.</td><td>Nullable (if the information is not available)</td><td><code>10</code></td></tr><tr><td><code>stageResult</code></td><td>The result of the most recently completed stage.If the ad placement occurs at the end of a stage or game, this should reflect the result of that stage. If the placement is in the middle of a stage/game or the user is not currently in gameplay, provide the result of the last finished stage.<br>You <strong>must</strong> use one of the pre-defined strings from the list below.<br>• <code>"success"</code><br>• <code>"fail"</code><br>• <code>"giveup"</code><br>• <code>"retry"</code><br>• <code>"draw"</code><br>• <code>"exhausted"</code></td><td>Nullable (if the game has no stages)</td><td><code>"success"</code><br></td></tr><tr><td><code>adCooldownSeconds</code></td><td>When a cooldown is applied to an ad placement, this key-value map shows the trigger and duration of the cooldown. The key is omitted when no cooldown is applied.<br>• <code>interstitial_ad</code> : Cooldown calculated from the last interstitial ad<br>• <code>rewarded_ad</code> : Cooldown calculated from the last rewarded ad.<br>• <code>app_open</code> : Cooldown calculated from the app open event<br>• <code>install</code> : Cooldown calculated from the app install event.<br>• <code>other</code> : Cooldown calculated from other events<br>Example: If <code>{"rewarded_ad": 120}</code> is included, it means a 2-minute cooldown is applied from the last rewarded ad.</td><td>Nullable (if no cooldown is applied)</td><td><code>{"rewarded_ad":10,"interstitial_ad": 20}</code></td></tr><tr><td><code>rewardItems</code></td><td>A key-value map of items rewarded to the player. Only for rewarded ads; otherwise, <code>null</code>.</td><td>Nullable (if the ad has no rewards)</td><td><code>{"coin": 500, "gem": 10}</code></td></tr></tbody></table>

#### **Code Example**

{% code title="Android: Kotlin" overflow="wrap" %}

```kotlin
import ai.airflux.Airflux
import ai.airflux.common.AirfluxCategory
import ai.airflux.common.AirfluxAttribute

Airflux.trackEvent(
    category = AirfluxCategory.AD_IMPRESSION,
    semanticAttributes = mapOf(
        AirfluxAttribute.VALUE to 1.99,
        AirfluxAttribute.CURRENCY to "USD",
        AirfluxAttribute.AD_TYPE to "interstitial_ad",
        AirfluxAttribute.AD_PLACEMENT_ID to "placement_3",
        AirfluxAttribute.AD_PLACEMENT_TYPE to "static",
        AirfluxAttribute.AD_PLACEMENT_POSITION to "stage_start",
        AirfluxAttribute.LEVEL to 10,
        AirfluxAttribute.STAGE_TYPE to "primary_stage",
        AirfluxAttribute.STAGE to 10,
        AirfluxAttribute.TOTAL_FINISHED_STAGE to 10,
        AirfluxAttribute.STAGE_RESULT to "success",
        AirfluxAttribute.AD_COOLDOWN_SECONDS to mapOf(
            "rewarded_ad" to 10,
            "interstitial_ad" to 20
        ),
        AirfluxAttribute.REWARD_ITEMS to mapOf(
            "coin" to 500,
            "gem" to 10
        )
    )
)
```

{% endcode %}

{% code title="Android: Java" %}

```java
import ai.airflux.Airflux;
import ai.airflux.common.AirfluxCategory;
import ai.airflux.common.AirfluxAttribute;

Airflux.trackEvent(
    AirfluxCategory.AD_IMPRESSION,
    new HashMap<String, Object>() {{
        put(AirfluxAttribute.VALUE, 1.99);
        put(AirfluxAttribute.CURRENCY, "USD");
        put(AirfluxAttribute.AD_TYPE, "interstitial_ad");
        put(AirfluxAttribute.AD_PLACEMENT_ID, "placement_3");
        put(AirfluxAttribute.AD_PLACEMENT_TYPE, "static");
        put(AirfluxAttribute.AD_PLACEMENT_POSITION, "stage_start");
        put(AirfluxAttribute.LEVEL, 10);
        put(AirfluxAttribute.STAGE_TYPE, "primary_stage");
        put(AirfluxAttribute.STAGE, 10);
        put(AirfluxAttribute.TOTAL_FINISHED_STAGE, 10);
        put(AirfluxAttribute.STAGE_RESULT, "success");
        put(AirfluxAttribute.AD_COOLDOWN_SECONDS, new HashMap<String, Integer>() {{
            put("rewarded_ad", 10);
            put("interstitial_ad", 20);
        }});
        put(AirfluxAttribute.REWARD_ITEMS, new HashMap<String, Integer>() {{
            put("coin", 500);
            put("gem", 10);
        }});
    }}
);
```

{% endcode %}

</details>

<details>

<summary>Order Completed</summary>

Track this event when an in-app purchase is completed. Collect data such as transaction ID, purchase amount, currency, and product information.

{% hint style="danger" %}
The in-app purchase revenue data must be collected using the client-side SDK and sent to Airflux. There might be a slight gap between the data sent to Airflux and the revenue data provided by vendors.
{% endhint %}

| Name                      | Description                                                                                                                                                             | Required     | Sample Value              |
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | ------------------------- |
| `transactionID`           | A unique identifier for the transaction.                                                                                                                                | **Required** | `TXN-20250411-5F3C9A72B1` |
| `value`                   | The purchase amount.                                                                                                                                                    | **Required** | `1.99`                    |
| `currency`                | The currency code for the purchase amount.                                                                                                                              | **Required** | `"USD"`                   |
| `products`                | A list of the purchased products.                                                                                                                                       | **Required** | `[]`                      |
| `products[X].productID`   | The unique identifier of the purchased product.                                                                                                                         | **Required** | `1C569KY32P1`             |
| `products[X].productName` | The name of the purchased product.                                                                                                                                      | **Required** | `"welcome_pack"`          |
| `purchaseRoute`           | <p>The purchase path. You must use one of the pre-defined strings from the list below.<br>• <code>"shop"</code><br>• <code>"popup"</code><br>• <code>"other"</code></p> | **Required** | `"shop"`                  |
| `inAppPurchased`          | The status of in-app purchases                                                                                                                                          | **Required** | `True`                    |

#### **Code Example**

{% code title="Android: Kotlin" %}

```kotlin
import ai.airflux.Airflux
import ai.airflux.common.AirfluxCategory
import ai.airflux.common.AirfluxAttribute

Airflux.trackEvent(
    category = AirfluxCategory.ORDER_COMPLETED,
    semanticAttributes = mapOf(
        AirfluxAttribute.TRANSACTION_ID to "TXN-20250411-5F3C9A72B1",
        AirfluxAttribute.VALUE to 1.99,
        AirfluxAttribute.CURRENCY to "USD",
        AirfluxAttribute.PRODUCTS to listOf(
            mapOf(
                AirfluxAttribute.PRODUCT_ID to "1C569KY32P1",
                AirfluxAttribute.PRODUCT_NAME to "welcome_pack"
            )
        ),
        AirfluxAttribute.PURCHASE_ROUTE to "shop"
    )
)
```

{% endcode %}

{% code title="Android: Java" %}

```java
import ai.airflux.Airflux;
import ai.airflux.common.AirfluxCategory;
import ai.airflux.common.AirfluxAttribute;

Airflux.trackEvent(
    AirfluxCategory.ORDER_COMPLETED,
    new HashMap<String, Object>() {{
        put(AirfluxAttribute.TRANSACTION_ID, "TXN-20250411-5F3C9A72B1");
        put(AirfluxAttribute.VALUE, 1.99);
        put(AirfluxAttribute.CURRENCY, "USD");
        put(AirfluxAttribute.PRODUCTS, Arrays.asList(
            new HashMap<String, String>() {{
                put(AirfluxAttribute.PRODUCT_ID, "1C569KY32P1");
                put(AirfluxAttribute.PRODUCT_NAME, "welcome_pack");
            }}
        ));
        put(AirfluxAttribute.PURCHASE_ROUTE, "shop");
    }}
);
```

{% endcode %}

</details>

<details>

<summary>Start Stage</summary>

Track this event when a stage or a game session begins.

<table><thead><tr><th width="135.54296875">Name</th><th width="214.48828125">Description</th><th>Required</th><th>Sample Value</th></tr></thead><tbody><tr><td><code>stageType</code></td><td>The type of stage where the user has played.<br><br>You must use one of the pre-defined strings from the list below.<br>• <code>"primary_stage"</code><br>• <code>"secondary_stage"</code><br>• <code>"extra_stage"</code></td><td>Nullable (if the game has no stages)</td><td><code>"primary_stage"</code></td></tr><tr><td><code>stage</code></td><td>The stage number the user has played</td><td>Nullable (if the game has no stages)</td><td><code>10</code></td></tr></tbody></table>

#### **Code Example**

{% code title="Android: Kotlin" %}

```kotlin
import ai.airflux.Airflux
import ai.airflux.common.AirfluxCategory
import ai.airflux.common.AirfluxAttribute

Airflux.trackEvent(
    category = AirfluxCategory.START_STAGE,
    semanticAttributes = mapOf(
        AirfluxAttribute.STAGE_TYPE to "primary_stage",
        AirfluxAttribute.STAGE to 10
    )
)
```

{% endcode %}

{% code title="Android: Java" %}

```java
import ai.airflux.Airflux;
import ai.airflux.common.AirfluxCategory;
import ai.airflux.common.AirfluxAttribute;

Airflux.trackEvent(
    AirfluxCategory.START_STAGE,
    new HashMap<String, Object>() {{
        put(AirfluxAttribute.STAGE_TYPE, "primary_stage");
        put(AirfluxAttribute.STAGE, 10);
    }}
);
```

{% endcode %}

</details>

<details>

<summary>Finish Stage</summary>

Track this event when a stage or game ends.

<table><thead><tr><th>Name</th><th width="192.68359375">Description</th><th>Required</th><th>Sample Value</th></tr></thead><tbody><tr><td><code>stageType</code></td><td>The type of stage where the user has played.<br><br>You must use one of the pre-defined strings from the list below.<br>• <code>"primary_stage"</code><br>• <code>"secondary_stage"</code><br>• <code>"extra_stage"</code></td><td>Nullable (if the game has no stages)</td><td><code>"primary_stage"</code></td></tr><tr><td><code>stage</code></td><td>The stage number the user has played</td><td>Nullable (if the game has no stages)</td><td><code>10</code></td></tr><tr><td><code>totalFinishedStage</code></td><td>The total number of stages a player has finished.<br>For games without stages, this should be the total play count.</td><td>Nullable (if the game has no stages)</td><td><code>10</code></td></tr><tr><td><code>stageResult</code></td><td>The result of the most recently completed stage.<br>If the ad placement occurs at the end of a stage or game, this should reflect the result of that stage. If the placement is in the middle of a stage/game or the user is not currently in gameplay, provide the result of the last finished stage.<br>You must use one of the pre-defined strings from the list below.<br>• <code>"success"</code><br>• <code>"fail"</code><br>• <code>"giveup"</code><br>• <code>"retry"</code><br>• <code>"draw"</code><br>• <code>"exhausted"</code></td><td>Nullable (if the game has no stages)</td><td><code>"success"</code></td></tr></tbody></table>

#### Code Example

{% code title="Android: Kotlin" %}

```kotlin
import ai.airflux.Airflux
import ai.airflux.common.AirfluxCategory
import ai.airflux.common.AirfluxAttribute

Airflux.trackEvent(
    category = AirfluxCategory.FINISH_STAGE,
    semanticAttributes = mapOf(
        AirfluxAttribute.STAGE_TYPE to "primary_stage",
        AirfluxAttribute.STAGE to 10,
        AirfluxAttribute.TOTAL_FINISHED_STAGE to 10,
        AirfluxAttribute.STAGE_RESULT to "success"
    )
)
```

{% endcode %}

{% code title="Android: Java" %}

```java
import ai.airflux.Airflux;
import ai.airflux.common.AirfluxCategory;
import ai.airflux.common.AirfluxAttribute;

Airflux.trackEvent(
    AirfluxCategory.FINISH_STAGE,
    new HashMap<String, Object>() {{
        put(AirfluxAttribute.STAGE_TYPE, "primary_stage");
        put(AirfluxAttribute.STAGE, 10);
        put(AirfluxAttribute.TOTAL_FINISHED_STAGE, 10);
        put(AirfluxAttribute.STAGE_RESULT, "success");
    }}
);
```

{% endcode %}

</details>

<details>

<summary>Achieve Level</summary>

Track this event when a player's or character's level changes, including when it decreases. This event can be omitted for games without a level system.

| Name    | Description                                | Required                                     | Sample Value |
| ------- | ------------------------------------------ | -------------------------------------------- | ------------ |
| `level` | The player's or character's current level. | <p>Nullable<br>(only if no level system)</p> | `10`         |

#### **Code Example**

{% code title="Android: Kotlin" %}

```kotlin
import ai.airflux.Airflux
import ai.airflux.common.AirfluxCategory
import ai.airflux.common.AirfluxAttribute

Airflux.trackEvent(
    category = AirfluxCategory.ACHIEVE_LEVEL,
    semanticAttributes = mapOf(
        AirfluxAttribute.LEVEL to 10
    )
)
```

{% endcode %}

{% code title="Android: Java" %}

```java
import ai.airflux.Airflux;
import ai.airflux.common.AirfluxCategory;
import ai.airflux.common.AirfluxAttribute;

Airflux.trackEvent(
    AirfluxCategory.ACHIEVE_LEVEL,
    new HashMap<String, Object>() {{
        put(AirfluxAttribute.LEVEL, 10);
    }}
);
```

{% endcode %}

</details>

### Verification

<details>

<summary>Using the App Real-Time Log</summary>

Trigger events based on your test scenarios and check the corresponding logs in the \[Raw Data] > \[App Real-time Log] menu. The event data will be displayed in JSON format, allowing you to confirm that the data type and structure of each field match the predefined format.

<table data-header-hidden><thead><tr><th width="221.7890625">Field</th><th>Validation Criteria</th></tr></thead><tbody><tr><td>eventData.goal.category</td><td>Verify that the event name exactly matches the string defined in the taxonomy.</td></tr><tr><td>semanticAttributes</td><td>• All keys must match those defined in the taxonomy. <br>• Value types must match the defined types (string, number, boolean). <br>• For revenue events (ad_impression, order_completed), values must be positive numbers.</td></tr><tr><td>originalCurrency</td><td>Must be a 3-letter uppercase code defined by ISO-4217 (e.g., USD, KRW)</td></tr></tbody></table>

</details>

***

## 2. Send player attribute data

Player attribute data provides a crucial snapshot of a player's status at a given time. This data is used to fine-tune player segmentation and personalize ad experiences. There are two primary functions for sending this data: `Airflux.setUser()` and `Airflux.setContext()`.

{% hint style="warning" %}
Player attribute data is only transmitted to the server when an event is tracked or an inference API is called. Ensure this data is set before making any inference API requests.
{% endhint %}

### Send User ID

Send the player's unique User ID when they sign up or sign in. This ensures all subsequent events and attributes are properly linked to that user. The User ID must be sent before the event data.

<details>

<summary>Send User ID </summary>

#### **When to trigger**

* When a player signs up or signs in.

| Name | Description                 | Example                   |
| ---- | --------------------------- | ------------------------- |
| `ID` | The player’s unique User ID | `"your_internal_user_id"` |

{% hint style="danger" %}
If the User ID is not sent before the event data, the User ID cannot be linked to the event data.
{% endhint %}

#### **Code Examples**

{% code title="Android: Kotlin" %}

```kotlin
import ai.airflux.Airflux
import ai.airflux.common.AirfluxUser

// Call when a player signs in
Airflux.setUser(AirfluxUser.ID, "your_internal_user_id")
```

{% endcode %}

{% code title="Android: Java" %}

```java
import ai.airflux.Airflux;
import ai.airflux.common.AirfluxUser;

Airflux.setUser(AirfluxUser.ID, "your_internal_user_id");
```

{% endcode %}

</details>

### Send Contextual Data

`Airflux.setContext()` is used to pass player attributes that are not tied to a specific event. This is crucial for providing the AI model with a complete snapshot of the player's status, such as their current level or currency balance at app launch.

<details>

<summary>Level Attributes</summary>

#### **When to trigger**

* When the game app opens
* When the player logs in

| Name    | Description                                | Example | Skip Case                 |
| ------- | ------------------------------------------ | ------- | ------------------------- |
| `Level` | The player's or character's current level. | `10`    | If the game has no levels |

{% hint style="danger" %}
The player attribute data must be passed to the SDK before the inference API request.
{% endhint %}

#### **Code Example**

{% code title="Android: Kotlin" %}

```kotlin
import ai.airflux.Airflux
import ai.airflux.common.AirfluxContext

Airflux.setContext(AirfluxContext.LEVEL, 10)
```

{% endcode %}

{% code title="Android: Java" %}

```java
import ai.airflux.Airflux;
import ai.airflux.common.AirfluxContext;

Airflux.setContext(AirfluxContext.LEVEL, 10);
```

{% endcode %}

</details>

<details>

<summary>Stage Attributes</summary>

#### **When to Trigger**

* When the game app opens.
* When a player logs in.

| Name                   | Description                                                                                                      | Example | Skip Case                       |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------- | ------- | ------------------------------- |
| `START_STAGE`          | The last stage the player started.                                                                               | `10`    | If the game has no stages       |
| `FINISH_STAGE`         | The last stage the player finished.                                                                              | `10`    | If the game has no stages       |
| `TOTAL_FINISHED_STAGE` | The total number of stages a player has finished. For games without stages, this should be the total play count. | `10`    | If information is not available |

#### **Code Example**

{% code title="Android: Kotlin" %}

```kotlin
import ai.airflux.Airflux
import ai.airflux.common.AirfluxContext

Airflux.setContext(AirfluxContext.START_STAGE, "primary_stage", 10)
Airflux.setContext(AirfluxContext.FINISH_STAGE, "primary_stage", 10)
Airflux.setContext(AirfluxContext.TOTAL_FINISHED_STAGE, "primary_stage", 10)
```

{% endcode %}

{% code title="Android: Java" %}

```java
import ai.airflux.Airflux;
import ai.airflux.common.AirfluxContext;

Airflux.setContext(AirfluxContext.START_STAGE, "primary_stage", 10);
Airflux.setContext(AirfluxContext.FINISH_STAGE, "primary_stage", 10);
Airflux.setContext(AirfluxContext.TOTAL_FINISHED_STAGE, "primary_stage", 10);
```

{% endcode %}

</details>

<details>

<summary>Other Attributes</summary>

#### **When to Trigger**

When other custom game attributes are updated.&#x20;

#### **Note**

* Attributes can have up to 100 key-value pairs.
* Keys must satisfy the regex ^\[a-zA-Z\_]\[a-zA-Z0-9\_]\*$.
* The maximum length of keys is 128 characters.
* Values type must be string, numeric, or boolean.
* The maximum length of string values is 1024 characters.

| Name        | Description                                                       | Example                   | Skip Case     |
| ----------- | ----------------------------------------------------------------- | ------------------------- | ------------- |
| `Attribute` | A key-value map for other custom attributes and game information. | `"battlePass", "premium”` | If not needed |

#### **Code Examples**

{% code title="Android: Kotlin" %}

```kotlin
import ai.airflux.Airflux
import ai.airflux.common.AirfluxContext

Airflux.setContext(AirfluxContext.ATTRIBUTE, "battlePass", "premium")
```

{% endcode %}

{% code title="Android: Java" %}

```java
import ai.airflux.Airflux;
import ai.airflux.common.AirfluxContext;

Airflux.setContext(AirfluxContext.ATTRIBUTE, "battlePass", "premium");
```

{% endcode %}

</details>

***

## Frequently Asked Questions

<details>

<summary>How should I use the <code>category</code>, <code>semanticAttributes</code>, and <code>customAttributes</code> parameters for event data collection?</summary>

| Name                 | Type                         | Description                                                                                                                                                                                                                                                                                                          |
| -------------------- | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `category`           | `String`                     | <p><strong>The event's unique name</strong> (e.g., <code>AD\_IMPRESSION</code>).<br>Only underscores are permitted as special characters; colons and other special characters are not allowed. If the collected data exceeds the maximum limit of 128 characters, only the initial 128 characters will be saved.</p> |
| `semanticAttributes` | `Dictionary<string, object>` | <p><strong>Semantic attributes of the event</strong><br>Semantic attribute data collection is limited by type: up to 1024 characters for strings, and 64 bits for integers or floats.</p>                                                                                                                            |
| `customAttributes`   | `Dictionary<string, object>` | **Custom attributes of the event** Custom attribute data collection is limited to 2,048 characters; exceeding the limit results in ERROR\_MAX\_LENGTH\_EXCEEDED.                                                                                                                                                     |

</details>

<details>

<summary>When a player completes a stage and levels up at the same time, how should I track it?</summary>

Use the `TrackEvent()` function to track the player's action of completing a stage as the Achieve Level event, and use the `SetLevel()` function to track the player's updated level as the player attribute.

</details>

<details>

<summary>Can I use the Airflux SDK to collect and send game store payment data?</summary>

No. The game store payment data must be collected and sent using the client-side SDK.

</details>

<details>

<summary>After restarting the game, the Airflux SDK stops sending events. How can I fix this?</summary>

Airflux Native SDK v1.0 Guide: \
The Airflux Native SDK automatically tracks app lifecycle events, so you do not need to manually call `startTracking()`. This issue typically occurs if the SDK is disabled, either by:

1. Setting `setSDKEnabled(false)` in the SDK initialization options.
2. Calling the `Airflux.disableSDK()` function during runtime.

When the SDK is disabled, both event tracking and inference requests are halted. To resolve this, you must explicitly call `Airflux.enableSDK()` to re-activate the SDK's features.

</details>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.airflux.ai/airflux-onboarding/airflux-integration-android/3.-send-in-game-event-data.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
