Google Ads Enhanced Conversion helps you improve your conversion tracking by sharing more detailed conversion data with Google Ads.

Here, you will get a fully functional solution to set up Google Ads Enhanced Conversions in a few steps.

Before moving on to setting up & optimizing, you are recommended to check out our article on the key benefits of setting up Google Ads Enhanced Conversions.

google-ads-enhanced-conversion-setup-on-shopify-updated-image

Key Takeaways:

  • Use Analyzify’s open source code block to set up Google Ads Enhanced Conversions on Shopify (below)
  • Google Ads Enhanced Conversion allows sharing more detailed conversion data with Google Ads, by including customer information like email, name, address, and phone number.
  • Accurate conversion tracking is crucial for optimizing advertising spending, especially given changes in data tracking due to iOS, Safari ITP, and ad blockers.
  • There are now three ways to set up Google Ads Enhanced Conversions on your Shopify store:1. Google Tag (Gtag): If you have the Google tag on your store, you can enable enhanced conversions by adjusting your existing tag setup. This method sends customer data like email addresses securely to Google for better conversion tracking.
    2. Google Tag Manager (GTM): If you use GTM, you can enable enhanced conversions with a few changes to your setup. This method is great if you want more control over how the data is sent to Google.
    3. Google Ads API: This method is for advanced users. It allows you to send customer data directly to Google using their API. It is used to send your offline conversions to Google Ads and to increase the accuracy rate in your online conversions.

enhanced conversions - analyzify

🎉 Bonus Content: Explore the best Shopify Google Ads apps to improve the quality of your campaigns.

How to set up Google Ads Enhanced Conversions on Shopify

First of all, if you are using an ad blocker, you should note that this tutorial contains many images- most image names include “Google Ads” or “Ads”. Ad blockers think that it is an ad and blocks those. So make sure to temporarily disable your ad blocker to properly view the content.

There are several methods available for setting up Google Ads Enhanced Conversion.

You can easily handle it yourself with the first method.

If you prefer more control over your data, you might choose the Google Tag Manager method.

For those requiring greater flexibility, the Google Ads API is an option.

Our focus is primarily on Purchase tracking, as it’s the key area where user data like email, phone number, and address is available for enhanced conversion tracking on Shopify. We mainly guide you through the Google Ads setup process here.

Before Starting: Enable Enhanced Conversion Setting on Google Ads

You can either create a new conversion or apply enhanced conversion tracking to an existing one.

In this tutorial, we’ll use an existing Google Ads conversion. The steps will be very similar if you decide to set up a new conversion instead.

  • Step 1: Navigate to Google Ads > Goals > Conversions > Summary

google-ads-enhanced-conversion-setup-on-shopify-step-1

  • Step 2: Locate your Purchase conversion. Make sure the conversion source is set to “Website” because enhanced conversion tracking on Shopify cannot be applied to conversions sourced from Google-hosted or GA4 data.

google-ads-enhanced-conversion-setup-on-shopify-step-2

  • Step 3: In the “Enhanced Conversions” section, found just below “Tag setup,” check the box to enable it.

google-ads-enhanced-conversion-setup-on-shopify-step-3

Note: Google frequently updates its interface, and settings may appear in different locations depending on your account type. If you cannot find the “Enhanced Conversions” setting in this location, try these alternatives:

  1. Go to Goals > Conversions > Summary > Settings. You should see the “Enhanced Conversion” option below “Attribution”
  2. Go to Goals > Conversions > Settings > Enhanced Conversions
  • Step 4: After enabling Enhanced Conversions, a new screen will appear. Select “Google Tag or Google Tag Manager (GTM)” or “API” as your setup method. Click on the “Google Tag or GTM” option and save your changes.

Now that you have enabled Enhanced Conversions, let’s move on to the next section. I will explain how to set up Google Ads Enhanced Conversion on Shopify using the Google Tag method.

Method 1: Set Up Google Ads Enhanced Conversion with Google Tag

Here are the steps and code blocks you’ll need. You can check this official article if you are not using Shopify or if you want to learn more about it.

