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

# Store Brand Alternative Savings

> Suggest cheaper store-brand alternatives for name-brand purchases.

> 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

Users frequently buy name-brand products without realizing equivalent store-brand alternatives exist at the same retailer for significantly less. Store brands are often 25-55% cheaper for comparable items, but most users default to name brands out of habit. Without visibility into what was purchased at the SKU level, there is no practical way to surface these savings at the right moment.

## Solution

Retrieve SKU-level transaction data from the [Sync Transactions](/api-reference/products/transaction-link/sync) endpoint. Compare the products users purchase against a catalog of comparable products at the same merchant. When a cheaper alternative exists in the same category, surface it as a proactive savings tip.

<Frame>
  <img src="https://mintcdn.com/knot/0MwiXdOBgWetsfg_/images/store-brand-alternative-savings.png?fit=max&auto=format&n=0MwiXdOBgWetsfg_&q=85&s=a7622fbc89fe1d5834670ceb1ffef194" alt="iPhone lock screen showing a push notification: Grocery savings opportunity found — You can save $2.50 each time you buy ketchup with a different brand at Walmart" width="3840" height="1600" data-path="images/store-brand-alternative-savings.png" />
</Frame>

This gives users a concrete, actionable savings insight tied to their real purchases, without requiring any change to their checkout behavior.

## 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[Check each product against cheaper alternatives at same merchant]
    C --> D{Savings above threshold?}
    D -->|Yes| E[Surface savings suggestion]
    D -->|No| F[No action needed]
```

## 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](/api-reference/products/transaction-link/sync) to sync SKU-level transactions on a daily basis.

    **Key fields**

    | Field                         | Purpose                                                            |
    | ----------------------------- | ------------------------------------------------------------------ |
    | `products[].name`             | Product display name for the push or UI.                           |
    | `products[].external_id`      | Unique product identifier for tracking across orders.              |
    | `products[].price.unit_price` | Price paid, used to calculate potential savings.                   |
    | `products[].category`         | Knot-provided product category for grouping alternatives.          |
    | `products[].subcategory`      | Knot-provided subcategory for narrower matching within a category. |
    | `products[].image_url`        | Product image for the UI.                                          |
    | `merchant.id`                 | Identifies the merchant for catalog scoping.                       |
    | `merchant.name`               | Merchant display name for the UI.                                  |
    | `datetime`                    | Purchase timestamp.                                                |
    | `external_user_id`            | Identifies the user in your system.                                |
    | `order_status`                | Filter to completed orders 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 and maintain a product catalog" titleSize="h3">
    As transaction data accumulates across your users, maintain a per-merchant product catalog. Knot can provide a `products[].category` and `products[].subcategory` on each product, so no custom categorization logic is required. Use `subcategory` for matching where available - it groups products at the right level of specificity (e.g., "creamy peanut butter" rather than just "condiments").

    ```text theme={"system"}
    FOR each product in new_transaction.products:
        upsert into product_catalog:
            (merchant_id, external_id, name,
             category, subcategory, unit_price, image_url)
    ```

    Cross-user data compounds the value: as more users shop at a merchant, the catalog grows to cover more categories and refine price signals for each product.
  </Step>

  <Step title="Detect alternatives" titleSize="h3">
    On each incoming transaction (or on a daily job), check whether any product in the order has a cheaper alternative in the same category at the same merchant.

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

        alternatives = query product_catalog WHERE
            merchant_id   == new_transaction.merchant.id
            AND subcategory == product.subcategory  // fall back to category if null
            AND unit_price  < product.price.unit_price
            AND external_id != product.external_id

        IF alternatives is not empty:
            best = alternative with lowest unit_price
            savings = product.price.unit_price - best.unit_price
            savings_pct = savings / product.price.unit_price

            IF savings >= MIN_SAVINGS AND savings_pct >= MIN_SAVINGS_PCT:
                queue suggestion for external_user_id
    ```

    **Configuration decisions for your team:**

    | Parameter                 | Suggested Default         | Considerations                                                                                |
    | ------------------------- | ------------------------- | --------------------------------------------------------------------------------------------- |
    | `MIN_SAVINGS`             | \$0.50                    | Filters out trivial differences that won't feel meaningful to users.                          |
    | `MIN_SAVINGS_PCT`         | 15%                       | Prevents surfacing alternatives where the price gap is negligible relative to the item price. |
    | Max suggestions per order | 3                         | Avoids alert fatigue when a user buys many name-brand items in one order.                     |
    | Alert frequency           | Once per product per user | Don't re-alert on the same product in a future order unless the price gap has grown.          |

    **Trigger timing options:**

    * **Real-time (preferred):** Run the check on each incoming transaction. Best for high-savings items where the impact is immediate and the user is likely to remember the purchase.
    * **Weekly digest:** Aggregate all matched alternatives from the week and present a cumulative "you could have saved \$X" summary. Less disruptive for small per-item amounts.
    * **Hybrid:** Real-time for savings above \$2 per item; weekly digest for smaller gaps.
  </Step>

  <Step title="Surface the savings suggestion" titleSize="h3">
    When an alternative is identified, notify the user with the product name, what they paid, the store-brand alternative, and the potential savings.

    **Push notification:**

    > **Save \$2.50 on ketchup next time.** You can save \$2.50 each time you buy ketchup with a different brand at Walmart.

    Deeplink the user to a screen displaying more details about the savings opportunity, including a direct link to the alternative product, so they can check it out more deeply.
  </Step>
</Steps>

## Expansion Path

* **Broader merchant coverage:** Extend the catalog to additional retailers with established store brands. Each new merchant multiplies the addressable product categories and addressable users.
* **Personalized suggestions:** Use a user's purchase history to prioritize alternatives they are most likely to try. Users who already buy some store-brand products in a category are significantly more likely to switch in adjacent categories. Surface those first.
* **Weekly savings digest:** Aggregate all suggested swaps from the past week and send a single in-app card showing total potential savings. This keeps the feature visible without generating a notification per purchase.
