DOCS
Developers

JSON objects

Full example payloads for Incentive Engine advance, CustomerFacts, per-surface context, emit/done, and outcomes.

Example JSON for the objects apps pass into (and receive from) the Incentive Engine. Values match the sample shopper used in Customer facts and Facts by surface.

Client vs server

Client advance may only send trigger, context, sessionId, and optional renderTarget. organizationId, customer, marketId, and extraFacts are server-derived and must not be accepted from the client.

Thank You vs Post-purchase triggers

order_editing.post_purchase = Thank You page. order_editing.checkout_post_purchase_viewed = Post-purchase interstitial (no context.order).

Conditions evaluate against { customer, context } (see Evaluation scope). Cart prices are in minor units (cents).


Client advance (Thank You)

What a storefront / extension sends to the app’s incentive tRPC advance mutation.

{
  "trigger": "order_editing.post_purchase",
  "context": {
    "orderId": "gid://shopify/Order/5678901234"
  },
  "sessionId": "gid://shopify/Order/5678901234",
  "renderTarget": "purchase.thank-you.block.render"
}

Server AdvanceInput (enriched)

What the engine receives after the app resolves org, customer, market, and (for Thank You) live order rollup into extraFacts.

{
  "organizationId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "trigger": "order_editing.post_purchase",
  "context": {
    "orderId": "gid://shopify/Order/5678901234"
  },
  "customer": {
    "id": "gid://shopify/Customer/9988776655"
  },
  "sessionId": "oe:gid://shopify/Order/5678901234",
  "marketId": "gid://shopify/Market/1",
  "renderTarget": "purchase.thank-you.block.render",
  "extraFacts": {
    "order": {
      "id": "gid://shopify/Order/5678901234",
      "name": "#1042",
      "order_number": 1042,
      "email": "alex@shop.com",
      "financial_status": "paid",
      "fulfillment_status": "unfulfilled",
      "total_price": "89.00",
      "subtotal_price": "75.00",
      "total_discount": "10.00",
      "total_tax": "14.00",
      "currency": "EUR",
      "edited": false,
      "created_at": "2026-08-15T09:12:00.000Z",
      "line_items": [
        {
          "id": "gid://shopify/LineItem/1",
          "product_id": "gid://shopify/Product/123",
          "variant_id": "gid://shopify/ProductVariant/456",
          "sku": "TEE-BLK-M",
          "title": "Classic Tee",
          "variant_title": "Black / M",
          "quantity": 2,
          "price": "29.00",
          "total_discount": "5.00",
          "currency": "EUR"
        }
      ]
    }
  }
}

extraFacts is merged into context before evaluation (e.g. context.order).


Evaluation scope

What the condition builder / evaluator sees after facts load and context merge.

