ShopifyCase studyHarbor Lane (demo store)

Shopify retention and CRO, tested.

Harbor Lane Coffee is an invented brand on a Shopify development store. I built the retention and conversion work that Shopify brands keep hiring for, then checked each piece with a script or a real test order: Klaviyo flows, an A/B test with a sample-size plan, a 301 redirect map, a coded Mailchimp email and GA4 purchase tracking.

Demo store: no real customers, orders or revenue. Everything here is verified behaviour, not business results.
Role
Solo: theme, Klaviyo, tracking, scripts, write-up
Stack
Shopify (Liquid, OS 2.0, Horizon) · Shopify CLI · Admin GraphQL API · Klaviyo · Mailchimp · GA4 Customer Events · Python · Puppeteer
When
November 2026
Proof
Screenshots and script output below · Code on GitHub
3Live Klaviyo flows, tested with a real checkout
60/60Redirect checks passed, one hop each
78/78Simulated A/B sessions saw the right variant
5/5GA4 ecommerce events seen in Realtime
01 / The problem

What Shopify brands actually hire for.

My Shopify proof was custom Liquid themes. When I read the Shopify job posts I was screening, the same gaps kept coming up: Klaviyo, A/B testing, Shopify CLI, CRO and the Admin GraphQL API. Upwork posts add three paid problems on top:

  • Klaviyo flows that misfire: generic cart reminders, or "you forgot something" emails sent to people who already paid.
  • Re-platforms that lose Google traffic: WooCommerce uses /product/, Shopify uses /products/, and every old URL needs a 301.
  • GA4 that sees traffic but no purchases: since Shopify moved checkout to extensibility, old checkout scripts no longer fire.

So I built a coffee store with a real catalogue and solved each of these on it. The rule for the project was that nothing counts until a script or a test order proves it.

harbor-lane-coffee · demo store
Harbor Lane Coffee home page: custom hero, fresh-roast badge and marquee
Custom Online Store 2.0 sections on Horizon. The client's brand stays the client's.
02 / What I built

Six pieces, each with a check.

1. Klaviyo: three flows that know who already bought

  • Abandoned checkout: emails at 1 hour and 24 hours with the real cart (image, variant, price) and a return link. A flow filter removes anyone who places an order after starting the flow.
  • Welcome: a split sends existing customers a thank-you and new subscribers a unique 10% code (prefix WELCOME-, expires after 7 days). After 3 days a second split re-checks for an order before any reminder goes out.
  • Post-purchase: a brewing guide straight after the order, and a review ask on day 10, once the coffee has arrived.
  • A popup and a footer form, two segments ("Engaged 30 days", "Bought once") and 8 coded templates. The flows are defined in code through Klaviyo's API.
welcome
Klaviyo welcome flow with two conditional splits
abandoned checkout
Klaviyo abandoned checkout flow: wait 1 hour, email, wait 23 hours, email
post-purchase
Klaviyo post-purchase flow: thank-you, wait 10 days, review ask
Tested with a real checkout

A test shopper started checkout and paid with Shopify's test gateway inside the hour. Klaviyo recorded every step from product view to order. The post-purchase email arrived 1 minute after the order, and the abandoned flow sent nothing, which is exactly what it should do.

email 1 · rendered from the real checkout
Abandoned cart email showing Ethiopia Guji 250g, $17, and a Return to checkout button

2. A/B test, set up properly

Shopify Rollouts isn't available on development stores, so the split runs in the theme. Variant B shows a quick add button on product cards.

  • A hypothesis, one primary metric (sessions with an add to cart), and a 50/50 cookie split that sticks across visits.
  • A QA override, exposure events, and the variant saved on the cart and sent to GA4, so it follows the customer into checkout.
  • Sample size before launch: at a 7% baseline and a +10% lift, the test needs 21,815 sessions per variant. At 1,000 visits a day and a 7% baseline, a fair test of a +10% lift takes 7 weeks.
