GA4 Ecommerce Tracking on Ecwid | OpsBlu Docs

GA4 Ecommerce Tracking on Ecwid

Complete guide to implementing enhanced ecommerce tracking for Ecwid stores using Google Analytics 4.

Ecwid provides comprehensive ecommerce tracking capabilities for GA4, allowing you to track the complete customer journey from product discovery to purchase.

Ecommerce Tracking Overview

GA4's ecommerce tracking captures:

  • Product Impressions: Which products customers see
  • Product Interactions: Clicks, add to cart, remove from cart
  • Checkout Process: Each step of the purchase funnel
  • Transactions: Complete order details with revenue
  • Refunds: Refunded transactions (manual implementation)

Implementation Methods

Method 1: Ecwid Built-in Integration

Best for: Quick setup, Venture plan or higher.

Enable in Ecwid Control Panel → Settings → General → Tracking & Analytics:

  1. Add GA4 Measurement ID
  2. Toggle Track ecommerce to ON
  3. Toggle Enhanced ecommerce to ON
  4. Save

What's tracked automatically:

  • ✓ Product views
  • ✓ Add to cart / remove from cart
  • ✓ Checkout steps
  • ✓ Purchases with full transaction data
  • ✓ Product list impressions

Limitations:

  • No customization of event parameters
  • Cannot add custom dimensions
  • Limited control over data structure

Method 2: Custom JavaScript Implementation

Best for: Full control, custom parameters, any Ecwid plan.

Implement using Ecwid JavaScript API in Settings → General → Tracking & Analytics → Custom JavaScript Code.

Method 3: Google Tag Manager

Best for: Enterprise setups, multiple tags, consent management.

Configure ecommerce events as GTM tags with Ecwid data layer variables.

See GTM Data Layer for implementation.

Complete Custom Implementation

This section provides complete code for custom GA4 ecommerce tracking.

Setup Base Configuration

Add to Ecwid's Custom JavaScript Code section:

<!-- Google Analytics 4 Ecommerce Tracking -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  // Configure GA4
  gtag('config', 'G-XXXXXXXXXX', {
    'send_page_view': true,
    'currency': 'USD', // Set your default currency
    'allow_google_signals': true
  });

  // Ecommerce tracking implementation
  Ecwid.OnAPILoaded.add(function() {
    console.log('Ecwid Ecommerce Tracking Initialized');

    // Product Impressions (List Views)
    trackProductImpressions();

    // Product Detail Views
    trackProductViews();

    // Add to Cart
    trackAddToCart();

    // Remove from Cart
    trackRemoveFromCart();

    // Checkout Process
    trackCheckoutProcess();

    // Purchase
    trackPurchase();
  });

  // Implementation functions below...
</script>

Replace G-XXXXXXXXXX with your GA4 Measurement ID.

Track Product Impressions

When customers view product lists (categories, search results):

function trackProductImpressions() {
  Ecwid.OnPageLoad.add(function(page) {

    if (page.type === 'CATEGORY' || page.type === 'SEARCH') {
      var listName = page.type === 'CATEGORY' ?
        'Category' : 'Search Results';

      var listId = page.type === 'CATEGORY' ?
        page.categoryId.toString() : 'search';

      // Fetch products for current page
      var params = {
        limit: 100 // Adjust based on your pagination
      };

      if (page.type === 'CATEGORY') {
        params.categoryId = page.categoryId;
      } else if (page.type === 'SEARCH') {
        params.keyword = page.keywords;
      }

      Ecwid.getProducts(params, function(searchResult) {
        if (searchResult.items && searchResult.items.length > 0) {

          var items = searchResult.items.map(function(product, index) {
            return {
              item_id: product.id.toString(),
              item_name: product.name,
              item_brand: product.brand || '',
              item_category: getCategoryHierarchy(product.categoryIds),
              item_list_name: listName,
              item_list_id: listId,
              price: product.defaultDisplayedPrice,
              index: index,
              quantity: 1
            };
          });

          gtag('event', 'view_item_list', {
            item_list_id: listId,
            item_list_name: listName,
            items: items
          });
        }
      });
    }
  });
}