{
  "customer": {
    "organization_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "customer_id": "gid://shopify/Customer/9988776655",
    "profile": {
      "email": "alex@shop.com",
      "first_name": "Alex",
      "last_name": "Müller",
      "display_name": "Alex Müller",
      "phone": "+49 170 1234567",
      "locale": "de",
      "tags": ["VIP", "newsletter"],
      "total_orders": 12,
      "total_spent": "348.50",
      "currency": "EUR",
      "created_at": "2024-01-10T08:00:00.000Z",
      "updated_at": "2026-08-15T09:12:00.000Z"
    },
    "orders": [
      {
        "id": "gid://shopify/Order/5678901234",
        "name": "#1042",
        "order_number": 1042,
        "email": "alex@shop.com",
        "financial_status": "paid",
        "fulfillment_status": "unfulfilled",
        "total_price": "89.00",
        "subtotal_price": "75.00",
        "total_discount": "10.00",
        "total_tax": "14.00",
        "currency": "EUR",
        "edited": false,
        "created_at": "2026-08-15T09:12:00.000Z",
        "line_items": [
          {
            "id": "gid://shopify/LineItem/1",
            "product_id": "gid://shopify/Product/123",
            "variant_id": "gid://shopify/ProductVariant/456",
            "sku": "TEE-BLK-M",
            "title": "Classic Tee",
            "variant_title": "Black / M",
            "quantity": 2,
            "price": "29.00",
            "total_discount": "5.00",
            "currency": "EUR"
          }
        ]
      }
    ],
    "subscriptions": [
      {
        "id": "gid://shopify/SubscriptionContract/111",
        "status": "ACTIVE",
        "currency_code": "EUR",
        "next_billing_date": "2026-09-01T00:00:00.000Z",
        "billing_interval": "MONTH",
        "billing_interval_count": 1,
        "delivery_price": "4.90",
        "lines_count": 1,
        "origin_order_id": "gid://shopify/Order/111000",
        "last_payment_status": "SUCCEEDED",
        "created_at": "2025-06-01T10:00:00.000Z",
        "days_until_next_billing": 5,
        "lines": [
          {
            "id": "gid://shopify/SubscriptionLine/1",
            "product_id": "gid://shopify/Product/789",
            "variant_id": "gid://shopify/ProductVariant/790",
            "selling_plan_id": "gid://shopify/SellingPlan/99",
            "selling_plan_name": "Deliver every month",
            "sku": "COFFEE-1KG",
            "title": "House Blend",
            "variant_title": "1 kg",
            "quantity": 1,
            "current_price": "24.00",
            "currency_code": "EUR"
          }
        ]
      }
    ]
  },
  "context": {
    "orderId": "gid://shopify/Order/5678901234",
    "order": {
      "id": "gid://shopify/Order/5678901234",
      "name": "#1042",
      "order_number": 1042,
      "email": "alex@shop.com",
      "financial_status": "paid",
      "fulfillment_status": "unfulfilled",
      "total_price": "89.00",
      "subtotal_price": "75.00",
      "total_discount": "10.00",
      "total_tax": "14.00",
      "currency": "EUR",
      "edited": false,
      "created_at": "2026-08-15T09:12:00.000Z",
      "line_items": [
        {
          "id": "gid://shopify/LineItem/1",
          "product_id": "gid://shopify/Product/123",
          "variant_id": "gid://shopify/ProductVariant/456",
          "sku": "TEE-BLK-M",
          "title": "Classic Tee",
          "variant_title": "Black / M",
          "quantity": 2,
          "price": "29.00",
          "total_discount": "5.00",
          "currency": "EUR"
        }
      ]
    }
  }
}

Anonymous / missing replica row → customer is null.


CustomerFacts

Standalone row from data_plane.customer_facts (same object nested under customer in the scope above). Money fields are Postgres numeric strings.

{
  "organization_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "customer_id": "gid://shopify/Customer/9988776655",
  "profile": {
    "email": "alex@shop.com",
    "first_name": "Alex",
    "last_name": "Müller",
    "display_name": "Alex Müller",
    "phone": "+49 170 1234567",
    "locale": "de",
    "tags": ["VIP", "newsletter"],
    "total_orders": 12,
    "total_spent": "348.50",
    "currency": "EUR",
    "created_at": "2024-01-10T08:00:00.000Z",
    "updated_at": "2026-08-15T09:12:00.000Z"
  },
  "orders": [
    {
      "id": "gid://shopify/Order/5678901234",
      "name": "#1042",
      "order_number": 1042,
      "email": "alex@shop.com",
      "financial_status": "paid",
      "fulfillment_status": "unfulfilled",
      "total_price": "89.00",
      "subtotal_price": "75.00",
      "total_discount": "10.00",
      "total_tax": "14.00",
      "currency": "EUR",
      "edited": false,
      "created_at": "2026-08-15T09:12:00.000Z",
      "line_items": [
        {
          "id": "gid://shopify/LineItem/1",
          "product_id": "gid://shopify/Product/123",
          "variant_id": "gid://shopify/ProductVariant/456",
          "sku": "TEE-BLK-M",
          "title": "Classic Tee",
          "variant_title": "Black / M",
          "quantity": 2,
          "price": "29.00",
          "total_discount": "5.00",
          "currency": "EUR"
        }
      ]
    }
  ],
  "subscriptions": [
    {
      "id": "gid://shopify/SubscriptionContract/111",
      "status": "ACTIVE",
      "currency_code": "EUR",
      "next_billing_date": "2026-09-01T00:00:00.000Z",
      "billing_interval": "MONTH",
      "billing_interval_count": 1,
      "delivery_price": "4.90",
      "lines_count": 1,
      "origin_order_id": "gid://shopify/Order/111000",
      "last_payment_status": "SUCCEEDED",
      "created_at": "2025-06-01T10:00:00.000Z",
      "days_until_next_billing": 5,
      "lines": [
        {
          "id": "gid://shopify/SubscriptionLine/1",
          "product_id": "gid://shopify/Product/789",
          "variant_id": "gid://shopify/ProductVariant/790",
          "selling_plan_id": "gid://shopify/SellingPlan/99",
          "selling_plan_name": "Deliver every month",
          "sku": "COFFEE-1KG",
          "title": "House Blend",
          "variant_title": "1 kg",
          "quantity": 1,
          "current_price": "24.00",
          "currency_code": "EUR"
        }
      ]
    }
  ]
}