Step 1: Verify Your Google Tag Installation

To proceed, make sure that the Google Tag (gtag.js) is installed on your Shopify store. Enter your URL and click “CHECK URL.” If the Google Tag isn’t installed, you will only see the option for Google Tag Manager. In that case, proceed to Method 2. Alternatively, you can learn how to install Google Tag on Shopify.

google-ads-enhanced-conversion-setup-on-shopify-step-4

Step 2: Choose The Setup Method: Edit Code/Event Snippet

If the Google Tag is installed on your Shopify store, you should see the setup options.

enhanced-conversion-setup-on-shopify-customerpeg

Step 3: Select and Save Your Settings

Click on “Confirm how you want to set up enhanced conversions” and select “Edit Code.” Click “Save” to proceed.

google-ads-enhanced-conversion-setup-on-shopify-editcode

Step 4: Find and Copy Your Conversion ID and Label

Next, you need to retrieve your Conversion ID and Label. Scroll up to the “Tag Setup” section and select Google Tag Manager. We won’t be using Google Tag Manager, but this will help you easily access your Conversion ID and Label. Copy these details before moving to the next step.

google-ads-enhanced-conversion-setup-on-shopify-step-5

Step 5: Find Your Existing Conversion Script

You likely have a conversion script located in Admin > Settings > Checkout > Additional Scripts. If you don’t see it immediately, search for “AW-” and it should guide you to the script. It should look something like this:

google-ads-enhanced-conversion-setup-on-shopify-step-6

If the script isn’t there, here are three possibilities:

  1. Your conversion tracking wasn’t already working properly.
    In this case, just continue to the next step because our code snippet will already include the conversion tracking script as well.
  2. Your conversion script is managed via Customer Events > Custom Pixel.
    In this case, disconnect the relevant Custom Pixel and follow the instructions in this article to properly set up the latest enhanced conversion tracking.
  3. You are using Google Tag Manager to track conversions.
    In this case, you can either pause your conversion tag in Google Tag Manager or use Method 2 to implement the enhanced conversions.

Step 6: Add the New Enhanced Conversion Tracking Code on Shopify Checkout

Navigate to Customer Events > Custom Pixel on your Shopify store and add the code block provided below. Before implementing, read these points carefully:

  • Update the code block with your Conversion ID, Label, item ID format, and feed region in the next step. Avoid copying and pasting the block without these updates—completing the next step is crucial.

Ready? Great! Now copy the code block below and proceed to the next step.

// Configuration Variables
// Configuration Variables
const px_config = {
    GADS: {
        id: "AW-XXXXXXXXXX",
        business_vertical: "retail",
        conversions: {
            add_to_cart: null,
            view_item: null,
            begin_checkout: null,
            purchase: null,
        },
    },
    flags: {
        product_added_to_cart: false,
        product_viewed: false,
        checkout_started: false,
        checkout_completed: true,
    }
};

const consentModeEnabled = false;
/*
  consent_mode
  
  Options:
    - true: Consent Mode enabled
    - false: Consent Mode disabled
  
*/

const totalValue_option = null;
/*
totalValue_option

Options:
  - net: without shipping and taxes
  - no_shipping: without shipping
  - no_tax: without taxes
  - null: total price with shipping and taxes
*/

const add_to_cart_only_collections = false;
const add_to_cart_only_home = false;
const add_to_cart_only_pdp = true;
/*
Configuration for "Add to Cart" event tracking:

add_to_cart_only_pdp: 
  - When true, tracks add to cart events on product detail pages (/products/*)
  - Set to false to disable tracking on product pages
  - by default it is true

add_to_cart_only_collections:
  - When true, tracks add to cart events on collection pages (/collections/*)
  - Set to false to disable tracking on collection pages
  - by default it is false

add_to_cart_only_home:
  - When true, tracks add to cart events on the homepage (/)
  - Set to false to disable tracking on the homepage
  - by default it is false

These settings allow you to control where add to cart events are tracked.
You can enable/disable tracking for specific page types independently.
*/

