Integration guide
Recovering failed Shopify payments
Shopify's native abandoned checkout email is a single template on a fixed delay. For merchants running subscriptions or higher-value carts, the useful work sits in separating a genuinely abandoned checkout from a payment that failed at authorisation — the two need very different messages.
Quick answer
Shopify recovery combines abandoned checkout events with failed subscription or payment events, then follows up on the channel the shopper actually reads instead of a single email sequence.
Events that matter
- checkouts/update
- A checkout was started and not completed.
- orders/paid
- The order completed — used to stop follow-ups.
- orders/cancelled
- The order was cancelled and should be excluded.
Setting it up
- 1
Register the webhooks
Subscribe your RRLabs endpoint to checkout and order topics from the Shopify admin or app configuration.
- 2
Separate the causes
Checkouts that reached payment and failed are treated as recovery; checkouts abandoned earlier are treated as nurture.
- 3
Pick the channel
WhatsApp or SMS where the shopper opted in, email otherwise.
- 4
Suppress on success
orders/paid cancels any queued follow-up for that checkout.
Handle checkouts/update and orders/paid
// Shopify webhook topics: checkouts/update, orders/paid, orders/cancelled
const topic = request.headers.get("x-shopify-topic");
const payload = JSON.parse(rawBody); // verify X-Shopify-Hmac-Sha256 first
if (topic === "checkouts/update" && !payload.completed_at) {
await rrlabs.enqueueRecovery({
provider: "shopify",
externalId: String(payload.id),
customerEmail: payload.email,
customerPhone: payload.phone ?? payload.shipping_address?.phone,
amountCents: Math.round(Number(payload.total_price) * 100),
currency: payload.currency,
});
}
if (topic === "orders/paid" || topic === "orders/cancelled") {
await rrlabs.closeRecovery({ provider: "shopify", externalId: String(payload.checkout_id) });
}Manual recovery vs. automated recovery
| Capability | Shopify alone | With RRLabs |
|---|---|---|
| Trigger granularity | One abandoned-checkout trigger | Abandoned vs. failed-payment handled separately |
| Timing | Fixed delay | Timing per cause and per customer timezone |
| Channels | Email, WhatsApp, SMS where consented | |
| Reporting | Recovered-checkout count | Attempt-level attribution per channel and message |
| Source of truth | Shopify | Shopify — orders and payments stay in Shopify |
Frequently asked questions
Does this work with Shopify Payments and third-party gateways?
Yes. Recovery is driven by Shopify's checkout and order webhooks, which fire regardless of the gateway behind them.
Can I keep Shopify's own abandoned checkout email?
You can, but running both usually means duplicate contact. Most merchants disable the native email once RRLabs sequences are live.
Is WhatsApp outreach allowed?
Only to customers who opted in. RRLabs stores the consent record with the contact.