Where exactly do shoppers drop off in checkout?

Build the product-view to purchase funnel with drop-off and time-on-step. The 1-prompt ecommerce funnel that Shopify analytics doesn't ship.

Published

difficulty beginner · time to value 2 minutes · tools used 3

Just say this

Build the cart-abandonment funnel: product_view → add_to_cart → checkout_started → purchase. Show drop-off and average time-on-step for the last 30 days.

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:

  1. Add-to-cart → checkout-started: “shipping cost shown” surprise → cart abandonment
  2. Checkout-started → purchase: payment friction (declined card, slow Stripe response)
  3. 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

You

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.

Agent

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 }
  ]
}
Agent

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%
}
Agent

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.”

Try this recipe in your own agent.

Paste the prompt above into your agent. It'll set up Agentry against your data, then run the recipe and show you the real output.

Install https://agentry.sh/agentry.md and set it up