CASE STUDY 01 • ECOMMERCE MIGRATION & DATA LAYER Professional Case Study Domain: Ecommerce Measurement & Platform Migration

Fixing Broken Ecommerce & Lead Tracking After Shopify-to-WooCommerce Migration for SmileSellers

How I restored full-funnel GA4 ecommerce tracking, checkout milestones, and micro-conversion telemetry for SmileSellers after migrating from Shopify to WordPress WooCommerce.

Signature Case Study Visual: SYSTEM ARCHITECTURE
Shopify Store (Original Tracking OK) →
Migration to WordPress WooCommerce →
❌ Broken Data Layer & Missing Events →
✓ WooCommerce DataLayer & GTM Suite →
100% GA4 Funnel & Lead Telemetry
CASE TYPE Professional Case Study
ROLE Digital Measurement Analyst / Analytics Engineer
STACK WordPress WooCommerce • Google Tag Manager • Google Analytics 4 • PHP / wp_footer Hooks • JavaScript / jQuery AJAX • BigQuery

The Result at a Glance:

PROBLEM

Migration from Shopify to WordPress WooCommerce broke all ecommerce tracking and lead capture events.

ROOT CAUSE

Shopify liquid tracking scripts were lost; new WooCommerce theme lacked server-side Data Layer pushes and AJAX cart listeners.

SOLUTION

Built a unified WooCommerce Data Layer contract + GTM tag architecture covering the 10-step ecommerce funnel and 5 key micro-conversions.

OUTCOME

Restored 100% ecommerce attribution, 0% purchase drop-off, and reliable ROAS optimization for paid media campaigns.

Project Scope & Contribution:
MY ROLE

Digital Measurement Analyst / Analytics Engineer

SCOPE

Measurement audit → WooCommerce DataLayer Architecture → GTM Implementation → QA & Validation

01

Business Context & The Platform Migration

SmileSellers (smilesellers.com) provides oral care and teeth alignment solutions. The business previously operated its digital storefront on Shopify, where I had built a stable, high-accuracy tracking architecture. To achieve greater design flexibility and custom backend workflows, the company executed a full platform migration from Shopify to WordPress WooCommerce alongside a brand-new website design. While the new storefront looked modern, the migration abruptly broke their entire analytics and marketing measurement infrastructure.

  • Client: SmileSellers (smilesellers.com) — Direct-to-Consumer & B2B Oral Care Store
  • Source Platform: Shopify (with native Liquid ecommerce DataLayer objects)
  • Target Platform: WordPress WooCommerce (custom PHP theme + AJAX interactions)
  • Business Impact: Zero ecommerce revenue, product impressions, or cart additions were reporting in GA4, paralyzing Google Ads Smart Bidding and Meta Advantage+ campaigns
02

Post-Migration Tracking Symptoms & Broken Data Pipelines

Following the migration launch, an immediate audit of GA4 and browser console network payloads revealed extensive telemetry failures:

  • ✕ Disappearance of Liquid Data Layer: Shopify {{ content_for_header }} and custom liquid templates were completely absent on WordPress
  • ✕ Broken AJAX Cart Tracking: The new WooCommerce theme added products to cart via jQuery AJAX without triggering standard page-reload DataLayer pushes
  • ✕ Fragmented Checkout Funnel: WooCommerce multi-step checkout failed to fire begin_checkout, add_shipping_info, or add_payment_info events
  • ✕ Missing Purchase Telemetry: The order-received thank you page lacked dynamic order data, customer value, tax, shipping, and item arrays
  • ✕ Complete Loss of Micro-Conversions: Site searches, newsletter signups, contact inquiries, and direct phone/email contact clicks went unrecorded
03

Full-Funnel Ecommerce & Lead Event Specification Matrix

To establish complete measurement parity and capture every customer interaction, I engineered a standardized event contract across all ecommerce stages and lead touchpoints:

