# Release Checklist

Before you ship your first release with the ContextSDK, we recommend taking a few steps to validate the integration works as expected.

{% stepper %}
{% step %}
**Validate the Context**

1. Add the following log right after wherever you [capture the `context`](https://docs.contextsdk.com/context-decision/logging-conversions#capturing-context) object:

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

```swift
print(context.validate())
```

{% endtab %}

{% tab title="Android" %}
{% tabs %}
{% tab title="Kotlin" %}

```kotlin
Log.d("ContextSDK", context.validate())
```

{% endtab %}

{% tab title="Java" %}

```java
Log.d("ContextSDK", context.validate());
```

{% endtab %}
{% endtabs %}
{% endtab %}

{% tab title="Flutter" %}

```dart
print(await context.validate());
```

{% endtab %}

{% tab title="Unity" %}

```csharp
Debug.Log(context.Validate());
```

{% endtab %}

{% tab title="React Native" %}

```javascript
const output = await context.validate();
console.log(output); // Or print it anywhere else
```

{% endtab %}
{% endtabs %}

2. Run your app on a **physical device**, not on a simulator or emulator.
3. Navigate to the screen where you access ContextSDK. Make sure all the requirements you've implemented in your app are met (e.g. the user has not purchased the product, the user has not seen the upsell before, etc.).
4. You should see the following output printed, with the numbers varying depending on the current context:

```
✅ Number of Signals: 340 (this number may be higher)
✅ Flow name provided: your_flow_name
✅ Accelerometer Data: Valid
👉 Signal Sample 1: 0.0 (if your device was flat on the table not moving, this should be 0.0)
👉 Signal Sample 2: 0.0059286836 (this should never be exactly 0.0)
✅ Calibration Mode active
✅ ContextSDK License: Active
👉 ContextSDK Version: 5.15.0
```

5. If you notice the ContextSDK version not being 5.15.0, please follow the instructions in [updating-your-sdk](https://docs.contextsdk.com/other/updating-your-sdk "mention").
   {% endstep %}

{% step %}
**Verify each flow has a unique name**

Each flow should have a distinct name, even if the same flow is triggered from different parts of the app. We automatically analyze the overlap between different flows, to decide if there should be one, or more models.

**Best practice**: use `snake_case` and group flows that lead to the same prompt using the same prefix, e.g. `upsell_onboarding`, `upsell_first_action` .
{% endstep %}

{% step %}
**Verify the moment you are capturing context and logging outcome**

It is critical that you capture the `context` object **right before** you show the upsell prompt. This guarantees that the signals are taken at the correct moment (as context can change quickly), and also allows you to start making decisions once your custom model is ready.

Similarly, you should log the outcome **after the user has interacted** with the upsell prompt.

Failing to follow these guidelines will likely show console warnings, such as a message indicating that you’re logging an outcome immediately after creating the context, as this approach is generally considered incorrect.
{% endstep %}

{% step %}
**Verify you are correctly logging all outcome scenarios**

You need to ensure you always log at least one outcome for each time you access the current context:

<figure><img src="https://3581907717-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FSkVGr8d4Ye763BArtYu5%2Fuploads%2Fgit-blob-6ee8547374f7c569753535fb606709dbdf6f9deb%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

Also, make sure both positive and negative code paths are tested before releasing your app. Forgetting to log one or the other usually invalidates the data collected and delays the training of your custom model.

We recommend logging `.positive` only after the user successfully completes a purchase.

If the user dismisses the iOS payment sheet or encounters a transaction error (e.g., due to network issues), avoid logging an outcome immediately. Instead, log a new [custom-outcome-metadata](https://docs.contextsdk.com/context-decision/advanced/custom-outcome-metadata "mention") and allow the user to retry (e.g., by keeping the paywall screen open after a payment error). Log the final outcome later, such as when the user either dismisses the paywall or successfully completes the purchase.

Alternatively, you can be more fine-grained with your logging and use [alternative-outcomes](https://docs.contextsdk.com/context-decision/advanced/alternative-outcomes "mention").

When logging outcome metadata, be sure to call `context.log(…)` afterward. The metadata is transmitted to the server only when an outcome is logged.

Also, avoid logging multiple outcomes for the same context without updating metadata between them. For example, if a user dismisses the upsell prompt, logging a `.negative` outcome repeatedly without changing metadata isn’t necessary. Update the metadata between each outcome, or log the outcome only once.
{% endstep %}

{% step %}
**Ensure no errors are logged by the SDK**

When running your app with ContextSDK installed on a real device, ensure that your IDE doesn't print out any ContextSDK-related errors (search console logs for "ContextSDK").
{% endstep %}
{% endstepper %}
