Zum Hauptinhalt springen
Version: Aktuelle Plattform

Conversion Tracking

Upsurge measures conversions at two levels:

LevelSourceUsed for
Browser-observedThe SDK's conversion event (purchase by default)Real-time activity, campaign and experiment reporting, the Conversions page
AuthoritativeOrders sent from your store or serverConfirmed revenue, refunds and cancellations, customer value, and partner reconciliation

Send both when you can. The browser event is fast but can be blocked or lost. The server record is the source of truth for money.

1. Choose the conversion event​

The SDK marks exactly one event type as the conversion. Set it in init:

window.UpsurgeQueue.push([
'init',
{
siteId: 'site_replace_me',
baseUrl: 'https://api.upsur.ge',
conversionEventType: 'purchase', // or 'checkout_complete'
},
]);

Every event of that type gets is_conversion: true and conversion_event_type. The SDK also attaches the shopper's experiment and partner-experiment assignments so experiment results can count the conversion. Credit to overlays, recommendations, and chatbots comes from the signed product touches those runtimes record, not from the purchase payload.

Use checkout_complete only when your storefront cannot see the order confirmation page. In that case each checkout_complete must carry a stable cart_id, checkout_id, transaction_id, or order_id, or at least one item with a product_id.

2. Track the purchase in the browser​

Call trackPurchase once on the order confirmation page:

window.upsurge.trackPurchase({
transaction_id: 'ORDER-10492',
total_amount: 258.0,
currency: 'USD',
coupon_code: 'SAVE15',
products: [
{
product_id: 'SKU-TRAIL-123',
product_name: 'Trail Runner',
quantity: 2,
price: 129.0,
currency: 'USD',
},
],
});
  • transaction_id, total_amount, currency, and products are required.
  • Use the same order ID that your store and server use, so duplicates are removed and the browser event can be matched to the authoritative order.
  • A page reload that repeats the call is deduplicated by the order ID.

Track the steps before the purchase too (trackProductView, trackAddToCart, trackCheckoutStart) so funnels and cart-recovery campaigns have data. See Event tracking.

Shopify and WooCommerce

The Upsurge Shopify app's Web Pixel and the Upsurge WordPress plugin send storefront commerce events for you, and the store connection supplies orders. Use the calls on this page for custom or headless storefronts, or to add events those integrations do not send.

3. Carry the journey token to the order (optional)​

With revenue attribution enabled, the SDK keeps a signed journey token that links the browser journey to the order your server records later.

window.UpsurgeQueue.push([
'init',
{
siteId: 'site_replace_me',
baseUrl: 'https://api.upsur.ge',
revenueAttribution: {
enabled: true,
consent: { analytics: false, advertising: false },
},
},
]);

// When the visitor's consent changes:
window.upsurge.setAttributionConsent({ analytics: true, advertising: true });

// Before checkout, store the token on the cart or order:
const journeyToken = window.upsurge.getJourneyToken();

Save the token as a cart attribute or order note, then send it as journey_token in the server conversion below. Consent is denied by default; without analytics consent only session-scoped state is kept.

4. Send authoritative orders from your server​

POST /api/v1/commerce/conversions records the order, and later its refunds and cancellations, as authoritative. It requires a secret API key with the commerce:convert permission; create one in Sites and API keys. Never call it from the browser.

curl --request POST 'https://api.upsur.ge/api/v1/commerce/conversions' \
--header "X-API-Key: $UPSURGE_SECRET_KEY" \
--header 'Content-Type: application/json' \
--data '{
"schema_version": 1,
"event_type": "purchase",
"idempotency_key": "order-10492-purchase",
"website_id": "site_replace_me",
"order_id": "ORDER-10492",
"occurred_at": "2026-09-24T18:04:11Z",
"source": "trusted_server",
"currency": "USD",
"revenue_minor": 25800,
"margin_minor": 9100,
"journey_token": "JOURNEY_TOKEN_FROM_CART",
"subject": { "merchant_user_id": "customer_48291" }
}'
FieldNotes
schema_versionAlways 1.
idempotency_key8–255 characters, unique per event. Retrying with the same key returns 200 instead of creating a duplicate.
order_idThe same order ID the browser sent as transaction_id.
occurred_at, source_updated_atISO 8601 timestamps with an offset. source_updated_at cannot be earlier than occurred_at.
sourceshopify, woocommerce, bigcommerce, magento, trusted_server, partner, or historical_import.
revenue_minor, margin_minorInteger amounts in the currency's minor unit, such as cents. Margin is optional.
revenue_delta_minorSigned change for an adjustment. reason is refund, partial_refund, correction, chargeback, or other.
subjectOptional: merchant_user_id and/or a SHA-256 hashed_email (64 lowercase hex characters). Never send a raw email.

A new record returns 201; a duplicate returns 200. Unknown fields are rejected.

For AWIN and CJ partner orders, use /partner-attribution/conversions instead.

5. Verify​

  1. Complete a test order on the storefront.
  2. In the browser Network panel, confirm the events/batch request includes the purchase event with is_conversion: true.
  3. Open Dashboard → Conversions and find the order under the Web source.
  4. If you send server conversions, confirm the API returned 201, then check that the customer's Confirmed revenue includes the order in Customers.

Troubleshooting​

SymptomCheck
Purchase recorded but not counted as a conversionconversionEventType matches the event you send.
400 on checkout_completeThe event needs a cart, checkout, transaction, or order ID, or an item with product_id.
Conversion appears twiceThe browser and server must use the same order ID; the server must reuse idempotency_key on retries.
Server call returns 401 or 403Use a secret key with commerce:convert in the X-API-Key header, sent from a server.
getJourneyToken() returns undefinedRevenue attribution is not enabled, or no token has been issued yet for this journey.