const user_data = 'email';
/*
  user_data
  
  Options:
    - email: Only email
    - all: Email and shipping address parameters
  
*/

const version = "1.6";

const debug = {
    status: true,
    dlv: false,
    detail: false,
    callback: false,
    color: "background:#9936ca;color:#fff;",
    msg: "Analyzify Ads Conv. Pixel ->",
}

const initData = init?.data || {};
const initCart = initData?.cart || {};
const initContext = init?.context || {};
const initCurrency = initCart?.cost?.totalAmount?.currencyCode || null;
const initCustomer = initData?.customer || {};

const feed_region = 'XX';
const item_id_format = null;
/*
item_id_format

Options:
  - variant_id
  - product_id (default)
  - product_sku
  - null (shopify_XX_product_id_variant_id)
*/

const block_items_id = false;

const script = document.createElement("script");
script.setAttribute("src", `https://www.googletagmanager.com/gtag/js?id=${px_config.GADS.id}`);
script.setAttribute("async", "");
document.head.appendChild(script);

window.dataLayer = window.dataLayer || [];

function gtag() {
    dataLayer.push(arguments);
}

gtag("js", new Date());

// Check if consent mode is enabled
if (consentModeEnabled) gtag_consent_mode(debug.status);

gtag("config", px_config.GADS.id, {
    "allow_enhanced_conversions": true,
    "send_page_view": false
});

if (debug.status) console.log("%c%s Initialized", debug.color, debug.msg);

async function gtag_consent_mode() {
    // Consent Mode Initialization
    try {
        const consent_version = "1.1";
        let initConsent = init?.customerPrivacy || {};
        let getCMPCookieValue = null;
        let getTrackingConsentValue = null;

        // Check cookies only if initConsent is not available
        if (!initConsent?.marketingAllowed && !initConsent?.analyticsProcessingAllowed) {
            try {
                [getCMPCookieValue, getTrackingConsentValue] = await Promise.all([
                    browser.cookie.get("_cmp_a"),
                    browser.cookie.get("_tracking_consent"),
                ]);

                if (debug?.status) {
                    console.log("%c%s Loading cookie consent values", debug.color, debug.msg, {
                        _cmp_a: getCMPCookieValue,
                        _tracking_consent: getTrackingConsentValue,
                    });
                }
            } catch (error) {
                console.warn("%c%s Error fetching cookies:", debug?.color, debug?.msg, error);
            }
        }

        if (debug?.status) {
            console.log("%c%s Initial Consent", debug.color, debug.msg, initConsent || { _cmp_a: getCMPCookieValue, _tracking_consent: getTrackingConsentValue });
        }

        let currentConsent = {};
        let currentConsentPurpose = {};

        try {
            const consentCookie = decodeURIComponent(getCMPCookieValue || getTrackingConsentValue);
            currentConsent = JSON.parse(consentCookie) || {};
            currentConsentPurpose = currentConsent?.purposes || {};
        } catch (parseError) {
            console.warn("%c%s Error parsing consent cookie, using defaults:", debug?.color, debug?.msg, parseError);
        }

        const cmpConsent = getTrackingConsentValue?.con?.CMP || {};

        const consentSettings = {
            ad_storage: initConsent?.marketingAllowed || currentConsentPurpose?.m === true || (cmpConsent?.m !== undefined && cmpConsent?.m !== '0') ? "granted" : "denied",
            analytics_storage: initConsent?.analyticsProcessingAllowed || currentConsentPurpose?.a === true || (cmpConsent?.a !== undefined && cmpConsent?.a !== '0') ? "granted" : "denied",
            ad_user_data: initConsent?.marketingAllowed || currentConsentPurpose?.m === true || (cmpConsent?.m !== undefined && cmpConsent?.m !== '0') ? "granted" : "denied",
            ad_personalization: initConsent?.marketingAllowed || currentConsentPurpose?.m === true || (cmpConsent?.m !== undefined && cmpConsent?.m !== '0') ? "granted" : "denied",
            analyzify_consent:
                (
                    initConsent?.analyticsProcessingAllowed ||
                    (currentConsentPurpose?.a === true || (cmpConsent?.a !== undefined && cmpConsent?.a !== '0'))
                ) &&
                    (
                        initConsent?.marketingAllowed ||
                        currentConsentPurpose?.m === true ||
                        (cmpConsent?.m !== undefined && cmpConsent?.m !== '0')
                    ) ? "granted" : "denied",
        };

        if (debug?.status) {
            console.log("%c%s Final Consent Settings", debug.color, debug.msg, consentSettings);
        }

        // Custom Event
        window.dataLayer.push({
            event: "consentUpdate",
            status: 'default',
            ...consentSettings
        });

        const consentObj = {
            ...consentSettings,
            wait_for_update: 500
        };

        // GTAG - Consent
        gtag("consent", "default", consentObj);
        if (debug.status) console.log(`%c%s Consent settings applied (v${consent_version})`, debug.color, debug.msg, consentObj);

    } catch (error) {
        console.error("%c%s Error fetching or parsing consent cookie:", debug.color, debug.msg, JSON.stringify(error));
    }

    if (debug.status) console.log('%c%s gtag_consent_mode is initiated!', debug.color, debug.msg);
}