// Helper: Get category hierarchy
function getCategoryHierarchy(categoryIds) {
  if (!categoryIds || categoryIds.length === 0) return '';
  // For simplicity, return first category
  // Optionally fetch full category path with Ecwid.getCategory()
  return 'Category ' + categoryIds[0];
}

Track Product Views

When customers view individual product pages:

function trackProductViews() {
  Ecwid.OnPageLoad.add(function(page) {

    if (page.type === 'PRODUCT') {
      Ecwid.getProduct(page.productId, function(product) {

        // Get selected variant if applicable
        var variant = getSelectedVariant(product);
        var price = variant ? variant.price : product.defaultDisplayedPrice;

        gtag('event', 'view_item', {
          currency: product.currency || 'USD',
          value: price,
          items: [{
            item_id: product.id.toString(),
            item_name: product.name,
            item_brand: product.brand || '',
            item_category: getCategoryHierarchy(product.categoryIds),
            item_category2: product.categoryIds[1] ? 'Category ' + product.categoryIds[1] : '',
            item_variant: variant ? variant.sku : '',
            price: price,
            quantity: 1
          }]
        });
      });
    }
  });
}

// Helper: Get selected product variant
function getSelectedVariant(product) {
  if (!product.combinations || product.combinations.length === 0) {
    return null;
  }
  // Return first available combination
  // In practice, track actual user selection
  return product.combinations[0];
}

Track Add to Cart

When customers add items to their cart:

function trackAddToCart() {
  var previousCart = null;

  Ecwid.OnCartChanged.add(function(cart) {

    // Initialize on first load
    if (previousCart === null) {
      previousCart = JSON.parse(JSON.stringify(cart));
      return;
    }

    // Detect item additions
    if (cart.items.length > previousCart.items.length) {

      // Find newly added item
      var newItems = cart.items.filter(function(cartItem) {
        return !previousCart.items.some(function(prevItem) {
          return prevItem.id === cartItem.id;
        });
      });

      newItems.forEach(function(item) {
        gtag('event', 'add_to_cart', {
          currency: cart.currency || 'USD',
          value: item.price * item.quantity,
          items: [{
            item_id: item.product.id.toString(),
            item_name: item.product.name,
            item_brand: item.product.brand || '',
            item_category: item.product.categoryIds ? 'Category ' + item.product.categoryIds[0] : '',
            item_variant: formatVariant(item.selectedOptions),
            price: item.price,
            quantity: item.quantity
          }]
        });
      });
    }

    // Detect quantity increases
    if (cart.items.length === previousCart.items.length) {
      cart.items.forEach(function(cartItem) {
        var prevItem = previousCart.items.find(function(prev) {
          return prev.id === cartItem.id;
        });

        if (prevItem && cartItem.quantity > prevItem.quantity) {
          var qtyAdded = cartItem.quantity - prevItem.quantity;

          gtag('event', 'add_to_cart', {
            currency: cart.currency || 'USD',
            value: cartItem.price * qtyAdded,
            items: [{
              item_id: cartItem.product.id.toString(),
              item_name: cartItem.product.name,
              price: cartItem.price,
              quantity: qtyAdded
            }]
          });
        }
      });
    }

    // Update reference
    previousCart = JSON.parse(JSON.stringify(cart));
  });
}

// Helper: Format variant options
function formatVariant(selectedOptions) {
  if (!selectedOptions || selectedOptions.length === 0) return '';
  return selectedOptions.map(function(opt) {
    return opt.name + ': ' + opt.value;
  }).join(', ');
}

Track Remove from Cart

When customers remove items from cart:

function trackRemoveFromCart() {
  var previousCart = null;

  Ecwid.OnCartChanged.add(function(cart) {

    if (previousCart === null) {
      previousCart = JSON.parse(JSON.stringify(cart));
      return;
    }

    // Detect item removals
    if (cart.items.length < previousCart.items.length) {

      // Find removed items
      var removedItems = previousCart.items.filter(function(prevItem) {
        return !cart.items.some(function(cartItem) {
          return cartItem.id === prevItem.id;
        });
      });

      removedItems.forEach(function(item) {
        gtag('event', 'remove_from_cart', {
          currency: cart.currency || 'USD',
          value: item.price * item.quantity,
          items: [{
            item_id: item.product.id.toString(),
            item_name: item.product.name,
            price: item.price,
            quantity: item.quantity
          }]
        });
      });
    }

    // Detect quantity decreases
    if (cart.items.length === previousCart.items.length) {
      cart.items.forEach(function(cartItem) {
        var prevItem = previousCart.items.find(function(prev) {
          return prev.id === cartItem.id;
        });

        if (prevItem && cartItem.quantity < prevItem.quantity) {
          var qtyRemoved = prevItem.quantity - cartItem.quantity;

          gtag('event', 'remove_from_cart', {
            currency: cart.currency || 'USD',
            value: cartItem.price * qtyRemoved,
            items: [{
              item_id: cartItem.product.id.toString(),
              item_name: cartItem.product.name,
              price: cartItem.price,
              quantity: qtyRemoved
            }]
          });
        }
      });
    }

    previousCart = JSON.parse(JSON.stringify(cart));
  });
}

Track Checkout Process

Track each step of the checkout funnel:

function trackCheckoutProcess() {
  var checkoutSteps = {
    CHECKOUT_ADDRESS: { step: 1, name: 'Address Information' },
    CHECKOUT_SHIPPING: { step: 2, name: 'Shipping Method' },
    CHECKOUT_PAYMENT: { step: 3, name: 'Payment Information' }
  };

  var trackedSteps = {};

  Ecwid.OnPageLoad.add(function(page) {

    // Begin checkout (first step)
    if (page.type === 'CHECKOUT_ADDRESS' && !trackedSteps['begin_checkout']) {
      trackedSteps['begin_checkout'] = true;

      Ecwid.Cart.get(function(cart) {
        gtag('event', 'begin_checkout', {
          currency: cart.currency || 'USD',
          value: cart.total,
          items: cart.items.map(function(item) {
            return {
              item_id: item.product.id.toString(),
              item_name: item.product.name,
              price: item.price,
              quantity: item.quantity
            };
          })
        });
      });
    }

    // Shipping info added
    if (page.type === 'CHECKOUT_PAYMENT' && !trackedSteps['add_shipping_info']) {
      trackedSteps['add_shipping_info'] = true;

      Ecwid.Cart.get(function(cart) {
        var shippingOption = cart.shippingOption || {};

        gtag('event', 'add_shipping_info', {
          currency: cart.currency || 'USD',
          value: cart.total,
          shipping_tier: shippingOption.shippingMethodName || 'Standard',
          items: cart.items.map(function(item) {
            return {
              item_id: item.product.id.toString(),
              item_name: item.product.name,
              price: item.price,
              quantity: item.quantity
            };
          })
        });
      });
    }

    // Payment info (payment page reached)
    if (page.type === 'CHECKOUT_PAYMENT' && !trackedSteps['add_payment_info']) {
      trackedSteps['add_payment_info'] = true;

      Ecwid.Cart.get(function(cart) {
        gtag('event', 'add_payment_info', {
          currency: cart.currency || 'USD',
          value: cart.total,
          payment_type: 'Unknown', // Ecwid API doesn't expose this
          items: cart.items.map(function(item) {
            return {
              item_id: item.product.id.toString(),
              item_name: item.product.name,
              price: item.price,
              quantity: item.quantity
            };
          })
        });
      });
    }

    // Reset when leaving checkout
    if (!checkoutSteps[page.type]) {
      trackedSteps = {};
    }
  });
}

Track Purchase

When order is successfully completed:

function trackPurchase() {
  var purchaseTracked = false;

  Ecwid.OnOrderPlaced.add(function(order) {

    // Prevent duplicate tracking
    if (purchaseTracked) return;
    purchaseTracked = true;

    gtag('event', 'purchase', {
      transaction_id: order.vendorOrderNumber,
      value: order.total,
      tax: order.tax || 0,
      shipping: order.shippingOption ? order.shippingOption.shippingRate : 0,
      currency: order.currency || 'USD',
      coupon: order.couponDiscount > 0 ? (order.couponName || 'Discount Applied') : '',
      items: order.items.map(function(item, index) {
        return {
          item_id: item.product.id.toString(),
          item_name: item.product.name,
          item_brand: item.product.brand || '',
          item_category: item.product.categoryIds ? 'Category ' + item.product.categoryIds[0] : '',
          item_variant: formatVariant(item.selectedOptions),
          price: item.price,
          quantity: item.quantity,
          index: index,
          discount: item.discount || 0
        };
      })
    });

    // Reset flag after delay (in case customer views order confirmation multiple times)
    setTimeout(function() {
      purchaseTracked = false;
    }, 5000);
  });
}

Advanced Ecommerce Features

Product Affinity (Frequently Bought Together)

Track which products are purchased together:

Ecwid.OnOrderPlaced.add(function(order) {
  if (order.items.length > 1) {
    // Multiple items in order
    var productIds = order.items.map(function(item) {
      return item.product.id;
    });

    gtag('event', 'product_affinity', {
      products: productIds.join(','),
      order_value: order.total
    });
  }
});

Customer Lifetime Value (CLV)

Track returning customer orders:

Ecwid.OnAPILoaded.add(function() {

  Ecwid.getCustomerInfo(function(customer) {
    if (customer && customer.id) {

      // Set user properties
      gtag('set', 'user_properties', {
        customer_lifetime_value: customer.totalSpent || 0,
        customer_order_count: customer.orderCount || 0,
        customer_type: customer.customerGroupId ? 'wholesale' : 'retail'
      });
    }
  });

});

Abandoned Cart Recovery

Track potential abandoned carts:

var cartAbandonTimer = null;

Ecwid.OnCartChanged.add(function(cart) {
  // Clear existing timer
  if (cartAbandonTimer) {
    clearTimeout(cartAbandonTimer);
  }

  // If cart has items, set abandon timer (e.g., 15 minutes)
  if (cart.items.length > 0) {
    cartAbandonTimer = setTimeout(function() {
      gtag('event', 'cart_abandoned', {
        currency: cart.currency || 'USD',
        value: cart.total,
        items_count: cart.items.length
      });
    }, 15 * 60 * 1000); // 15 minutes
  }
});

// Clear timer if checkout started
Ecwid.OnPageLoad.add(function(page) {
  if (page.type === 'CHECKOUT_ADDRESS') {
    if (cartAbandonTimer) {
      clearTimeout(cartAbandonTimer);
      cartAbandonTimer = null;
    }
  }
});

Refund Tracking

Track refunds (requires manual trigger via Ecwid webhook):

// This must be triggered server-side via Ecwid webhook
// When refund is processed, send to GA4 Measurement Protocol

function trackRefund(transactionId, refundAmount, refundItems) {
  gtag('event', 'refund', {
    transaction_id: transactionId,
    value: refundAmount,
    currency: 'USD',
    items: refundItems // Array of refunded items
  });
}

// Example usage (from webhook handler):
// trackRefund('ORDER-123', 29.99, [{item_id: '456', quantity: 1}]);

Product-Level Custom Dimensions

Add custom product attributes:

// Extend product items with custom dimensions
function enhanceProductData(product) {
  return {
    item_id: product.id.toString(),
    item_name: product.name,
    item_brand: product.brand || '',
    item_category: getCategoryHierarchy(product.categoryIds),
    price: product.defaultDisplayedPrice,

    // Custom dimensions
    item_list_name: product.inStock ? 'In Stock' : 'Out of Stock',
    item_custom_1: product.sku || '',
    item_custom_2: product.weight ? product.weight.value + product.weight.unit : '',
    item_custom_3: product.productClassId ? 'Class ' + product.productClassId : ''
  };
}

