Spreecommerce Analytics Integrations: Setup Guide | OpsBlu Docs

Spreecommerce Analytics Integrations: Setup Guide

Integrate GA4, GTM, and Meta Pixel with Spree Commerce using ERB layout templates, Spree extensions, and the Storefront API.

Spree Commerce is an open-source Ruby on Rails ecommerce platform. It provides full access to ERB templates, a gem-based extension system, and both traditional server-rendered and headless (Storefront API) delivery models. Analytics integration uses Rails view templates, Spree's decorator/override system, or gem-based extensions.

Integration Architecture

Spree Commerce provides four integration paths:

  1. ERB Layout Templates -- Edit the application layout at app/views/spree/layouts/spree_application.html.erb (or its override in your extension). Standard Rails ERB templating with Spree view helpers.
  2. Spree Extensions (Gems) -- Install analytics gems via Gemfile. Extensions like spree_analytics_trackers provide admin-configurable tracking.
  3. Deface Overrides -- Spree uses the Deface gem to modify views without editing core files. Add tracking scripts via Deface overrides that inject content into layout templates.
  4. Storefront API (Headless) -- Spree's REST/GraphQL API serves product and order data. Frontend frameworks consuming this API handle analytics independently.

Available Integrations

Analytics Platforms

Google Analytics 4

  • ERB layout template injection
  • spree_analytics_trackers gem (admin-configurable)
  • GTM-based GA4 with Spree data layer (recommended)

Tag Management

Google Tag Manager

  • Application layout ERB injection
  • Deface override for non-invasive injection

Marketing Pixels

Meta Pixel

  • Via GTM container (recommended)
  • ERB template head injection

ERB Layout Integration with Ecommerce Data Layer

Edit the Spree application layout to add GTM and an ecommerce data layer:

<%# app/views/spree/layouts/spree_application.html.erb %>
<!DOCTYPE html>
<html lang="<%= I18n.locale %>">
<head>
  <!-- Google Tag Manager -->
  <script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
  new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
  j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;
  j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;
  f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer','GTM-XXXX');</script>

  <script>
  window.dataLayer = window.dataLayer || [];
  window.dataLayer.push({
    'pageType': '<%= controller_name %>',
    'actionName': '<%= action_name %>',
    'currency': '<%= current_currency %>',
    'locale': '<%= I18n.locale %>',
    'userLoggedIn': <%= spree_current_user ? 'true' : 'false' %>,
    'storeName': '<%= current_store.name %>'
  });
  </script>

  <%= yield :head %>
</head>
<body>
  <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXX"
  height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
  <%= yield %>
</body>
</html>

On the product page, add a view_item event in app/views/spree/products/show.html.erb:

<% content_for :head do %>
<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
  event: 'view_item',
  ecommerce: {
    currency: '<%= current_currency %>',
    value: <%= @product.price.to_f %>,
    items: [{
      item_id: '<%= @product.sku || @product.id %>',
      item_name: '<%= j @product.name %>',
      price: <%= @product.price.to_f %>,
      item_category: '<%= j(@product.taxons.first&.name || "") %>'
    }]
  }
});
</script>
<% end %>

Platform Limitations

Deface complexity. Spree uses Deface for view overrides, which targets specific DOM elements in ERB templates using CSS selectors. If Spree updates its template HTML structure, Deface overrides can silently break. Pin your Spree version and test overrides after upgrades.

Order confirmation data. Spree's order confirmation page (orders#show after checkout) provides order data via @order. However, page refreshes re-render the order page without re-triggering the checkout flow, potentially causing duplicate purchase events. Use a flag (cookie or session) to fire the purchase event only once.

Gem compatibility. The spree_analytics_trackers gem may lag behind Spree core releases. Verify gem compatibility with your Spree version before installing.

Headless Spree. When using Spree as a headless backend (Storefront API), the ERB template integration does not apply. Analytics integration happens in your React/Next.js/Vue frontend using standard SPA tracking patterns.

Multi-store. Spree supports multiple stores from one installation. Each store can have different currencies, locales, and product catalogs. Ensure your data layer includes the store identifier for cross-store analytics segmentation.

Performance Considerations

  • Rails asset pipeline. Spree uses the Rails asset pipeline (Sprockets or Webpacker) for CSS/JS bundling. Third-party tracking scripts bypass this pipeline and load as separate HTTP requests.
  • Turbolinks/Turbo. If using Turbolinks or Hotwire Turbo with Spree, page navigations are AJAX-based without full reloads. GTM's standard pageview trigger fires only on initial load. Listen for turbolinks:load or turbo:load events for subsequent page views.
  • N+1 queries. Data layer construction that accesses product associations (@product.taxons, @product.variants) can trigger N+1 queries. Use eager loading (includes(:taxons)) in controllers.
  1. Add GTM to application layout -- Global coverage for all Spree pages
  2. Build ecommerce data layer -- Product, cart, and purchase events on relevant pages
  3. Handle Turbolinks/Turbo -- Fire virtual pageviews on SPA-like navigations
  4. Configure GA4 ecommerce in GTM -- Map Spree product data to GA4 ecommerce
  5. Add Meta Pixel via GTM -- Map ecommerce events to Meta standard events

Next Steps

For general integration concepts, see the integrations overview.