# Custom Outcome Metadata

## What is outcome metadata?

Outcome Metadata lets you attach additional details to a logged outcome, providing context about user behavior after an upsell offer is shown. For example, you can track whether a user clicked to learn more before making a purchase or interacted with other UI elements. ContextSDK records this information alongside the outcome, offering deeper insights into user behavior and monetization performance.

## How do outcome metadata differ from custom signals and revenue outcomes?

[Custom Signals](/context-decision/advanced/custom-signals.md) provide additional context to the machine learning model at the time of context capture, allowing them to influence decision-making. In contrast, outcome metadata is recorded after a context has been captured and does not affect the decision-making process.

[Revenue Outcomes](/context-decision/revenue-outcomes.md) are a specialized type of metadata that have dedicated APIs due to their importance. Use revenue outcomes to log details about in-app purchases, which will automatically include the product purchased, revenue, recurrence model, and other relevant metadata, without any extra effort.

## Why log outcome metadata?

Outcome metadata helps provide a deeper understanding of user behavior. It can also indicate whether your app overrode the ML model’s decision — for example, due to an upsell offer cooldown mechanism. By capturing this data, you can improve reporting accuracy and ensure the necessary data is available to refine and enhance future models.

{% hint style="info" %}
While metadata enriches outcome tracking, it does not influence **when** an upsell offer is shown. If you need to factor in additional signals for determining whether to display an offer, consider using [Custom Signals](/context-decision/advanced/custom-signals.md) instead.
{% endhint %}

## How to log outcome metadata

Use `appendOutcomeMetadata(_:)` to attach metadata to a context before logging an outcome. The metadata will only be recorded if an outcome is logged.

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

```swift
context.appendOutcomeMetadata([
    CustomSignalString(id: "path", value: "flow_2"),
    CustomSignalBool(id: "clicked_learn_more", value: true),
])
```

After appending metadata, ensure that an outcome (whether positive or negative) is logged, e.g.:

```swift
context.logRevenueOutcome(from: product)
```

{% endtab %}

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

```kotlin
context.outcomeMetadata["path"] = "flow_2"
context.outcomeMetadata["clicked_learn_more"] = true
```

After appending metadata, ensure that an outcome (whether positive or negative) is logged, e.g.:

```swift
context.log(EventOutcome.POSITIVE)
```

{% endtab %}

{% tab title="Java" %}

```java
context.getOutcomeMetadata().set("path", "flow_2");
context.getOutcomeMetadata().set("clicked_learn_more", true);
```

After appending metadata, ensure that an outcome (whether positive or negative) is logged, e.g.:

```swift
context.log(EventOutcome.POSITIVE);
```

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

{% tab title="Flutter" %}

```dart
context.appendOutcomeMetadata({
  'path': 'flow_2',
  'clicked_learn_more': true,
});
```

After appending metadata, ensure that an outcome (whether positive or negative) is logged, e.g.:

```dart
await context.log(Outcome.positive);
```

{% endtab %}

{% tab title="Unity" %}

```csharp
context.AppendOutcomeMetadata("path", "flow_2");
context.AppendOutcomeMetadata("clicked_learn_more", true);
```

After appending metadata, ensure that an outcome (whether positive or negative) is logged, e.g.:

```csharp
context.Log(Outcome.Positive);
```

{% endtab %}

{% tab title="React Native" %}

```javascript
await context.appendOutcomeMetadata({
    path: 'flow_2',
    clicked_learn_more: true,
});
```

After appending metadata, ensure that an outcome (whether positive or negative) is logged, e.g.:

```javascript
await context.log(Outcome.positive);
```

{% endtab %}
{% endtabs %}

Appending metadata with the same ID multiple times replaces the previous value. This ensures only the most recent data is retained. To remove a value, pass `nil`.


---

# 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.contextsdk.com/context-decision/advanced/custom-outcome-metadata.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.