async function hashValue(value) {
  if (!value) return null;

  // Check if crypto and subtle are available
  if (typeof window === 'undefined' || !window.crypto || !window.crypto.subtle) {
    console.error('Crypto API is not available in this browser. Unable to hash value.');
    return null;
  }

  try {
    const encoder = new TextEncoder();
    const data = encoder.encode(value);
    const hashBuffer = await window.crypto.subtle.digest('SHA-256', data);
    const hashArray = Array.from(new Uint8Array(hashBuffer));
    return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
  } catch (error) {
    console.error('Error while hashing value:', error);
    return null;
  }
}

const getTotal = (valueObj, total, shipping, tax, subtotal) => {
    try {
        const totalValue = total || valueObj?.totalPrice?.amount || 0;
        const shippingValue = shipping || valueObj?.shippingLine?.price?.amount || 0;
        const taxValue = tax || valueObj?.totalTax?.amount || 0;
        const subTotal = subtotal || valueObj?.subtotalPrice?.amount || 0;
  
        let finalValue = 0;
  
        switch (totalValue_option) {
            case 'net':
                finalValue = subTotal;
                break;
            case 'no_shipping':
                finalValue = subTotal + taxValue;
                break;
            case 'no_tax':
                finalValue = subTotal + shippingValue;
                break;
            default:
                finalValue = totalValue;
                break;
        }
  
        return Number(parseFloat(finalValue).toFixed(2));
    } catch (error) {
        console.error('getTotal error:', error);
        return 0; // Ensure a fallback return value
    }
}

const getItemObj = (itemObj) => {
    try {
      if (!itemObj) {
          console.error('Invalid itemObj:', itemObj);
          return null;
      }

      const item = itemObj.variant || itemObj.merchandise || itemObj.productVariant;

      let selected_id;
      switch(item_id_format) {
        case 'variant_id':
          selected_id = item?.id;
          break;
        case 'product_id':
          selected_id = item?.product?.id;
          break;
        case 'product_sku':
          selected_id = item?.sku || item?.id || item?.product?.id;
          break;
        default:
          selected_id = `shopify_${feed_region}_${item?.product?.id || ''}_${item?.id || ''}`;
        }

        const discountAll = itemObj?.discountAllocations?.reduce((total, discount) => {
          return total + Number(parseFloat(discount?.amount?.amount) || 0);
        }, 0) || 0;
        const computedDiscount = itemObj?.finalLinePrice?.amount ? parseFloat(item?.price?.amount - itemObj.finalLinePrice?.amount) : 0;    
        const getDiscount = Number((discountAll || computedDiscount).toFixed(2));

        const additions = {};

        if(block_items_id){
            additions.pid = selected_id || item?.id || null;
        } else {
            // customization part
            additions.id = item?.id || null;
        }

        return {
            id: selected_id || null,
            business_vertical: px_config.GADS.business_vertical || "retail",
            // item_id: selected_id || null,
            item_name: item?.product?.title?.trim() || item?.title?.trim() || null,
            item_category: item?.product?.type || null,
            item_brand: item?.product?.vendor?.trim() || null,
            item_sku: item?.sku || null,
            discount: getDiscount || 0,
            item_variant: item?.title?.trim() || null,
            item_variant_id: item?.id || null,
            price: item?.price?.amount || 0,
            quantity: item?.quantity || itemObj?.quantity || 1,
            currency: item?.price?.currencyCode || initCurrency,
            ...additions
        };
    } catch (error) {
        console.error('getItemObj error:', error);
    }
}