Check (78 simulated sessions)Result
Errors0
Split A / B39 / 39
Correct page for the variant78 / 78
Same variant after reload78 / 78
Cart attribute matches variant78 / 78

3. Redirect map for a re-platform

I mapped 30 old WooCommerce-style URLs (products, categories, tags and pages) to their new Shopify addresses. The redirects were created through the Admin GraphQL API and also exported as Shopify's CSV import file. A checker requests every old URL with and without the trailing slash, then confirms one 301 hop to the right page, which answers 200.

$ python3 redirects/check_redirects.py /product/ethiopia-guji-single-origin 301 -> /products/ethiopia-guji ok /product/ethiopia-guji-single-origin/ 301 -> /products/ethiopia-guji ok /product-category/coffee/single-origin 301 -> /collections/single-origin ok /about-us 301 -> /pages/about ok ... 60/60 passed

Finding: Shopify serves /shop itself, and URL redirects only fire on a 404, so /shop can't be redirected. Old links to it have to be fixed at the source.

4. GA4 purchase tracking through Customer Events

A custom pixel sends view_item, add_to_cart, begin_checkout and purchase. Each event carries its items and the A/B variant. I verified it in GA4 Realtime with a real browser and the test order, and the purchase counted as a key event.

GA4 realtime
GA4 Realtime overview with purchase as a key event
GA4 debugview
GA4 DebugView showing add_to_cart, page_view and view_item

Three findings worth knowing if you set this up:

  • GA4 Enhanced measurement sends extra page views from inside Shopify's pixel sandbox, using the frame's URL. Turn it off and let the pixel send page_view.
  • Inside the sandbox, debug_mode on the config doesn't reach the events, so DebugView stays empty. Set it on each event.
  • GA4 drops headless-browser traffic. Scripts can prove what the pixel sends, but only a real browser proves what GA4 receives.

5. Theme sections that help people buy

Seven custom sections and three blocks on Horizon, all editable in the theme editor: quick add, sticky add to cart on mobile, a roast picker (accessible tabs), a roast meter, a brew calculator, and trust badges next to the button. Mobile Lighthouse medians on the live theme: home 89, product 88, collection 84. These are lab numbers from a shared dev-store host.

6. A hand-coded Mailchimp email

A 600 px table layout with inlined CSS and merge tags, imported as a custom-coded template, test-sent, and checked on desktop and phone. On the free plan you can import, preview and test-send it. Sending a campaign with it needs the Standard plan.

03 / Results

What was proven, and what wasn't.

PieceHow it was checkedResult
Klaviyo flowsTest profiles and a test-gateway orderEvents received · post-purchase sent in 1 min · abandoned flow correctly silent
Email templatesKlaviyo's renderer and a real send7 / 7 render with every tag filled; the coupon email (unique codes only exist on a real send) was delivered to a test inbox
A/B mechanics78 simulated sessions78 / 78 correct variant, sticky cookie, cart attribute
RedirectsChecker script60 / 60, one hop each
GA4Network capture, Realtime, DebugViewAll 5 ecommerce events, purchase as key event
Theme speedLighthouse mobile, median of 389 / 88 / 84
Stated honestly

A development store has no real visitors, so there are no conversion or revenue results here. The A/B test is built and checked with simulated sessions; a real result needs a store with enough traffic, and the sample-size table says how much. Emails went to my own test inboxes only.

04 / What I'd do next

Where it goes from here.

  • A checkout UI extension on the same store, to cover checkout extensibility.
  • Browse-abandonment and winback flows, plus SMS when there's a sending number.
  • Server-side tracking on top of the Customer Events pixel, with event IDs to remove duplicates.

On your store, the same work becomes fixed-scope jobs: a Klaviyo flow audit and fix, a redirect map with a checker for a re-platform, a purchase-tracking fix, or an A/B test setup with a sample-size plan.

More case studies
Get in touch

Need your Shopify store to keep the customers it gets?

Tell me what's leaking: emails, tracking, redirects or the product page. I'll tell you straight whether I can help.

Cairo, Egypt — US, UK & Gulf time zones LinkedIn GitHub