days_until_next_billing is derived at read time, not stored.


Thank You context (merged)

After extraFacts.order merge for trigger order_editing.post_purchase.

{
  "orderId": "gid://shopify/Order/5678901234",
  "order": {
    "id": "gid://shopify/Order/5678901234",
    "name": "#1042",
    "order_number": 1042,
    "email": "alex@shop.com",
    "financial_status": "paid",
    "fulfillment_status": "unfulfilled",
    "total_price": "89.00",
    "subtotal_price": "75.00",
    "total_discount": "10.00",
    "total_tax": "14.00",
    "currency": "EUR",
    "edited": false,
    "created_at": "2026-08-15T09:12:00.000Z",
    "line_items": [
      {
        "id": "gid://shopify/LineItem/1",
        "product_id": "gid://shopify/Product/123",
        "variant_id": "gid://shopify/ProductVariant/456",
        "sku": "TEE-BLK-M",
        "title": "Classic Tee",
        "variant_title": "Black / M",
        "quantity": 2,
        "price": "29.00",
        "total_discount": "5.00",
        "currency": "EUR"
      }
    ]
  }
}

Post-purchase interstitial context

Trigger order_editing.checkout_post_purchase_viewed. No order object.

{
  "checkoutToken": "abc123checkout",
  "productIds": [
    "gid://shopify/Product/123",
    "gid://shopify/Product/124"
  ],
  "subtotal": 72.5,
  "currency": "EUR",
  "itemCount": 3,
  "countryCode": "DE"
}

checkoutToken and productIds are in the trigger schema but not in the condition picker.


Cancel context

Trigger subscriptions.cancel_intent.

{
  "subscriptionContractId": "gid://shopify/SubscriptionContract/111",
  "reason": "too_expensive",
  "subReason": "found_cheaper",
  "otherReason": null
}

Picker exposes reason / subReason only; subscriptionContractId and free-text otherReason are schema/payload fields.


Account upsell context (merged)

Trigger subscriptions.upsell_viewed. Client sends subscriptionContractId; server merges contract from the replica.

{
  "subscriptionContractId": "gid://shopify/SubscriptionContract/111",
  "contract": {
    "id": "gid://shopify/SubscriptionContract/111",
    "status": "ACTIVE",
    "currency_code": "EUR",
    "next_billing_date": "2026-09-01T00:00:00.000Z",
    "billing_interval": "MONTH",
    "billing_interval_count": 1,
    "delivery_price": "4.90",
    "lines_count": 1,
    "origin_order_id": "gid://shopify/Order/111000",
    "last_payment_status": "SUCCEEDED",
    "created_at": "2025-06-01T10:00:00.000Z",
    "days_until_next_billing": 5,
    "lines": [
      {
        "id": "gid://shopify/SubscriptionLine/1",
        "product_id": "gid://shopify/Product/789",
        "variant_id": "gid://shopify/ProductVariant/790",
        "selling_plan_id": "gid://shopify/SellingPlan/99",
        "selling_plan_name": "Deliver every month",
        "sku": "COFFEE-1KG",
        "title": "House Blend",
        "variant_title": "1 kg",
        "quantity": 1,
        "current_price": "24.00",
        "currency_code": "EUR"
      }
    ]
  }
}