function doesPagePath(event, paths, scope = 'contain') {
    const document = event.context.document;
    const pagePath = document.location.pathname;
  
    return paths.some((path) => {
      switch (scope) {
        case 'start':
          return pagePath.startsWith(path);
        case 'equal':
          return pagePath === path;
        case 'contain':
        default:
          return pagePath.includes(path);
      }
    });
}

const getUserData = async (checkoutData, initData) => {
    // Extract data from init
    const initCustomer = initData?.customer || {};
    const initEmail = initCustomer.email || initData?.email || null;
    const initPhone = initCustomer.phone || initData?.phone || null;

    // Extract data from checkoutData
    const checkoutCustomer = checkoutData?.order?.customer || {};
    const checkoutEmail = checkoutData?.email || checkoutCustomer?.email || null;
    const checkoutPhone = checkoutData?.phone || checkoutCustomer?.phone || null;
    const billingAddress = checkoutData?.billingAddress || {};
    const shippingAddress = checkoutData?.shippingAddress || {};

    // Determine the primary data source for user info
    const email = checkoutEmail || initEmail || null;
    const phone = checkoutPhone || initPhone || billingAddress?.phone || shippingAddress?.phone || null;
    const customerId = checkoutCustomer?.id || initCustomer?.id || null;
    const firstName = billingAddress?.firstName || shippingAddress?.firstName || initCustomer?.firstName || null;
    const lastName = billingAddress?.lastName || shippingAddress?.lastName || initCustomer?.lastName || null;
    const street = `${billingAddress?.address1 || shippingAddress?.address1 || ''} ${billingAddress?.address2 || shippingAddress?.address2 || ''}`.trim();

    // Hash email and phone
    const customerId_hashed = await hashValue(customerId);
    const email_hashed = await hashValue(email);
    const phone_hashed = await hashValue(phone);
    const firstName_hashed = await hashValue(firstName);
    const lastName_hashed = await hashValue(lastName);
    const street_hashed = await hashValue(street);

    // Create the final user data object
    const userData = user_data === 'email' ? {
        email: email,
        sha256_email_address: email_hashed,
    } : {
        id: customerId,
        user_id: customerId_hashed,
        email: email,
        sha256_email_address: email_hashed,
        phone_number: phone,
        sha256_phone_number: phone_hashed,
        address: {
            first_name: firstName,
            sha256_first_name: firstName_hashed,
            last_name: lastName,
            sha256_last_name: lastName_hashed,
            street: street,
            sha256_street: street_hashed,
            city: billingAddress?.city || shippingAddress?.city || null,
            country: billingAddress?.country || shippingAddress?.country || null,
            region: billingAddress?.province || shippingAddress?.province || null,
            postal_code: billingAddress?.zip || shippingAddress?.zip || null,
        }
    };

    if (debug.status && debug.detail) console.log('%c%s userData', debug.color, debug.msg, userData);

    return userData;
};

const getPageType = () => {
    const path = initContext?.document?.location?.pathname;
    
    const pathTypeMapping = [
      { type: 'category', includes: '/collections' },
      { type: 'product', includes: '/products' },
      { type: 'basket', includes: '/cart' },
      { type: 'homepage', equals: '/' },
      { type: 'purchase', includes: ['/thank_you', '/thank-you'] },
    ];
  
    for (const { type, includes, equals } of pathTypeMapping) {
      if (equals && path === equals) {
        return type;
      }
      if (includes && (Array.isArray(includes) ? includes.some(i => path.includes(i)) : path.includes(includes))) {
        return type;
      }
    }
  
    return 'other';
};

