Milly Software
InsightsEngagementPost-Purchase Engagement: The Shopify Chat Metric Most Analytics Miss
Engagement··6 min read

Post-Purchase Engagement: The Shopify Chat Metric Most Analytics Miss

Pre-purchase conversion is half the story. How a returning-customer support engagement metric reveals the chat value that pre-purchase tracking can't see.

V
Viet Le
co-founder · Milly Software

Most chat-widget effectiveness measurement focuses on pre-purchase conversion: did the visitor see the widget? Did they open it? Did they convert at a higher rate than the visitors who didn't see it? It's the right question for measuring acquisition lift, but it leaves a whole category of chat value invisible.

That category is returning customers. The widget's job for them isn't to convert — they're already converted. It's to handle the warranty question, the return policy lookup, the order-status check. That engagement keeps the customer in the merchant's ecosystem long enough for the next purchase to land. Pre-purchase tracking can't see any of it.

What post-purchase engagement captures

The metric is straightforward in definition, harder in practice: count orders that are followed by widget engagement within the merchant's configured attribution window. The Impact dashboard surfaces two cards backed by this idea:

  • ordersWithPostPurchaseEngagement — count of orders followed by a widget_opened event from the same visitor
  • revenueWithPostPurchaseEngagement — total revenue across those same orders

Same attribution window as the pre-purchase interactor metric (7 / 14 / 30 / 60 days, per-store). Same visitor-ID join. The difference is the time direction: pre-purchase looks backward from order to chat (was there chat in the 14 days before this order?), post-purchase looks forward (was there chat in the 14 days after?).

Why support-heavy and headless merchants need this

For a typical impulse-purchase store, post-purchase engagement is small relative to pre-purchase — the customer buys once and moves on. For support-heavy and headless merchants, the proportions invert.

UAG's setup is a clean example. Customers buy a phone case, then come back two months later asking about warranty coverage when their phone took a fall, or asking what the return policy looks like, or checking if a different model size is compatible with their existing gear. None of those conversations show up as "the widget caused a sale." All of them keep the customer engaged with UAG's catalog long enough to be present at the next case purchase six months later.

Without a post-purchase metric, the chat's contribution to that retention loop is invisible. The merchant looks at their pre-purchase lift number, sees an honest single-digit figure, and wonders why their interactor cohort feels more engaged than the lift suggests. The interactor cohort is more engaged — they're also coming back post-purchase, and that wasn't being counted.

The rollup architecture

Computing post-purchase engagement live would mean joining the orders table to analytics_events on visitor ID, for every order, every dashboard load. On a UAG-volume store that's a multi-second query. Worse, the same shape of query already runs for the pre-purchase interactor metric — so doing both live is double the cost.

The fix is precomputation. A nightly cron in milly-cloud-services (rollupWidgetAttribution.js) computes daily rows in a widget_attribution_dailytable:

widget_attribution_daily {
  store_id, order_date, window_days,
  interactor_orders_count,    interactor_revenue,
  post_purchase_orders_count, post_purchase_revenue
}

The table is keyed by (store_id, order_date, window_days) — one row per day per supported attribution window per store. The dashboard query becomes a sum over the date range:

SELECT
  COALESCE(SUM(post_purchase_orders_count), 0) as post_purchase_orders,
  COALESCE(SUM(post_purchase_revenue), 0) as post_purchase_revenue
FROM widget_attribution_daily
WHERE store_id = $1
  AND window_days = $2
  AND order_date >= $3 AND order_date <= $4

That's O(window-days) rows touched, not O(orders × events) joins. On UAG, Impact dashboard load went from seconds to milliseconds after the rollup landed. Same data, same truth, fundamentally different cost curve.

Both the interactor (pre-purchase) and post-purchase counts use the same rollup, so the savings apply to both metrics simultaneously. All four supported attribution windows get refreshed each night, so a merchant flipping their window from 7 to 30 days sees the new numbers on their next dashboard load — no backfill wait.

The Impact dashboard pair

On the Impact page, post-purchase engagement renders as a sibling card to Interactor Conversion. Same attribution-window label, same date range, same visitor-ID logic — different time direction. The merchant can see at a glance which side contributes more.

Pairing them on the same page surfaces the asymmetry in a useful way. A merchant whose interactor conversion is high but post-purchase engagement is low has a sales-funnel contribution that drops off after purchase — fine for impulse buys, signal of a missing retention loop for higher-LTV catalogs. A merchant with the opposite shape has a strong retention story without much new-acquisition lift. Most merchants land in between.

Either way, the math doesn't hide. Pre-purchase and post-purchase are both measurable, both shown side by side, both computed from the same source-of-truth rollup. The merchant doesn't have to choose which story to believe — the dashboard tells both.

Frequently Asked Questions

What is post-purchase engagement in the Impact dashboard?

It counts orders that are followed by widget engagement within your attribution window — a returning customer who comes back after buying to ask about warranty coverage, the return policy, or order status. The Impact page surfaces both the order count and the revenue for those orders. It's value that pre-purchase conversion tracking can't see, because pre-purchase only looks at whether chat happened before the sale.

How is post-purchase engagement different from pre-purchase conversion?

It uses the same attribution window (7, 14, 30, or 60 days, set per store) and the same visitor-ID join — the only difference is the time direction. Pre-purchase asks whether there was chat in the window before an order; post-purchase asks whether there was chat in the window after. On the Impact page they render as sibling cards, so you can see which side contributes more.

Does computing this slow the dashboard down?

No. A nightly cron precomputes daily rows in a rollup table keyed by store, order date, and window, so the dashboard just sums over the date range instead of joining orders to events on every load — turning a multi-second query into milliseconds. All supported windows refresh each night, so switching your window from 7 to 30 days shows the new numbers on the next load with no backfill wait.

Try Milly Chat

Want to see how this fits your store?
We'll set up a working session.

Get it on ShopifyTalk to sales →