Fix Broken Klaviyo Checkout URLs on Shopify (The Permanent Solution)
Your abandoned cart flow is running. Open rates look great. Customers click "Return to Cart." And they land on your homepage.
Not checkout. Not their cart. Your homepage.
If you've searched "klaviyo checkout url not working" or spent hours in the Klaviyo community troubleshooting {{ event.extra.checkout_url }}, you're not alone. This is one of the most common and frustrating issues Shopify merchants face with Klaviyo, and it has been for years.
The fix isn't another Klaviyo tag. It's rethinking how your abandoned cart links work.
The Problem: Why Klaviyo's Checkout URL Breaks
Klaviyo's {{ event.extra.checkout_url }} pulls a URL directly from Shopify when the "Checkout Started" event fires. That URL is a session-specific checkout link tied to the customer's browser session.
Here's why it breaks:
Session expiration. Shopify's checkout URLs are tied to a browser session. When the customer opens your email on a different device, a different browser, or even a different tab, the session data doesn't carry over. The link redirects to your homepage because the checkout session no longer exists.
The customer already purchased. If a customer completes their order after starting checkout, Shopify empties and invalidates that checkout session. When they click your recovery email (or when you preview the email in Klaviyo), the link goes nowhere. Shopify redirects to the homepage because the checkout is "completed."
Custom domain issues. The checkout URL Shopify passes to Klaviyo uses your myshopify.com domain, not your custom domain. If you've configured redirects or have apps that modify checkout routing, the URL can break in transit.
Apps interfering. Checkout customization apps, post-purchase apps, and even certain tracking scripts can conflict with Shopify's ability to generate a valid recovery URL. Klaviyo's own community moderators have confirmed this: "if you are using an app within Shopify that customizes the checkout page, that app could be conflicting with Shopify's ability to properly generate a recover cart URL."
The "Added to Cart" gap. {{ event.extra.checkout_url }} only works on flows triggered by "Checkout Started" — not "Added to Cart." If you're building a browse abandonment or cart abandonment flow triggered by a different metric, the checkout URL simply doesn't exist. There's no URL to pull.
The Workaround Everyone Tries (And Why It's Fragile)
The most common workaround in the Klaviyo community is to manually reconstruct a cart permalink using Liquid loops:
{% with event.extra.line_items as items %}
{{ organization.url|trim_slash }}/cart/
{% for item in items %}
{{ item.variant_id }}:{{ item.quantity|floatformat:'0' }}
{% if not forloop.last %},{% endif %}
{% endfor %}
{% endwith %}?checkout%5Bemail%5D={{ email }}
This bypasses the broken checkout URL by building a cart permalink from the event's line item data. It works. Sometimes.
But it has serious limitations:
- No discount. Cart permalinks don't support automatic discounts. If your abandoned cart strategy includes a recovery incentive, the customer has to remember and enter a code manually.
- No attribution. You have no way to track which email tier drove the conversion. You can't tell whether your first email (no discount) or your third email (15% off) is the one that actually works.
- Fragile formatting. One wrong character in that Liquid loop and the link breaks silently. You'll discover it when a customer emails you saying the link "doesn't work."
- No escalation. You can't offer tiered incentives (5% on email 1, 10% on email 2, 15% on email 3) through a cart permalink. It's one link, one experience.
You can also try {{ event.extra.responsive_checkout_url }} — another Klaviyo variable that sometimes resolves the issue. But it's the same session-based URL with the same fundamental problem. If the session is gone, the link is gone.
The Fix: Checkout Links That Don't Depend on Sessions
Checkout Links takes a completely different approach to abandoned cart recovery. Instead of relying on Shopify's session-based checkout URLs, it creates permanent checkout links that accept cart contents via URL parameters.
The link never expires. It works on any device. It doesn't depend on a browser session. And it adds things Klaviyo's default checkout URL can't: automatic discounts, tiered promotions, free gifts, free shipping, and full attribution tracking.
Here's the difference:
Klaviyo checkout_url |
Checkout Links | |
|---|---|---|
| Session-dependent | Yes — breaks across devices | No — works anywhere |
| Expires | Yes — when checkout session ends | No — permanent link |
| Works on "Added to Cart" | No — only "Checkout Started" | Yes — any flow trigger |
| Automatic discounts | No | Yes — tiered by cart value |
| Free shipping | No | Yes — configurable thresholds |
| Free gifts | No | Yes — add bonus products |
| Attribution tracking | No | Yes — per-link analytics |
| A/B testing | No | Yes — built in |
| Custom domain | Uses myshopify.com | Uses your store domain |
| Price | Free (included with Klaviyo) | $25/month |
How to Set It Up (10 Minutes)
Step 1: Create Your Abandoned Cart Link
Install Checkout Links and create a new link.
- Name: "Abandoned Cart Recovery" (or whatever helps you identify it)
- Custom slug:
/abandoned-cart - Dynamic mode: ON
Turning on Dynamic mode allows the link to accept cart contents through a URL parameter. This is what replaces Klaviyo's broken checkout_url.
Step 2: Add Recovery Promotions
This is where it gets interesting. Instead of a flat discount code that customers have to remember, you set up tiered promotions that apply automatically based on cart value.
Open the Promotions section and configure tiers:
| Cart Total | Offer |
|---|---|
| Under $50 | Free shipping |
| $50 - $150 | Free shipping + 10% off |
| $150+ | Free shipping + 15% off |
A customer who abandoned a $30 cart gets free shipping. A customer who abandoned a $200 cart gets free shipping and 15% off. One link handles both scenarios automatically.
Don't give away margin you don't have to. Most cart abandoners will come back with free shipping alone. Reserve the bigger discounts for the bigger carts where the ROI makes sense.
Step 3: Replace the Link in Klaviyo
Open your Abandoned Checkout flow in Klaviyo. Find the CTA button that currently uses {{ event.extra.checkout_url }}.
Replace it with your Checkout Links URL plus a Klaviyo variable that passes the cart contents:
https://yourstore.com/abandoned-cart?li={% for item in event.extra.line_items %}{{ item.variant_id }},{{ item.quantity|floatformat:0 }}{% if not forloop.last %}:{% endif %}{% endfor %}
That's it. The ?li= parameter passes each variant ID and quantity from the Klaviyo event data. When the customer clicks, Checkout Links loads their exact cart and applies the matching promotion tier.
Step 4: Build a Tiered Email Sequence
Now that your link handles tiered promotions automatically, you can create a multi-email sequence where each email uses the same link but the customer's urgency increases:
Email 1 (1 hour after abandonment): "You left something behind." No mention of a discount — just a reminder with the checkout link. Many customers will come back for free shipping alone.
Email 2 (24 hours): "Still thinking it over? Here's 10% off." Same link. If their cart is over $50, the discount applies automatically. Under $50, they still get free shipping.
Email 3 (72 hours): "Last chance — 15% off expires soon." Same link. Pair this with Checkout Links' scheduling feature to set a real expiration. When you say the offer expires, make it expire.
You can use Checkout Links' scheduling feature to set an actual expiration on the link for your final email. Real urgency converts better than fake urgency.
Step 5: Add UTM Tracking
Append UTM parameters to track which email in the sequence drives conversions:
https://yourstore.com/abandoned-cart?li={% for item in event.extra.line_items %}{{ item.variant_id }},{{ item.quantity|floatformat:0 }}{% if not forloop.last %}:{% endif %}{% endfor %}&utm_source=klaviyo&utm_medium=email&utm_campaign=abandoned_cart_1
Change abandoned_cart_1 to abandoned_cart_2 and abandoned_cart_3 for your second and third emails.
Beyond Abandoned Cart: Browse Abandonment
Here's something Klaviyo's checkout_url simply cannot do: browse abandonment recovery.
If a customer views a product page and leaves without adding to cart, Klaviyo tracks the "Viewed Product" event. But there's no checkout URL to pull — the customer never started a checkout.
With Checkout Links, you can create a link that pre-loads the browsed product:
https://yourstore.com/browse-recovery?li={{ event.extra.variant_id }},1
The customer gets an email saying "Still interested in [product name]?" with a link that takes them straight to checkout with the product already loaded. Add free shipping as an incentive and you're recovering revenue from visitors who never even reached the cart.
What This Looks Like in Practice
A Shopify store running Checkout Links in their Klaviyo abandoned cart flow sees:
- Zero broken links. The link doesn't depend on Shopify sessions. It works on any device, any browser, weeks later.
- Automatic tiered recovery. High-value carts get bigger incentives. Low-value carts get free shipping. One link, no code.
- Full attribution. You know exactly how much revenue each email in the sequence recovered, which tier converted, and your overall recovery rate.
- Pre-checkout review. Customers can see their cart and discount before entering payment info. This flexibility actually increases conversion — they can adjust quantities or swap variants without starting over.
Common Questions
What if I'm using the "Added to Cart" trigger instead of "Checkout Started"?
This is actually where Checkout Links shines. Klaviyo's checkout_url doesn't exist on "Added to Cart" events. Checkout Links' ?li= parameter works with any event that includes line item data, regardless of trigger.
Can I use this with Klaviyo SMS flows too?
Yes. The link works in SMS exactly the same way. Shorter URLs work better for SMS — set a short custom slug like /ac.
Does this work with custom Shopify domains? Yes. Checkout Links uses your store's custom domain. No myshopify.com redirects.
What happens if the product goes out of stock? Checkout Links handles this gracefully. If a product is out of stock, the customer sees the pre-checkout review page where they can adjust their cart rather than hitting an error.
Stop Sending Customers to Your Homepage
Every abandoned cart email that sends a customer to your homepage instead of checkout is lost revenue. Not because your email was bad — because your link was broken.
Klaviyo's {{ event.extra.checkout_url }} was designed when Shopify's checkout worked differently. Session-based URLs made sense when customers used one device and one browser. That's not how people shop anymore.
Your customer starts on their phone, gets your email on their laptop, and clicks from their tablet. The link needs to work everywhere, every time.
Checkout Links costs $25/month. No percentage of sales. 7-day free trial. It takes 10 minutes to set up in your existing Klaviyo flow.
If your abandoned cart emails are your highest-performing revenue channel (and they should be), they deserve a link that actually works.
Fix your abandoned cart links →
Already using Checkout Links? Check out our guides for win-back flows and reorder campaigns to get even more out of your Klaviyo integration.