Tracking Product Promotions

Track promotional products or sales:

Ecwid.OnAPILoaded.add(function() {

  Ecwid.OnPageLoad.add(function(page) {
    if (page.type === 'PRODUCT') {
      Ecwid.getProduct(page.productId, function(product) {

        // Check if product is on sale
        if (product.compareToPrice && product.compareToPrice > product.defaultDisplayedPrice) {
          var discount = product.compareToPrice - product.defaultDisplayedPrice;
          var discountPercent = (discount / product.compareToPrice * 100).toFixed(0);

          gtag('event', 'view_promotion', {
            promotion_id: 'sale_' + product.id,
            promotion_name: 'Product Sale',
            creative_name: discountPercent + '% Off',
            items: [{
              item_id: product.id.toString(),
              item_name: product.name,
              discount: discount
            }]
          });
        }
      });
    }
  });

});

Multi-Currency Support

Handle multiple currencies:

Ecwid.OnAPILoaded.add(function() {

  // Get store currency settings
  Ecwid.getStorefrontInfo(function(info) {
    var defaultCurrency = info.currency || 'USD';

    // Use this in all events
    gtag('config', 'G-XXXXXXXXXX', {
      'currency': defaultCurrency
    });
  });

  // For individual transactions, use order currency
  Ecwid.OnOrderPlaced.add(function(order) {
    gtag('event', 'purchase', {
      transaction_id: order.vendorOrderNumber,
      value: order.total,
      currency: order.currency || 'USD', // Order-specific currency
      // ... rest of purchase data
    });
  });

});

Testing & Validation

Use GA4 DebugView

  1. Enable debug mode:
gtag('config', 'G-XXXXXXXXXX', {
  'debug_mode': true
});
  1. In GA4, go to AdminDebugView

  2. Perform test transactions

  3. Verify all events and parameters

Test Checklist

  • Product impressions tracked on category pages
  • Product views tracked on detail pages
  • Add to cart fires with correct product and quantity
  • Remove from cart detects removals
  • Begin checkout fires once at checkout start
  • Add shipping info fires when shipping selected
  • Purchase fires with complete transaction data
  • Transaction ID is unique and correct
  • Revenue matches order total
  • Tax and shipping values are accurate
  • Product data includes all custom dimensions
  • Currency is correct for all events

Console Debugging

// Monitor all events
window.dataLayer = window.dataLayer || [];
var originalPush = window.dataLayer.push;
window.dataLayer.push = function() {
  console.log('GA4 Event:', arguments[0]);
  return originalPush.apply(window.dataLayer, arguments);
};

Common Issues

Duplicate Purchase Events

Cause: Order confirmation page reloaded or back button used.

Fix: Use flag to prevent duplicate tracking (shown in purchase function above).

Missing Product Data

Cause: API call not returning complete data.

Fix: Always use Ecwid.getProduct() for full details, not page context alone.

Currency Mismatch

Cause: Hard-coded currency doesn't match order currency.

Fix: Always use order.currency or cart.currency from Ecwid data.

Events Not Firing

See Events Not Firing Troubleshooting.

Reporting in GA4

Key Ecommerce Reports

Monetization Overview:

  • Reports → Monetization → Overview
  • Total revenue, transactions, average order value

Ecommerce Purchases:

  • Reports → Monetization → Ecommerce purchases
  • Transaction details, product performance

Item Performance:

  • Reports → Monetization → Item-list name and Item-promotion name
  • Which products drive revenue

Purchase Journey:

  • Explore → Funnel Analysis
  • Create funnel: view_item → add_to_cart → begin_checkout → purchase

Custom Reports

Create explorations for:

  • Product affinity analysis
  • Category performance
  • Coupon effectiveness
  • Shipping method preferences

Next Steps

For general GA4 ecommerce concepts, see GA4 Ecommerce Guide.