const GTAG_Event = (event, data) => {
    try {
        data.event_callback = () => {
            if (debug.status && debug.callback) console.log(`%c%s ${event} event sent successfully`, debug.color, debug.msg);
        };
        data.ecomm_pagetype = getPageType();

        gtag("event", event, data);
        if (debug.status) console.log(`%c%s ${event}`, debug.color, debug.msg, data);
        if (debug.dlv) console.log("%c%s dataLayer", debug.color, debug.msg, window.dataLayer);
    } catch (error) {
        console.error('GTAG_Event error:', error);
    }
};

if (debug.status) console.log(`%c%s Checkout Only Customer Events Pixel for ${px_config.GADS.id} initiated. Version: ${version}`, debug.color, debug.msg);

const commonEventHandler = async (event, flag, eventName, getDataFn) => {
    try {
        if (px_config.flags[flag]) {
            // Set user data
            const user_data = await getUserData({}, initData);
            gtag('set', 'user_data', user_data);
            const data = getDataFn(event);
            data.user_data = user_data;
            if(px_config.GADS?.conversions[eventName]){
                GTAG_Event("conversion", {
                    send_to: `${px_config.GADS?.id}/${px_config.GADS?.conversions[eventName]}`,
                    ...data,
                });
                if (debug.status) console.log(`%c%s ${eventName} event sent`, debug.color, debug.msg, data);
            }
        }
    } catch (error) {
        console.error('commonEventHandler error:', error);
    }
};

function isEmptyObject(obj) {
    return (
        Object.keys(obj).length === 0 ||
        Object.values(obj).every(
            (value) => value === undefined || value === null || value === ""
        )
    );
}

function cleanObject(obj) {
    return Object.fromEntries(
        Object.entries(obj).filter(([_, value]) => value !== undefined && value !== null && value !== "")
    );
}

const checkoutEventHandler = async (event, eventName) => {
    const checkoutData = event.data.checkout;

    if(debug.status && debug.detail) console.log('%c%s checkoutData', debug.color, debug.msg, checkoutData);

    const productData = checkoutData.lineItems.map((item) => {
        const itemData = getItemObj(item);
        return {
            ...itemData,
            quantity: item.quantity || 1,
        };
    });

    // Set user data
    const user_data = await getUserData(checkoutData, initData);
    gtag('set', 'user_data', user_data);

    const allDiscountCodes = checkoutData?.discountApplications
    .filter(discount => discount.type === 'DISCOUNT_CODE' || discount.type === 'CODE')
    .map(discount => discount.title) || null;

    const shippingTiers = checkoutData?.delivery?.selectedDeliveryOptions
    .filter(option => option.type === 'shipping')
    .map(option => option.title) || null;

    const lineItemPrice = Array.isArray(productData) ? productData.reduce((total, item) => {
      const price = parseFloat(item?.price || 0);
      const quantity = parseInt(item?.quantity || 1, 10);
      return total + (price * quantity);
    }, 0) : 0;
    
    const subTotal = checkoutData?.subtotalPrice?.amount;
    const discount = checkoutData?.discountsAmount?.amount || checkoutData?.discountApplications[0]?.amount || 0;
    const coupon = allDiscountCodes.length > 0 ? allDiscountCodes.join(', ') : checkoutData?.discountApplications[0]?.title || null;
    const token = checkoutData?.token || null;

    let evObj = {
        items: productData,
        transaction_id: checkoutData?.order?.id || token || null,
        payment_type: checkoutData?.transactions?.[0]?.gateway || null,
        coupon: coupon,
        discount: (coupon == null) ? 0 : (discount > 0) ? discount : lineItemPrice,
        value: totalValue_option ? getTotal(checkoutData) : checkoutData?.totalPrice?.amount || 0,
        currency: checkoutData?.currencyCode || initCurrency,
        shipping: checkoutData?.shippingLine?.price?.amount || 0,
        shipping_tier: Array.isArray(shippingTiers) ? shippingTiers.join(', ') : shippingTiers,
        tax: checkoutData?.totalTax?.amount || 0,
        user_data: user_data,
        new_customer: initCustomer?.ordersCount > 0 ? true : false,
    };

    if(block_items_id){
        evObj.ecomm_prodid = evObj?.items.map(item => item?.pid);
        evObj.ecomm_totalvalue = evObj?.value;
        evObj.ecomm_ordercount = initCustomer?.ordersCount || 0,
        evObj.ecomm_category = evObj?.items.map(item => item?.item_category);
    }

    evObj = cleanObject(evObj); // Clean the object to remove undefined, null, or empty values

    if(px_config.GADS?.conversions[eventName] && !isEmptyObject(evObj)){
        GTAG_Event("conversion", {
            send_to: `${px_config.GADS?.id}/${px_config.GADS?.conversions[eventName]}`,
            ...evObj,
        });
    }
};

