Skip to content
Loïc Chossière AI Consultant

Free guide

Integrate Google Ads Shopify conversion tracking via Customer Events - 2025

Conversion tracking is the cornerstone of any successful Google Ads strategy. On Shopify, it automatically tracks sales made after a click on an ad, so you can accurately assess the return on your advertising investment.

  • 9 min read
  • 7 chapters
  • No email address required

1. Understanding Google Ads conversion tracking on Shopify (without GTM)

Conversion tracking is the cornerstone of any successful Google Ads strategy. On Shopify, it automatically tracks sales made after a click on an ad, so you can accurately assess the return on your advertising investment.

Enjoy the added bonus of enhanced conversions.

Since the restrictions imposed by browsers (Safari's ITP, iOS 14+ blocks, the end of third-party cookies), the reliability of standard tracking has greatly diminished. The result: fewer attributed conversions, falsely underperforming campaigns... and a poorly optimized advertising algorithm.

This is where a more robust version of tracking comes in: direct transmission of Shopify checkout information to Google Ads This information, such as the customer's e-mail address or telephone number, is transmitted securely and anonymously.

🔐 This data is automatically hashed using the SHA-256 algorithm before they are transmitted, thus guaranteeing their protection. Google never receives unencrypted e-mail.

🧾 Example of transmitted data:

  • Customer email address (hashed)
  • Telephone number (hashed)
  • First name / last name (hashed)
  • Postal address (hashed)

Google can then cross-check these data with users logged into their Gmail or Android account, and correctly attribute the conversion to the initial advertising click, even if the purchase takes place several days later.

2. Prerequisites before implementing Google Ads conversion tracking on Shopify (without GTM)

Before diving into the integration of the tracking script, it's essential to check that all the necessary elements are in place. Here's the complete technical checklist.

2.1 Have an active Google Ads conversion

You need a Purchase" conversion already configured in Google Ads. It will be used to capture Shopify orders triggered by an ad click.

🧭 If you don't already have one:
Go to Tools > Goals > Conversions click on New conversion select Website then configure a purchase / transaction event.

2.2 Activating the "Enhanced conversions" setting in Google Ads

  1. Go to Goals > Conversions > Summary
  2. Click on the line corresponding to your "Purchase" conversion
  3. In the Settings tab, activate the "Enhanced conversions section
  4. Choose the "Google Tag or Google Tag Manager" method
  5. Save

💡 Even if we don't use GTM, this option must be checked to enable customer information to be sent via the manual script.

2.3 Access to "Customer Events" on Shopify

Since 2023, Shopify has allowed the direct injection of JavaScript code via Custom Pixels in:

⚠️ This method works only for stores using the native Shopify checkout (no OnePage custom checkout or checkout.liquid).

2.4 Identifying your Google Ads conversion ID

Go to Google Ads

  1. Left menu: Goals > Conversions

  2. Click on your conversion line (e.g. "Website purchase")

  3. In Settings > Tag setup click on "Use Google tag

  4. You'll see:

    • Your Conversion ID (ex: AW-1234567890)
    • Your Conversion label (ex: kLMnOpQRsTUvWXyZ)

If your site targets Europe, you need to integrate tracking into a consent logic (cookies banner).

Shopify offers native consent management via:

  • Customer Privacy API
  • Third-party CMP such as Cookiebot, Axeptio or CookieYes

The script you insert later must be compatible with Google's Consent Mode to respect user preferences.

I invite you to read my guide to implementing Consent Mode via Shopify in 2025 and to return to this page later for the events section 🔥

3. Integration method without GTM - Via Google tag gtag.

3.1 Installing the Google tag on Shopify

You can add it manually in Shopify using the following settings:

Add the tag to "Customer Events":

  1. Go to Settings > Customer events
  2. Click on Add a custom pixel
  3. In the "Code" field, add this snippet:
// === CONFIGURATION PERSONNALISABLE ===
const CONFIG = {
  conversionId:      'AW-XXXXXXXXX',
  merchantId:        'XXXXXXXXX',
  feedCountry:       'FR',
  feedLanguage:      'fr',
  productIdFormat:   null,              // 'sku' | 'variant_id' | 'id' | null = shopify_FR_pid_vid
  prefixProductId:   'shopify_FR_',
  businessVertical:  'retail',
  sendPageView:      true,
  valueOption:       null,              // 'net' | 'no_shipping' | 'no_tax' | null = TTC
  debug:             true,
  conversions: {
  // events remarketing dynamique pures (pas de label) à indiquer
  // view_cart:        'undefined',
  // view_item:        'undefined',
  // add_to_cart:      'undefined',
  begin_checkout:   'exempleindiquerlabelici', // Conversion “début tunnel”
  add_shipping_info:'exempleindiquerlabelici', // Conversion “infos livraison”
  purchase:         'exempleindiquerlabelici' // Conversion “achat”
  }
};

// === INITIALISATION GTAG ===
(function loadGtag(){
  const s = document.createElement('script');
  s.async = true;
  s.src = 'https://www.googletagmanager.com/gtag/js?id=' + CONFIG.conversionId;
  document.head.appendChild(s);
  window.dataLayer = window.dataLayer || [];
  function gtag(){ dataLayer.push(arguments); }
  window.gtag = gtag;

  gtag('js', new Date());
  gtag('config', CONFIG.conversionId, {
    send_page_view:            CONFIG.sendPageView,
    allow_enhanced_conversions: true
  });
  if (CONFIG.debug) console.log('[GAds] gtag initialized');
})();

🔁 If you set up Consent Mode following my guide which is GTM-oriented rather than pure Google Ads, all you have to do is replace the GTM script (function loadGTM) with this one (function loadGTag)

💡 Important information: the aim here is for Shopify to load correctly gtag.js on all site pages, including checkout pages and above all on the thank you page (/thank_you), where conversion tracking will be triggered.

3.2 Structure of the Google Ads conversion tracking script (gtag.js)

The implementation is based on a JavaScript script injected into Shopify via the Custom Pixels. This script does several things:

  1. Load the library gtag.js
  2. Retrieves customer data (email, telephone, address, etc.)
  3. Provides unanonymized and anonymized data (SHA-256 hash) - it's up to you what you send to Google Ads
  4. Trigger an event conversion to Google Ads

🔐 Data protection: hashing sensitive fields

Personal data comes in two formats: hashed and unhashed via a SHA-256 hash - it's up to you what you want to send to Google Ads, for example:

const hashValue = async value => {
  if (!value || !window.crypto) return null;
  const enc = new TextEncoder().encode(value);
  const hash = await crypto.subtle.digest('SHA-256', enc);
  return Array.from(new Uint8Array(hash)).map(b => b.toString(16).padStart(2,'0')).join('');
};

As a reminder, Google's official documentation requires you to provide it with non-hashed data to ensure the proper functioning of enhanced conversion tracking.

Variables to be configured in the script

Here are the elements you will need to adapt manually to your project:

Variable Explanation
CONFIG.conversionId Your Google Ads conversion ID → example: "AW-1234567890"
CONFIG.conversions.purchase Conversion label for the event purchase → example: "AbCdEfGhIjk"
CONFIG.feedCountry ISO country code linked to your Merchant Center feed (e.g.: "FR", "US", "DE")
CONFIG.productIdFormat Product ID format ("sku", "variant_id", "id"or null for Shopify format)
CONFIG.user_data "email" for minimal tracking, "all" for all customer data
CONFIG.valueOption Method for calculating the amount sent to Google ("net", "no_shipping", "no_tax"or null for the VAT-inclusive amount)
CONFIG.prefixProductId Prefix to be added if productIdFormat = null (ex: "shopify_FR_")
CONFIG.businessVertical Business vertical for Google Ads, generally "retail"
CONFIG.sendPageView true to send a page_view each time a page is loaded
CONFIG.debug true to activate logs in the console

💡 It's up to you to define exactly what you want to send to Google Ads.:

  • If you want basic remarketing: conversionId + view_item + add_to_cart are all you need.
  • If you want full tracking with conversions + enhanced conversions: properly configure user_data, valueOptionand labels for each event.

3.3 Adapting the script to your Shopify catalog and the format expected by Google Ads

Correct product identification is crucial to the performance of your tracking: Google must be able to match products purchased to those in your Merchant Center feed. To do this, you need to set two key variables in the script:

feedCountry - Region of your Google Shopping feed

This variable represents the country code used by the Merchant Center feed:

Example of a value Country
"FR" France
"US" United States
"DE" Germany

You can find it in Google Ads > Products > Overview. If the item ID starts with shopify_FR_...use "FR" here.

productIdFormat - Product identifier format

This is the key to associating what the customer buys with what you advertise on Google Shopping. Choose the format that matches your feed:

Value Description
"product_id" Shopify product ID
"variant_id" Variant ID (e.g. size/color)
"product_sku" SKU if defined in Shopify
null Shopify standard format → shopify_{region}_{product_id}_{variant_id}

📌 You can consult your Item IDs in Merchant Center > Products > Item ID tab.

Example of script adaptation

CONFIG.feedCountry = 'FR'; // ← adapte à ton pays
CONFIG.productIdFormat = null; // ← laisse null si tu utilises le format "shopify_FR_123456_987654"

The script will then construct the final ID as follows:

shopify_FR_123456_987654

This will match your feed perfectly if you use the Shopify Google & YouTube app to feed Merchant Center.

🎯 Final objective: when a conversion is reported, Google Ads knows exactly which products were purchased and can link them to your Shopping campaign.

3.5 Integrating and activating the script in Shopify (Custom Pixel)

Step 1 - Go to Shopify settings

  1. Log in to your Shopify admin
  2. Go to Settings > Customer Events
  3. Click on the custom event managing Consent Mode if you followed my guide on the subject. If you don't need Consent Mode, use the Google Ads loading pixel (loadGTag function above).

Step 2 - Pixel configuration

  1. Pixel name: Google Ads Conversion - Purchase (or leave the name if it's the pixel linked to the consent mode)
  2. Script type: JavaScript
  3. Pixel code: paste the following complete script after our consent management pixel (if you use it), removing the === CONFIGURATION PERSONNALISABLE === and === INITIALISATION GTAG === parts.

Step 3 - Complete Google Ads tracking script for Shopify conversions


// Google Ads Tracking + Remarketing + Enhanced Conversions pour Shopify

// === CONFIGURATION PERSONNALISABLE ===
const CONFIG = {
  conversionId:      'AW-XXXXXXXXX',
  merchantId:        'XXXXXXXXX',
  feedCountry:       'FR',
  feedLanguage:      'fr',
  productIdFormat:   null,              // 'sku' | 'variant_id' | 'id' | null = shopify_FR_pid_vid
  prefixProductId:   'shopify_FR_',
  businessVertical:  'retail',
  sendPageView:      true,
  valueOption:       null,              // 'net' | 'no_shipping' | 'no_tax' | null = TTC
  debug:             true,
  conversions: {
  // events remarketing dynamique pures (pas de label) à indiquer
  // view_cart:        'undefined',
  // view_item:        'undefined',
  // add_to_cart:      'undefined',
  begin_checkout:   'exempleindiquerlabelici', // Conversion “début tunnel”
  add_shipping_info:'exempleindiquerlabelici', // Conversion “infos livraison”
  purchase:         'exempleindiquerlabelici' // Conversion “achat”
  }
};

// === INITIALISATION GTAG ===
(function loadGtag(){
  const s = document.createElement('script');
  s.async = true;
  s.src = 'https://www.googletagmanager.com/gtag/js?id=' + CONFIG.conversionId;
  document.head.appendChild(s);
  window.dataLayer = window.dataLayer || [];
  function gtag(){ dataLayer.push(arguments); }
  window.gtag = gtag;

  gtag('js', new Date());
  gtag('config', CONFIG.conversionId, {
    send_page_view:            CONFIG.sendPageView,
    allow_enhanced_conversions: true
  });
  if (CONFIG.debug) console.log('[GAds] gtag initialized');
})();

// === UTILITAIRES ===
const hashValue = async value => {
  if (!value || !window.crypto) return null;
  const enc  = new TextEncoder().encode(value);
  const hash = await crypto.subtle.digest('SHA-256', enc);
  return Array.from(new Uint8Array(hash))
    .map(b => b.toString(16).padStart(2,'0')).join('');
};

const formatItemId = variant => {
  if (!variant) return null;
  switch (CONFIG.productIdFormat) {
    case 'sku':        return variant.sku;
    case 'variant_id': return variant.id;
    case 'id':         return variant.product?.id;
    default:           return `${CONFIG.prefixProductId}${variant.product?.id}_${variant.id}`;
  }
};

// Envoi remarketing (sans label) 
const trackRemarketing = (eventName, data) => {
  gtag('event', eventName, {
    send_to: CONFIG.conversionId,
    google_business_vertical: CONFIG.businessVertical,
    ...data
  });
  if (CONFIG.debug) console.log(`[GAds] Remarketing: ${eventName}`, data);
};

// Envoi conversion si label défini
const trackConversion = (eventKey, data) => {
  const label = CONFIG.conversions[eventKey];
  if (!label) return;
  gtag('event','conversion',{
    send_to: `${CONFIG.conversionId}/${label}`,
    google_business_vertical: CONFIG.businessVertical,
    ...data
  });
  if (CONFIG.debug) console.log(`[GAds] Conversion: ${eventKey}`, data);
};

// Utilitaire combiné
const trackDual = (eventKey, remarketingName, data) => {
  trackRemarketing(remarketingName, data);
  trackConversion(eventKey, data);
};

// === ÉCOUTE DES ÉVÉNEMENTS SHOPIFY ===

// 1. Vue produit
analytics.subscribe('product_viewed', e => {
  const id = formatItemId(e.data.productVariant);
  if (!id) return;
  const payload = {
    items: [{ id }],
    value: e.data.productVariant?.price?.amount
  };
  trackDual('view_item','view_item', payload);
});

// 2. Vue collection
analytics.subscribe('collection_viewed', e => {
  const c = e.data.collection;
  const payload = {
    collection_id: c?.id,
    collection_title: c?.title
  };
  trackDual('view_item_list','view_item_list', payload);
});

// 3. Résultats de recherche
analytics.subscribe('search_submitted', e => {
  const payload = { query: e.data?.searchResult?.query || '' };
  trackDual('view_search_results','view_search_results', payload);
});

// 4. Ajout au panier
analytics.subscribe('product_added_to_cart', e => {
  const id = formatItemId(e.data.cartLine?.merchandise);
  if (!id) return;
  const payload = {
    items: [{ id }],
    value: e.data.cartLine?.merchandise?.price?.amount
  };
  trackDual('add_to_cart','add_to_cart', payload);
});

// 5. Vue du panier
analytics.subscribe('cart_viewed', e => {
  const items = (e.data.cart?.lines || []).map(l => ({
    id:       formatItemId(l.merchandise),
    quantity: l.quantity,
    price:    l.merchandise?.price?.amount
  }));
  trackDual('view_cart','view_cart', { items });
});

// 6. Début de tunnel (clic Checkout)
analytics.subscribe('checkout_started', e => {
  const items = (e.data.checkout?.lineItems || []).map(li => ({
    id:       formatItemId(li.variant),
    quantity: li.quantity,
    price:    li.variant?.price?.amount
  }));
  trackDual('begin_checkout','begin_checkout', { items });
});

// 7. Infos de livraison
analytics.subscribe('checkout_shipping_info_submitted', e => {
  const items = (e.data.checkout?.lineItems || []).map(li => ({
    id:       formatItemId(li.variant),
    quantity: li.quantity,
    price:    li.variant?.price?.amount
  }));
  trackDual('add_shipping_info','add_shipping_info', { items });
});

// 8. Achat final
analytics.subscribe('checkout_completed', async e => {
  const c = e.data.checkout;
  const items = c.lineItems.map(li => ({
    id:       formatItemId(li.variant),
    quantity: li.quantity,
    price:    li.variant?.price?.amount
  }));

  // Discount
  let totalDiscount = 0;
  (c.lineItems || []).forEach(li => {
    (li.discountAllocations || []).forEach(d => {
      const amt = parseFloat(d?.amount?.amount);
      if (!isNaN(amt)) totalDiscount += amt;
    });
  });
  totalDiscount = totalDiscount.toFixed(2);

  // User data
  const userData = {
    email:                c.email,
    sha256_email_address: await hashValue(c.email),
    phone_number:         c.phone,
    sha256_phone_number:  await hashValue(c.phone),
    address: {
      first_name:         c.shippingAddress?.firstName,
      sha256_first_name:  await hashValue(c.shippingAddress?.firstName),
      last_name:          c.shippingAddress?.lastName,
      sha256_last_name:   await hashValue(c.shippingAddress?.lastName),
      street:             await hashValue(`${c.shippingAddress?.address1} ${c.shippingAddress?.address2}`),
      city:               c.shippingAddress?.city,
      postal_code:        c.shippingAddress?.zip,
      country:            c.shippingAddress?.countryCode
    }
  };
  gtag('set','user_data', userData);

  const total = (() => {
    const t  = c.totalPrice?.amount || 0,
          s  = c.subtotalPrice?.amount || 0,
          sh = c.shippingLine?.price?.amount || 0,
          tx = c.totalTax?.amount || 0;
    switch (CONFIG.valueOption) {
      case 'net':         return s;
      case 'no_shipping': return s + tx;
      case 'no_tax':      return s + sh;
      default:            return t;
    }
  })();

  trackDual('purchase','purchase',{
    transaction_id:    c.order?.id || c.token,
    value:             total,
    currency:          c.currencyCode,
    discount:          parseFloat(totalDiscount),
    aw_merchant_id:    CONFIG.merchantId,
    aw_feed_country:   CONFIG.feedCountry,
    aw_feed_language:  CONFIG.feedLanguage,
    items
  });
});

Step 4 - Testing implementation

  1. Enable the debug.status = true option in your script (part const debug = {}).

  2. Make a test purchase with a fictitious order (real but with a free product, if necessary).

  3. Open the Console tab of your browser and observe:

    • logs gtag initialized
    • the generated user_data
    • the event conversion sent with send_to: AW-XXXXXXX/Label

Step 5 - Monitoring in Google Ads

In Google Ads > Tools > Conversions:

  • Check that conversions start to register within a few days
  • You can also consult tag status in the "Tag status" column
  • The usual lead time is 12 hours for an initial conversion.

4. Use of Google Tag Manager (optional)

🔒 Important note: This guide is designed for integration without Google Tag Manager (GTM). If you use GTM, the implementation logic changes fully.

Why use GTM?

Google Tag Manager lets you centralize the management of all your marketing tags, tracking pixels, e-commerce events, trigger rules and custom variables. This is particularly useful for high-volume sites or those requiring a lot of A/B testing, third-party scripting or cross-team coordination.

Useful documentation:

  • Google Ads Enhanced Conversions (GTM) support
  • GTM + Shopify example via Analyzify