Order-status nudge context (merged)

Trigger subscriptions.order_status_viewed.

{
  "orderId": "gid://shopify/Order/5678901234",
  "order": {
    "id": "gid://shopify/Order/5678901234",
    "name": "#1042",
    "order_number": 1042,
    "email": "alex@shop.com",
    "financial_status": "paid",
    "fulfillment_status": "unfulfilled",
    "total_price": "89.00",
    "subtotal_price": "75.00",
    "total_discount": "10.00",
    "total_tax": "14.00",
    "currency": "EUR",
    "edited": false,
    "created_at": "2026-08-15T09:12:00.000Z",
    "line_items": [
      {
        "id": "gid://shopify/LineItem/1",
        "product_id": "gid://shopify/Product/123",
        "variant_id": "gid://shopify/ProductVariant/456",
        "sku": "TEE-BLK-M",
        "title": "Classic Tee",
        "variant_title": "Black / M",
        "quantity": 2,
        "price": "29.00",
        "total_discount": "5.00",
        "currency": "EUR"
      }
    ]
  }
}

Cart context

Trigger cart.cart_viewed. Prices are minor units.

{
  "cartToken": "abc123cart",
  "cart": {
    "token": "abc123cart",
    "note": "Leave at door",
    "currency": "EUR",
    "item_count": 4,
    "total_price": 4999,
    "original_total_price": 5999,
    "items_subtotal_price": 5500,
    "total_discount": 1000,
    "total_weight": 1200,
    "requires_shipping": true,
    "items": [
      {
        "product_id": 1234567890,
        "variant_id": 9876543210,
        "quantity": 2,
        "sku": "TEE-BLK-M",
        "vendor": "memberr",
        "product_type": "Apparel",
        "handle": "classic-tee",
        "product_title": "Classic Tee",
        "variant_title": "Black / M",
        "title": "Classic Tee - Black / M",
        "price": 2900,
        "original_price": 2900,
        "final_price": 2610,
        "line_price": 5800,
        "original_line_price": 5800,
        "final_line_price": 5220,
        "total_discount": 580,
        "gift_card": false,
        "requires_shipping": true,
        "selling_plan_allocation": null
      }
    ],
    "cart_level_discount_applications": [
      {
        "type": "discount_code",
        "title": "SUMMER10",
        "value": "10.0",
        "value_type": "percentage",
        "total_allocated_amount": 1000
      }
    ]
  }
}

AdvanceResult emit

Engine found a matching offer and paused for accept/decline.

{
  "kind": "emit",
  "grantId": "grant_01JABCDEFGHJKMNPQRSTVWXYZ",
  "offerNodeId": "offer_upsell_1",
  "flowVersionId": "fv_01JFLOWVERSION000000000001",
  "incentive": {
    "kind": "upsell_offer",
    "surface": "checkout_ui",
    "selection": {
      "type": "single",
      "product": "gid://shopify/Product/555",
      "variants": [],
      "discount": {
        "type": "percent",
        "percent": 15
      }
    },
    "showProductsAlreadyInCart": false,
    "copy": {
      "headline": {
        "de": "Vervollständige deine Bestellung",
        "en": "Complete your order"
      },
      "body": {
        "de": "Füge Electrolytes hinzu, solange sie noch vorrätig sind.",
        "en": "Add electrolytes while we still have stock."
      },
      "cta": {
        "de": "Zur Bestellung hinzufügen",
        "en": "Add to order"
      }
    }
  }
}

Apps may wrap this with surface UI (ui / flowUi) before returning to the extension.


AdvanceResult done

No offer to show (flow ended, no match, or caps exhausted).

{
  "kind": "done"
}

Client recordOutcome

After the customer accepts or declines an emitted offer.

{
  "grantId": "grant_01JABCDEFGHJKMNPQRSTVWXYZ",
  "outcome": "accepted"
}

Use "declined" when they dismiss. Redemption is a separate client call with { "grantId": "…" } when the surface records fulfillment of the grant.

On this page