const logEventDebug = (eventName) => {
    if (debug.status) {
        console.log(`%c%s all_standard_events -> ${eventName}`, debug.color, debug.msg);
    }
}

// Handle checkout_completed event
analytics.subscribe("all_standard_events", (event) => {
    try {
        const eventHandlers = {
            checkout_completed: async () => {
                if (px_config.flags.checkout_completed && !oneTimeEventHandlers.checkout_completed) {
                    oneTimeEventHandlers.checkout_completed = true;
                    await checkoutEventHandler(event, 'purchase');
                }
            }
        };

        if (eventHandlers[event.name]) {
            eventHandlers[event.name]();
            logEventDebug(event.name);
        }
    } catch (error) {
        console.error('all_standard_events error:', error);
    }
});

const oneTimeEventHandlers = {
    payment_info_submitted: false,
    checkout_completed: false,
};
Make sure that you have copied it correctly.

IMPORTANT:

  • user_data: ’email’, // options: all and email
    If you want to send only the “email” variable of customers as Enhanced conversion data to Google Ads, you can leave this variable as it is. However, if you are also collecting phone numbers and any address information from your customers, you can change this variable to “all” from the options listed in the variable.
  • debug: false, // options: true, false
    Use this variable only for testing purposes.To ensure that your code is working properly, you can change this variable to true and perform a test order. To ensure that the data is transmitted correctly, you can follow the activated console logs or check the Network signals in DevTools.

Once again, ONLY copy; don’t paste it yet.

google-ads-enhanced-conversion-setup-on-shopify-step-7

Step 7: Update the Variables in the Code

In this step, you’ll need to update specific sections of the code with your unique information. Do not change any other parts of the code. Here are the details:

  • “px_config.GADS.id”: Add your conversion ID (from Step 2) right after “AW-“. Only replace the numbers while keeping “AW-” intact. For example, if your conversion ID is 123456789, the updated code should read AW-123456789.
  • “px_config.GADS.conversions.purchase”: This is where you add your conversion label (from Step 3).
  • “item_id_format”: Use the item ID format that corresponds to your Google Ads feed. This will be further explained in the item ID format section below.
  • “feed_region“: If you use Shopify’s native app for uploading your Merchant product feed data, your item ID format might look like shopify_{feed_region}_{product_id}_{variant_id}. In this case, you must update the feed_region variable with your region’s ISO code.
  • “totalValue_option”: You can adjust the total value option to modify the conversion value sent to Google Ads. Options include values with no shipping, no tax, or net. By default, it includes the total price with shipping and tax.

Step 7: ItemID Format 

Let’s quickly double-check your Google Feed item ID format.

Visit Google Ads and click PRODUCTS on the left menu. You will see the merchant ID as marked below – and your item ID format next to that. In our example it starts with “shopify_AU_…” because the native Google Sales Channel is used for product feed on Shopify.

