> ## Documentation Index
> Fetch the complete documentation index at: https://docs.knotapi.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Price Is Right

> A gamified price-guessing game powered by real purchase data to drive repeat engagement.

> This is a product use case page. When implementing, follow the linked quickstarts for canonical API setup steps rather than inferring them from this page.

## Problem

Banking and fintech apps struggle to drive repeat engagement beyond core financial tasks. Users open the app to check their balance or make a transfer, then leave. There is little reason to come back between transactions, and little-to-no connection between the app and a user's actual purchasing behavior.

## Solution

Build a gamified price-guessing feature that surfaces a product from the user's real purchase history and challenges them to guess how much they paid. The game uses SKU-level transaction data from Knot's [Sync Transactions](/api-reference/products/transaction-link/sync) endpoint, including product names, images, and unit prices, to create a personalized, entertaining experience that drives engagement and reinforces card usage awareness.

<Frame>
  <img src="https://mintcdn.com/knot/UI5vmaLrIbjzR32k/images/price-is-right.png?fit=max&auto=format&n=UI5vmaLrIbjzR32k&q=85&s=9658786508ff235dd78ccc67949b3140" alt="In-app card showing a product image of toothpaste with the prompt: How much did you pay? The user enters a guess and submits it." width="3840" height="1600" data-path="images/price-is-right.png" />
</Frame>

This gives users a reason to come back to your app regularly, while reinforcing awareness of their spending on your card.

## Flow

```mermaid placement="top-right" actions={false} theme={"system"}
%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#f5f5f5', 'primaryTextColor': '#000', 'primaryBorderColor': '#000', 'lineColor': '#000', 'secondaryColor': '#f5f5f5', 'tertiaryColor': '#f5f5f5', 'edgeLabelBackground': '#fff', 'fontSize': '16px'}}}%%
flowchart LR
    A[User switches their card at a merchant through Knot or simply links their merchant account to begin syncing SKU-level purchase data] --> B[Sync each user's purchase data daily from Knot's API]
    B --> C[Select a product from a user's history]
    C --> D[Surface the product in-app and prompt the user to guess the price]
    D --> E[Reveal the actual price and score the guess]
```

## Implementation

<Steps>
  <Step title="Sync transaction data" titleSize="h3">
    When a user switches their card at a merchant or they simply link their merchant account w/o switching their card, Knot begins collecting transaction data for that account. Listen for the [`NEW_TRANSACTIONS_AVAILABLE`](/transaction-link/webhook-events/new-transactions-available) webhook event, then call [Sync Transactions](https://docs.knotapi.com/api-reference/products/transaction-link/sync) to sync SKU-level transactions on a daily basis. Each transaction includes an array of products with names, images, and prices.

    **Key fields**

    | Field                         | Purpose                                                            |
    | ----------------------------- | ------------------------------------------------------------------ |
    | `products[].name`             | Product display name shown to the user in the game.                |
    | `products[].image_url`        | Product photo for the game card.                                   |
    | `products[].price.unit_price` | The actual price, which is the answer the user is trying to guess. |
    | `merchant.name`               | Merchant label for context (e.g., "Walmart").                      |
    | `datetime`                    | Purchase timestamp for "You bought this on..." context.            |
    | `external_user_id`            | Identifies the user in your system.                                |
    | `order_status`                | Filter to completed transactions only.                             |

    Only include transactions with `order_status` of `COMPLETED`, `DELIVERED`, `PICKED_UP`, `SHIPPED`, `BILLED`, or `ORDERED`. Filter out `CANCELLED`, `REFUNDED`, and `FAILED`.
  </Step>

  <Step title="Build the product pool" titleSize="h3">
    Store synced products and filter them into a pool of eligible game candidates. Not every product makes a good game round, so apply filtering rules to keep it fun and fair.

    ```text theme={"system"}
    FOR each product in new_transaction.products:

        IF product.price.unit_price >= MIN_PRICE
           AND product.price.unit_price <= MAX_PRICE
           AND product.image_url is not null
           AND transaction.order_status in [COMPLETED, DELIVERED, PICKED_UP, SHIPPED, BILLED, ORDERED]
        THEN
            add to product_pool for external_user_id
    ```

    **Configuration decisions for your team:**

    | Parameter      | Suggested Default | Considerations                                                                                                                                    |
    | -------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `MIN_PRICE`    | \$1.00            | Filters out free samples and near-zero items that aren't interesting to guess.                                                                    |
    | `MAX_PRICE`    | \$500.00          | Filters out outlier purchases where guessing feels arbitrary.                                                                                     |
    | Recency window | 30-90 days        | Products from the last 30-90 days work best. Users are more likely to remember recent purchases, and more likely to be surprised when they don't. |
  </Step>

  <Step title="Select and present a product" titleSize="h3">
    When the user opens the game or receives a daily prompt, pick a product from their pool. Track which products have already been shown to avoid repeats.

    ```text theme={"system"}
    eligible = query product_pool WHERE
        external_user_id == user.external_user_id
        AND already_shown == false

    IF difficulty_tier is set:
        eligible = filter eligible by tier

    product = random selection from eligible
    mark product as shown
    ```

    Present the product as an in-app game card:

    <Frame>
      <img src="https://mintcdn.com/knot/UI5vmaLrIbjzR32k/images/price-is-right.png?fit=max&auto=format&n=UI5vmaLrIbjzR32k&q=85&s=9658786508ff235dd78ccc67949b3140" alt="In-app Price Is Right game card showing a product with multiple-choice price options" width="3840" height="1600" data-path="images/price-is-right.png" />
    </Frame>
  </Step>

  <Step title="Score the guess and reveal the result" titleSize="h3">
    Compare the user's guess to `products[].price.unit_price` and score based on accuracy.

    ```text theme={"system"}
    difference = abs(guess - product.price.unit_price)
    pct_off = difference / product.price.unit_price

    IF difference <= 0.10:       points = 25, label = "Nailed it!"
    ELSE IF pct_off <= 0.10:     points = 15, label = "So close!"
    ELSE IF pct_off <= 0.25:     points = 10, label = "Not bad!"
    ELSE IF pct_off <= 0.50:     points = 5,  label = "Keep trying!"
    ELSE:                        points = 1,  label = "Way off!"

    update user streak (reset if pct_off > 0.25, increment otherwise)
    add points to user total
    ```

    **Configuration decisions for your team:**

    | Parameter              | Suggested Default      | Considerations                                                                                            |
    | ---------------------- | ---------------------- | --------------------------------------------------------------------------------------------------------- |
    | Streak reset threshold | 25% off                | Resets the streak if the guess is more than 25% off. Adjust to make streaks easier or harder to maintain. |
    | Streak bonus           | 2x points at 3+ streak | Rewards consistency and drives repeat play.                                                               |
  </Step>
</Steps>

## Expansion Path

* **"Which merchant is cheaper?":** The same product often appears across multiple merchants at different prices. Surface a product the user bought and ask them to guess which merchant had the best price. This builds shopping intuition and adds a new game mode without requiring additional data.
* **Post-purchase trigger:** After a new purchase syncs, queue that product for a future round with a 3-7 day delay. The game stays fresh and tied to recent activity.
* **Spending insights from gameplay:** Aggregate guess accuracy data to surface insights like "You tend to underestimate how much you spend on food delivery," turning the game into a lightweight financial awareness tool.