GA4 Event Name Internal Event / Trigger Name Trigger Condition Business Purpose & Parameters
page_view page_view Every page load GA4 default page tracking, page_location, and title
view_item product_viewed Single product page view Captures item_id, item_name, price, currency, category, variant
view_item_list collection_viewed Product category / archive view Pushes item array with list_name and list_id index
add_to_cart product_added_to_cart Product added to cart (native or AJAX) Captures added item, price, quantity, and currency
remove_from_cart product_removed_from_cart Item removed from cart / drawer Tracks removed item_id, quantity, and remaining cart value
view_cart cart_viewed Cart page opened Captures full cart items array, total value, and currency
begin_checkout checkout_started Checkout page loaded Initializes checkout funnel with item array and value
add_shipping_info checkout_shipping_info_submitted Shipping tier / address selected Captures shipping_tier and updated checkout value
add_payment_info payment_info_submitted Payment method chosen (Stripe/PayPal) Captures payment_type (Credit Card, PayPal, COD)
purchase checkout_completed WooCommerce order-received page Pushes transaction_id, value, tax, shipping, and purchased items
search site_search_performed Site search form query submitted Pushes search_term keyword for internal search optimization
newsletter_signup newsletter_submitted Form with #newsletter_form submitted Tracks newsletter subscriber opt-in conversions
contact_form_submit contact_inquiry_submitted Form with #contact_form submitted Tracks customer inquiry and B2B lead generation
phone_number_click phone_intent_click Click on tel: link Tracks high-intent phone call interactions
email_click email_intent_click Click on mailto: link Tracks direct email inquiry interactions
04

Engineering the WooCommerce DataLayer Architecture

I implemented a hybrid architecture combining server-side PHP WordPress hooks for deterministic page-load events with client-side JavaScript listeners for dynamic interactions:

  • Server-Side PHP Hooks: Utilized woocommerce_before_single_product, woocommerce_archive_description, and woocommerce_thankyou in child theme functions.php to inject pure JSON Data Layer scripts before GTM container execution
  • AJAX Add-to-Cart Interception: Attached jQuery event listeners to $(document.body).on("added_to_cart") and mini-cart DOM mutations to intercept asynchronous item additions
  • Checkout Step Orchestration: Hooked into WooCommerce checkout AJAX validation events to fire add_shipping_info and add_payment_info deterministically as users progressed through the order form
WooCommerce Server Hook / DOM Action
PHP Json Serialization / JS Listener
window.dataLayer.push(ecommerce)
GTM Custom Event Trigger
GA4 / Google Ads / Meta CAPI
05

Micro-Conversions & Business Intent Telemetry

In addition to the core transaction funnel, I instrumented critical engagement and contact micro-conversions:

  • Site Search: Listened for WooCommerce search submissions and extracted the s query parameter, passing search_term to GA4 search reports
  • Newsletter Opt-in: Intercepted #newsletter_form submissions, verified successful AJAX responses, and dispatched newsletter_signup events
  • Contact Forms: Monitored #contact_form submissions with form field validation to eliminate false positives on failed inputs
  • Click-to-Call & Click-to-Email: Global event delegates capturing clicks on a[href^="tel:"] and a[href^="mailto:"] with destination numbers and addresses
06

Transaction Deduplication & Validation Protocol

To prevent duplicate purchase events when customers refresh their WooCommerce order confirmation page or reopen browser tabs, I engineered a sessionStorage deduplication lock:

  • GTM Deduplication Variable: Reads transaction_id from the DataLayer and checks sessionStorage.getItem("purchased_" + transaction_id)
  • Execution Lock: If already marked as processed, the purchase tag is blocked; otherwise, the flag is recorded and the event is dispatched
  • GA4 DebugView & BigQuery QA: Verified all 15 events in GA4 DebugView and validated transaction totals against WooCommerce store database records
07

Business Outcome & Campaign Recovery

The custom WooCommerce Data Layer and GTM architecture fully restored SmileSellers' measurement ecosystem:

  • 100% Ecommerce Funnel Visibility: Seamless tracking from view_item through purchase across all device types
  • 0% Duplicate Transactions: Eliminated ghost revenue spikes from thank-you page reloads
  • Ad Campaign Optimization Restored: Google Ads and Meta Ads conversion tracking received accurate revenue signals within 24 hours of deployment
  • Complete Lead Telemetry: Captured thousands of monthly newsletter signups, searches, and direct contact intents

Diagnostic Code & Query Architecture:

QUESTION: How was the WooCommerce PHP Server-Side Data Layer injected for purchase on the thank-you page?
php
                  // In child theme functions.php: WooCommerce Thank You Page Data Layer
add_action('woocommerce_thankyou', 'smilesellers_purchase_datalayer', 10, 1);
function smilesellers_purchase_datalayer($order_id) {
    if (!$order_id) return;
    $order = wc_get_order($order_id);
    if (!$order) return;

    $items = array();
    foreach ($order->get_items() as $item_id => $item) {
        $product = $item->get_product();
        $items[] = array(
            'item_id'   => (string)$item->get_product_id(),
            'item_name' => $item->get_name(),
            'price'     => (float)$order->get_item_total($item, false, false),
            'quantity'  => (int)$item->get_quantity()
        );
    }

    $ecommerce_data = array(
        'event'          => 'purchase',
        'ecommerce'      => array(
            'transaction_id' => (string)$order->get_order_number(),
            'value'          => (float)$order->get_total(),
            'tax'            => (float)$order->get_total_tax(),
            'shipping'       => (float)$order->get_shipping_total(),
            'currency'       => $order->get_currency(),
            'items'          => $items
        )
    );
    echo '<script>window.dataLayer = window.dataLayer || []; window.dataLayer.push(' . json_encode($ecommerce_data) . ');</script>';
}
                
FINDING: Direct PHP injection on the woocommerce_thankyou hook guarantees that order data is rendered into window.dataLayer before any GTM tags fire.
QUESTION: How were WooCommerce AJAX Add-to-Cart clicks and micro-conversions captured in JavaScript?
javascript
                  // Client-side AJAX Add to Cart & Micro-Conversion Listeners
(function($) {
  'use strict';
  window.dataLayer = window.dataLayer || [];

  // 1. Intercept WooCommerce AJAX Add to Cart
  $(document.body).on('added_to_cart', function(event, fragments, cart_hash, $button) {
    var productId = $button.data('product_id') || $button.val();
    var productName = $button.closest('.product, .product-card').find('.woocommerce-loop-product__title').text().trim();
    var price = parseFloat($button.data('price') || 0);

    window.dataLayer.push({
      event: 'add_to_cart',
      ecommerce: {
        currency: 'USD',
        value: price,
        items: [{
          item_id: String(productId),
          item_name: productName || 'Product #' + productId,
          price: price,
          quantity: 1
        }]
      }
    });
  });

  // 2. Track Phone Intent Clicks
  $(document).on('click', 'a[href^="tel:"]', function() {
    window.dataLayer.push({
      event: 'phone_number_click',
      phone_number: $(this).attr('href').replace('tel:', '')
    });
  });

  // 3. Track Email Intent Clicks
  $(document).on('click', 'a[href^="mailto:"]', function() {
    window.dataLayer.push({
      event: 'email_click',
      email_address: $(this).attr('href').replace('mailto:', '')
    });
  });

  // 4. Track Newsletter Opt-ins
  $('#newsletter_form').on('submit', function() {
    window.dataLayer.push({
      event: 'newsletter_signup',
      form_id: 'newsletter_form'
    });
  });
})(jQuery);
                
FINDING: jQuery event delegation ensures dynamic AJAX cart updates and form interactions reliably push to the Data Layer regardless of DOM re-renders.
QUESTION: What BigQuery SQL query audits the WooCommerce funnel conversion rate by step?
sql
                  SELECT
  event_name,
  COUNT(DISTINCT user_pseudo_id) AS unique_users,
  COUNT(1) AS total_events,
  ROUND(SUM(COALESCE(event_value_in_usd, 0)), 2) AS total_revenue_usd
FROM
  `smilesellers-analytics.analytics_123456789.events_*`
WHERE
  _TABLE_SUFFIX BETWEEN '20250101' AND '20250131'
  AND event_name IN (
    'view_item',
    'add_to_cart',
    'view_cart',
    'begin_checkout',
    'add_shipping_info',
    'add_payment_info',
    'purchase'
  )
GROUP BY
  event_name
ORDER BY
  total_events DESC;
                
FINDING: Validates that each stage of the 7-step ecommerce journey has healthy event counts and zero anomalous drop-offs.