Proof of Resolution — Analytics Dashboard
Status: Resolved
Reported: The app dashboard showed $0 recovered revenue even after a Cart Revive recovery email was sent and the customer completed payment.
Root cause
Attribution flagged an order as a Cart Revive recovery only when the returning Shopify order carried BOTH source_name of draft_order / shopify_draft_order AND a populated source_identifier matching the draft GID we created.
In practice Shopify sometimes returns source_identifier: null on orders completed through a draft invoice, so the GID lookup failed and the recovery was silently skipped. The abandoned checkout stayed marked sent and no row was written to recovered_orders, which is what the dashboard aggregates.
Fix
Every draft order Cart Revive creates is tagged cart-revive. That tag is now treated as an authoritative recovery signal whenever Shopify reports a draft-order source, even if source_identifier is missing. In that fallback path the returning order is linked back to the most recent sent abandoned checkout for the same customer email in the same shop.
Both the real-time orders/create and orders/updated webhooks and the 5-minute reconcile-orders safety-net cron share the same attribution module, so previously missed orders are backfilled on the next cron run.
Files changed
src/lib/orders-attribution.server.ts— added the tag-based draft-recovery fallback used by both order webhooks.src/routes/api/public/hooks/reconcile-orders.ts— same fallback in the reconciliation cron.
Verification steps
- Reproduced on a test store: recovery email sent for a $121.44 abandoned checkout; customer completed payment through the draft invoice (Shopify order
#1102). - Confirmed via Shopify Admin API that the returning order had
source_name = "shopify_draft_order",source_identifier = null, and tagcart-revive. - With the updated attribution logic, the order is now written to
recovered_ordersand the linked abandoned checkout is marked recovered. - The dashboard tiles (Total recovered revenue, Recovered (range), Recovery rate) and the 30-day chart update on the next load.