VYG Docs
Custom EventsRecipes

Abandoned Checkout

Send abandoned checkouts to VYG and use them to start a recovery campaign.

Create a checkout_abandoned event for shoppers who start checkout without completing it. Then use that event to start a recovery campaign. See Triggering flows.

1. Define the event

In the app, open your data source under Settings → Data sources, click Add event, paste the example body from step 3 and name the event Checkout abandoned. To require fields, mark them on the event's Fields section. Over the API, register a definition with this payload schema:

{
	"$schema": "http://json-schema.org/draft-07/schema#",
	"type": "object",
	"required": ["checkout_id", "customer_email", "cart_total", "currency", "abandoned_at"],
	"properties": {
		"checkout_id": { "type": "string" },
		"customer_email": { "type": "string", "format": "email" },
		"customer_phone": { "type": "string" },
		"customer_first_name": { "type": "string" },
		"customer_last_name": { "type": "string" },
		"cart_total": { "type": "number" },
		"currency": { "type": "string" },
		"items": {
			"type": "array",
			"items": {
				"type": "object",
				"properties": {
					"sku": { "type": "string" },
					"title": { "type": "string" },
					"quantity": { "type": "integer" },
					"price": { "type": "number" }
				}
			}
		},
		"abandoned_at": { "type": "string", "format": "date-time" }
	}
}

2. Map identifiers

The identifier mapping tells VYG which fields identify the shopper. In the app's guided flow, these are the customer questions plus the time under More details. Over the API, for this schema:

{
	"external_id_path": ["checkout_id"],
	"email_path": ["customer_email"],
	"phone_path": ["customer_phone"],
	"first_name_path": ["customer_first_name"],
	"last_name_path": ["customer_last_name"],
	"received_at_path": ["abandoned_at"]
}

external_id_path resolves a stable id for the abandoned checkout. Include an email or phone number so VYG can identify the shopper. Email alone accepts the event and can trigger email flows; SMS and agent flows still need customer_phone.

3. Send the event

Sign the body with the brand's webhook secret (see HMAC Verification) and POST to the webhook endpoint:

SECRET='whsec_demo_secret'
URL='https://<your-vyg-webhook-host>/custom/<webhookId>'
BODY='{"type":"checkout_abandoned","event_id":"evt_chk_001","data":{"checkout_id":"ck_9f3a","customer_email":"jane@example.com","customer_phone":"+15551234567","customer_first_name":"Jane","customer_last_name":"Doe","cart_total":89.50,"currency":"USD","items":[{"sku":"COF-001","title":"Monthly Coffee","quantity":1,"price":29.99}],"abandoned_at":"2026-05-09T14:32:11Z"}}'

SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')
# expected: 259cf6883b6322233d897ce4f1279a12807b3a57e4ed64de0eb6ae9b49015a60

curl -sS -X POST "$URL" \
  -H 'content-type: application/json' \
  -H 'x-vyg-topic: checkout_abandoned' \
  -H 'x-vyg-event-id: evt_chk_001' \
  -H "x-vyg-signature: $SIG" \
  --data "$BODY"

An accepted event returns ok: true. Check campaign activity separately for flow runs and messages:

{
	"ok": true,
	"custom_event_id": "8e3b0f5a-…-…",
	"flow_event_id": null
}

4. Verify end-to-end

After sending the request:

  1. The event appears in Settings → Data sources: open the data source and check its Activity tab, which lists received events, newest first. The Checkout abandoned event has its own Activity tab too.
  2. Check that the contact information shown for the event matches your payload.
  3. If you have built and activated a flow on checkout_abandoned, the recorded event triggers it asynchronously after processing. See Custom Events → Triggering flows. Flow runs appear in the campaign's activity in the VYG dashboard.

If you see 404 unknown_event_type, your type slug doesn't match a registered definition. If you see 422 missing_external_id or missing_contact_channel, recheck the identifier mapping against your real payload. 422 contact_channel_conflict means the email or phone is already owned by a different contact — resolve that identity conflict before resending.

On this page