google-ads-enhanced-conversion-setup-on-shopify-step-8

If you are using a different format here, you should adjust our codes accordingly.

After you replace all these values – now it is time to use this code.

Step 9: Add the Updated Code to Shopify Checkout Additional Scripts

  • Go to Shopify Admin > Settings > Customer Events > Add Custom Pixel.
  • Name the new Custom Pixel as “Analyzify GAds Conv. v1.5” and click Add Pixel.
  • If you use a consent banner, you can select the Required option to ensure conversion data is sent according to customer consent preferences. Adjust this under Customer Privacy > Permission at the top of the Custom Pixel configuration.
  • Alternatively, you can select Not Required if you wish to collect conversion data from all users without needing consent.

enhanced-conversion-setup-on-shopify-customer-privacy

  • Paste the entire code and click Save
  • Lastly, we should click the Connect button to activate the Custom Pixel. 

enhanced-conversion-setup-on-shopify-final-step

We are done! The enhanced conversion data should be coming into Google Ads shortly.

Method 2: Set up Enhanced Conversions with Google Tag Manager

This is a more complex setup and it requires your store to have a set of data layers and a correctly structured Google Tag Manager container to make it work. We will add a separate series of tutorials for this.

For now, we recommend you use the method explained above. If you still want to use Google Tag Manager;

  • You can check the official documentation and follow the steps there.
  • You can purchase Analyzify, and our support team will complete your setup at no extra cost. Analyzify provides countless benefits for your Shopify store. You can check the features on our Analyzify Features page.

What is Google Ads Enhanced Conversion?

enhanced-conversion

Google Ads Enhanced Conversion is a feature that allows you to share more detailed conversion data with Google Ads, improving the accuracy of your conversion tracking. It functions similarly to the Facebook Conversion API.

In standard Google Ads conversion tracking, data like order ID, revenue, and optionally purchased products are sent to Google.

With Enhanced Conversion Tracking on Shopify, you can also share customer details such as email, name, address, and phone number for better attribution.

Let’s consider an example:

  • Imagine you run an online bookstore and advertise it using Google Ads with Enhanced Conversion tracking. One of your keywords is ‘buy books online.’
  • A potential buyer, logged into their Google account on Chrome, searches for this keyword and sees your ad on the first page. They click on your ad and visit your website. On your site, they explore different genres, read reviews, and add a book to their wishlist but decide to purchase it later.
  • A few days later, the same buyer returns to your website and buys the book from their wishlist. Enhanced Conversion Tracking captures this interaction by securely hashing customer data (like an email address or phone number) and sending it to Google. The hashing process ensures data is anonymized before being matched with logged-in Google accounts, helping attribute the conversion to your ad interactions.

Google’s Explanation:

The feature uses a secure one-way hashing algorithm called SHA256 on your first party customer data, such as email addresses, before sending to Google. The hashed data is then matched with signed-in Google accounts in order to attribute your campaign conversions to ad events, such as clicks or views. Source

Do I need Google Ads Enhanced Conversion?

Conversion tracking has become significantly hard after the new changes in the world of data tracking such as iOS updates, Safari ITP, and with arise of adblockers. You can’t optimize and measure your advertising spending if you don’t measure them well. So, the answer is yes if you want to count and attribute more conversions.

Note: After activating Google Ads enhanced conversions, don’t forget to import your Shopify customer data into Google Ads.

Final Words

Setting up Google Ads Enhanced Conversions on Shopify is vital for accurate conversion tracking, especially in the face of recent changes in data tracking. This feature allows you to share comprehensive conversion data, including customer information.

The tutorial offers two methods:

Editing Code Directly: This is a straightforward approach for those comfortable with coding.

Google Tag Manager: A more advanced setup requiring a structured container and data layers.

With Enhanced Conversions, you not only track order details but also capture valuable customer information, enabling more precise attribution of conversions to your advertising efforts.

In a landscape where accurate measurement of advertising ROI is paramount, adopting Google Ads Enhanced Conversions is a vital step toward optimizing your advertising spend.