Why this matters
Most ecommerce shops live in Shopify Analytics or GA4. Both can show you “conversion rate” but neither tells you exactly which step is bleeding. Shopify’s funnel is product-detail to purchase as a single hop. GA4 needs 30 minutes of custom event configuration per funnel. The result: nobody runs the funnel, nobody sees the leak.
The leak is almost always one of three steps:
- Add-to-cart → checkout-started: “shipping cost shown” surprise → cart abandonment
- Checkout-started → purchase: payment friction (declined card, slow Stripe response)
- Product-view → add-to-cart: product page conversion (price, photos, reviews)
You don’t know which until you cut the funnel. Agentry’s HogQL builds it in 2 minutes and publishes the result as a dashboard you can watch every morning.
What you get
- A 4-step funnel with absolute counts and conversion % at each step
- Average time-on-step (where shoppers are hesitating)
- A public dashboard URL — pin in the founder Slack channel
Walk through it
Build the cart-abandonment funnel: product_view → add_to_cart → checkout_started → purchase. Show drop-off and time-on-step for the last 30 days.
Let me check your event vocabulary first.
agentry_list_event_names {
project_id: "default",
matching: "view|cart|checkout|purchase|order"
}
{
"events": [
{ "name": "product_viewed", "count": 142000 },
{ "name": "add_to_cart", "count": 21400 },
{ "name": "checkout_started", "count": 8800 },
{ "name": "order_completed", "count": 4200 }
]
}
Your event names are slightly different — product_viewed (not product_view), order_completed (not purchase). Adjusting and running the funnel.
agentry_run_recipe {
recipe_id: "funnel",
params: {
project_id: "default",
steps: ["product_viewed", "add_to_cart", "checkout_started", "order_completed"],
window_days: 30,
conversion_window_hours: 24
}
}
{
"steps": [
{ "name": "product_viewed", "count": 142000, "conversion": 1.000, "avg_time_to_next_s": 94 },
{ "name": "add_to_cart", "count": 21400, "conversion": 0.151, "avg_time_to_next_s": 142 },
{ "name": "checkout_started", "count": 8800, "conversion": 0.411, "avg_time_to_next_s": 380 },
{ "name": "order_completed", "count": 4200, "conversion": 0.477 }
],
"overall": 4200 / 142000 // 2.96%
}
Funnel built. The numbers tell a clear story:
- Product view → Add to cart: 15.1% (typical: 8-15% for non-DTC, 10-25% for DTC. You’re upper-mid — fine)
- Add to cart → Checkout started: 41.1% (typical: 40-60%. Slightly low. People put things in cart and bail)
- Checkout started → Purchase: 47.7% ← THE LEAK (typical: 60-80%. You’re losing ~13k orders/month here)
- Overall: 2.96% (industry baseline ~2-3%, you’re average)
The 47.7% checkout-to-purchase is the actionable number. People literally start checking out and bail. Most common cause: shipping surprise, slow Stripe page, or no Apple Pay / payment options. The 380-second avg time-on-checkout-started is suspicious — they’re sitting there for 6+ minutes thinking.
Let me publish this so you can watch it improve as you fix the checkout.
agentry_publish_query {
recipe_id: "funnel",
description: "Cart Abandonment Funnel (30d)",
params: {
steps: ["product_viewed", "add_to_cart", "checkout_started", "order_completed"],
window_days: 30
}
}
{ "publication_id": "pub_cart_1", "public_url": "https://agentry.sh/q/pub_cart_1?key=agp_…" }
The output
Cart Abandonment Funnel (30d)
product_viewed 142,000 ────────────── 100%
↓ 94s avg 21,400 ▎ 15.1% (industry typical: 8-15%) ✓
add_to_cart 21,400 ▎ 15.1%
↓ 142s avg 8,800 ▎ 6.2% (industry typical: 6-10%) ✓
checkout_started 8,800 ▎ 6.2%
↓ 380s avg 4,200 ▎ 3.0% (industry typical: 4-5%) ✗
order_completed 4,200 ▎ 3.0%
Headline: 53% drop at checkout (4,600 abandoned orders/month) ★
Likely causes:
- Slow checkout page load (380s avg time suggests session timing out)
- Surprise shipping cost only shown at checkout
- No Apple Pay / Google Pay / Stripe Link
- Required account creation (vs guest checkout)
Public dashboard:
https://agentry.sh/q/pub_cart_1?key=agp_xxx
Suggested next investigations:
- stripe-payment-failure: are declines causing the bail-out?
- checkout-completion-time: split p99 by device (mobile is usually 8x worse)
Setting it up
You need 4 events with stable distinct_id per shopper. For guest checkout, use a visitor id from a first-party cookie:
// Get or create visitor id (cookie/localStorage)
function getVisitorId(): string {
let id = localStorage.getItem("visitor_id");
if (!id) {
id = crypto.randomUUID();
localStorage.setItem("visitor_id", id);
}
return id;
}
const distinct_id = currentUser?.email ?? getVisitorId();
// Fire on each step
async function track(event: string, properties: Record<string, unknown> = {}) {
await fetch(`https://api.agentry.sh/v1/analytics/${process.env.AGENTRY_PROJECT_ID}/`, {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.AGENTRY_DSN}`,
"Content-Type": "application/json",
"User-Agent": "myshop/1.0", // REQUIRED — Cloudflare 403s default UAs
},
body: JSON.stringify({ event, distinct_id, properties }),
});
}
// Product page
track("product_viewed", { sku: p.sku, price: p.price, category: p.category });
// Add to cart
track("add_to_cart", { sku: p.sku, qty, cart_total: cart.total });
// Begin checkout
track("checkout_started", { cart_value: cart.total, item_count: cart.items.length });
// Confirmation page
track("order_completed", { order_id: order.id, total: order.total, items: order.items.length });
If you’re on Shopify, the events fire by default with Shopify Analytics — you can swap the destination to Agentry by adding a Web Pixel script that pipes events to the Agentry analytics endpoint.
Variations
- “Same funnel but only for mobile traffic. The drop-off is usually 2-3x worse on mobile.”
- “Cart abandonment by SKU — are certain products driving the bail-outs?”
- “What’s the average cart value of abandoned vs completed orders? Are big carts more likely to bail?”
- “Weekly cron: post the previous week’s funnel snapshot to #shop-ops every Monday morning.”