Skip to main content

Build an abandoned-cart recovery flow

An abandoned-cart flow should do three things in order: receive a cart event, give the customer time to finish checkout, and stop as soon as an order is paid. This guide assembles that pattern in Devotel Orbit with a two-hour delay, an order check, an SMS message, and a WhatsApp fallback that includes the product link. You can use the same flow with Shopify, WooCommerce, a custom storefront webhook, a CDP import, or a scheduled re-scan. The examples use flat flow variables such as {{first_name}} and {{recovery_url}}; dotted placeholders such as {{contact.first_name}} do not resolve in flow messages.

1. Pick the use case

The graph is the same for several incomplete-transaction signals. Change the event name, conversion signal, and message copy to fit your business: Start with a single contact-level conversion key. For a cart, that is usually a checkout ID or cart ID. Include it in both the abandoned event and the purchase event so the condition cannot accidentally match a different order from the same customer.

2. Wire the source event

Choose one source. All three approaches end with the same flat Flow context.

Option A: Shopify or WooCommerce integration

Connect the store first, then subscribe the flow to the normalized cart event. Shopify’s checkouts/create delivery emits cart.created with contact_id, recovery_url, total_price, and currency. See Connect Shopify end to end. WooCommerce order events enter the CDP stream, and a cart-abandonment event can carry recovery_url, cart_total, and line_items. See Connect WooCommerce end to end. Map the store-specific event to the flow’s stable keys with a transform node if your source uses different names.

Option B: Send a webhook directly to a Flow

Use a Webhook trigger when your storefront already knows when a checkout is abandoned. Post an addressable contact and a stable cart key:
Treat a successful 202 as an accepted trigger, not as proof that a message was sent. Inspect the execution after the delay. Sign and authenticate the webhook according to Webhook security, and make the event idempotent in your sender so a store retry does not enroll the same cart twice.

Option C: Load or re-scan events through CDP

For a backfill or a scheduled export, use CDP file ingest. Upload event rows in chunks of 200 or fewer and include the cart key in properties:
Run a dry run first, then ingest the corrected file. A scheduled re-scan can emit the same event to a schedule-triggered flow, but do not re-enroll a cart unless its stable cart key has changed or the earlier run has ended.

3. Build the wait, condition, and fallback

The canonical path is:
The condition must check the purchase signal for the same cart. Do not use only contact_id: a customer can have a new cart while an older cart is being recovered. The API definition below uses cart_purchased as the result of a condition lookup populated by your event mapping. If your event source exposes order_status, gate on order_status != "paid" instead. Functions node recipes explains how to use a transform node to copy provider-specific keys into stable top-level variables. The smart-send fallback guide explains how cascade_policy arms a delivery fallback.

Create the draft flow

This request creates a draft. Replace the example contact and sender values with values from your tenant. The transform node creates the message variables; the delay parks the execution; the condition exits when the cart is no longer eligible.
The response is a draft flow. Save its data.id, then read it back before publishing:
Fetch the saved definition with GET /api/v1/flows/flow_cart_recovery. If your tenant’s flow builder uses the channel-specific fallback node rather than a node error edge, configure the same SMS → WhatsApp order in the builder and verify it in Test mode. A delivery fallback is not a second enrollment: it carries the remaining message context and product link to the next eligible channel.

Publish and test

Publish only after you have tested both branches:
Send one test event with cart_purchased: "false" and confirm that the run is waiting during the delay. Send a second test with the matching cart key marked purchased and confirm that the condition takes the no path. Finally, force an SMS delivery failure in your tenant’s test setup and confirm that the WhatsApp fallback keeps the same cart_link.

4. Personalize the message

Keep provider fields at the edge of the flow. Use the transform node to derive clean, flat values such as display_name, product_name, cart_link, and cart_total; downstream channel nodes should reference those values directly. The transform node can assign a literal, a template, or a safe boolean expression, but it cannot run arbitrary code. Before publishing, preview the message against representative contacts. Validate campaign personalization merge-tags describes the preview contract and coverage warnings. Check that:
  • phone and whatsapp are present for the intended recipients.
  • recovery_url is a valid HTTPS link owned by your store.
  • The product name and price are present, correctly escaped, and short enough for the channel.
  • Missing optional values have a safe message path; an empty {{product_name}} is worse than leaving the product name out.
  • You use flat tags. {{contact.first_name}} will render blank; {{first_name}} resolves from the event/contact context.
If you need click measurement, create a tenant-owned short link before the flow or use the links API, then inject the resulting URL as recovery_url. Do not expose raw credentials or unrelated customer attributes in the event payload.

5. Connect Shopify or WooCommerce

For Shopify, connect the store through Settings → Integrations. The integration registers the checkout webhook and emits cart.created with a recovery URL. Start with the complete Shopify integration walkthrough, then use the flow definition in this guide for the two-hour wait and purchase check. For WooCommerce, create a REST key pair in WooCommerce → Settings → Advanced → REST API, connect it in Orbit, and let the scheduled sync ingest cart and order events. Follow the WooCommerce integration walkthrough for the key pair and event envelope. Map the WooCommerce cart event to cart_id, recovery_url, and the contact address before it enters the flow. Both integrations are inbound sources. The SMS and WhatsApp sends use your tenant’s configured messaging routes; do not send outbound traffic through a provider’s control or messaging API that is not configured for your tenant.

6. Stop after purchase

A purchase must abort the waiting run before it sends. When the store emits order.paid, update or emit the matching cart context with cart_purchased: "true" and the same cart_id. The condition’s no edge has no target, so the execution ends without a message. Use the Flows Executions API to verify the behavior:
Then fetch the execution trace:
Look for the check_purchase step and its rendered input. A purchased cart should show the false branch and no recover_sms step. A still-open cart should show the true branch, followed by the SMS step and, only if delivery reaches a terminal failure, the WhatsApp fallback. If your store cannot update a waiting execution, use a purchase event as a second flow trigger that cancels the matching run through the Flows execution action exposed by your tenant. Keep the cancellation key scoped to cart_id; never cancel every flow for a contact because that can suppress a newer, valid cart.

7. Add the compliance gate

Compliance settings belong to your tenant. Configure the controls before you publish:
  • Quiet hours: schedule the two-hour send for the recipient’s permitted local window. If the delay ends during quiet hours, let the tenant send control defer the message rather than adding a second ad hoc scheduler.
  • Consent: enroll only contacts whose tenant records show marketing consent for the channel. SMS consent does not automatically grant WhatsApp consent.
  • Unsubscribe: include your tenant’s approved unsubscribe footer on every SMS step. Configure the equivalent WhatsApp opt-out instruction or approved template on every WhatsApp step.
  • Suppression and frequency caps: check the tenant’s suppression list and frequency caps before sending. A fallback is still a new channel send and must be covered by the channel’s consent and suppression settings.
  • Data minimization: send only the contact and cart attributes needed to recover the cart. Keep payment details and sensitive identity data out of the flow context.
These are tenant-owned controls. Review quiet hours configuration, message suppression, and opt-out rules before enabling a production flow.

Troubleshooting

Next steps