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.
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:
- Step 1: Navigate to Google Ads > Goals > Conversions > Summary
- 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.
- Step 3: In the “Enhanced Conversions” section, found just below “Tag setup,” check the box to enable it.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- “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.
- 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.
- Paste the entire code and click Save
- Lastly, we should click the Connect button to activate the Custom Pixel.
- 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.
- 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.
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.
Are you using an ad blocker? The 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.
🎉 Bonus Content: Explore the best Shopify Google Ads apps to optimize & improve the quality of your campaigns.
How to set up Google Ads Enhanced Conversions on Shopify
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.
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:
-
- Go to Goals > Conversions > Summary > Settings. You should see the “Enhanced Conversion” option below “Attribution”
- Go to Goals > Conversions > Settings > Enhanced Conversions
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.
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.
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.
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.
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:
If the script isn’t there, here are three possibilities:
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:
Ready? Great! Now copy the code block below and proceed to the next step.
1// Configuration Variables
2const px_config = {
3 GADS: {
4 id: "AW-XXXXXXX",
5 business_vertical: "retail",
6 conversions: {
7 purchase: "XXXXXXXXXXXXXXX",
8 },
9 },
10 flags: {
11 checkout_completed: true,
12 }
13};
14
15const user_data = 'email';
16
17/*
18 user_data
19
20 Options:
21 - email: Only email
22 - all: Email and shipping address parameters
23
24*/
25
26const feed_region = 'XX';
27const item_id_format = "product_id";
28/*
29item_id_format
30
31Options:
32 - variant_id
33 - product_id (default)
34 - product_sku
35 - null (shopify_XX_product_id_variant_id)
36*/
37
38const totalValue_option = "net";
39/*
40totalValue_option
41
42Options:
43 - net: without shipping and taxes
44 - no_shipping: without shipping
45 - no_tax: without taxes
46 - null: total price with shipping and taxes
47*/
48
49const block_items_id = true;
50const version = "1.5";
51const debug = {
52 status: false,
53 detail: false,
54 callback: false,
55 color: "background:#9936ca;color:#fff;",
56 msg: "Analyzify Ads Purchase Conv. Pixel ->",
57};
58
59const initData = init?.data || {};
60const initCart = initData?.cart || {};
61const initCustomer = initData?.customer || {};
62
63const script = document.createElement("script");
64script.setAttribute("src", `https://www.googletagmanager.com/gtag/js?id=${px_config.GADS.id}`);
65script.setAttribute("async", "");
66document.head.appendChild(script);
67
68window.dataLayer = window.dataLayer || [];
69
70function gtag() {
71 dataLayer.push(arguments);
72}
73
74gtag("js", new Date());
75gtag("config", px_config.GADS.id, {
76 "allow_enhanced_conversions": true,
77 "send_page_view": false
78});
79
80async function hashValue(value) {
81 if (!value) return null;
82 try {
83 const encoder = new TextEncoder();
84 const data = encoder.encode(value);
85 const hashBuffer = await window.crypto.subtle.digest('SHA-256', data);
86 const hashArray = Array.from(new Uint8Array(hashBuffer));
87 return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
88 } catch (error) {
89 console.error('Error while hashing value:', error);
90 return null;
91 }
92}
93
94const getTotal = (checkoutData) => {
95 try {
96 const totalValue = checkoutData?.totalPrice?.amount || 0;
97 const shippingValue = checkoutData?.shippingLine?.price?.amount || 0;
98 const taxValue = checkoutData?.totalTax?.amount || 0;
99 const subTotal = checkoutData?.subtotalPrice?.amount || 0;
100
101 switch (totalValue_option) {
102 case 'net':
103 return subTotal;
104 case 'no_shipping':
105 return subTotal + taxValue;
106 case 'no_tax':
107 return subTotal + shippingValue;
108 default:
109 return totalValue;
110 }
111 } catch (error) {
112 console.error('getTotal error:', error);
113 }
114};
115
116const getItemObj = (item) => {
117 try {
118 if (!item) {
119 console.error('Invalid item:', item);
120 return null;
121 }
122
123 let selected_id;
124 switch(item_id_format) {
125 case 'variant_id':
126 selected_id = item?.id;
127 break;
128 case 'product_id':
129 selected_id = item?.product?.id;
130 break;
131 case 'product_sku':
132 selected_id = item?.sku;
133 break;
134 default:
135 selected_id = `shopify_${feed_region}_${item?.product?.id || ''}_${item?.id || ''}`;
136 }
137
138 const itemObj = {
139 id: selected_id || item?.id || null,
140 business_vertical: px_config.GADS.business_vertical || "retail",
141 item_name: item?.title?.trim() || item?.product?.title?.trim() || null,
142 item_category: item?.product?.type || null,
143 item_brand: item?.product?.vendor?.trim() || null,
144 item_sku: item?.sku || null,
145 item_variant: item?.title?.trim() || null,
146 item_variant_id: item?.id || null,
147 price: item?.price?.amount || 0,
148 quantity: item?.quantity || 1,
149 currency: item?.price?.currencyCode || initCart?.cost?.totalAmount?.currencyCode || 'USD',
150 }
151
152
153 if(debug.status && debug.detail) console.log('%c%s itemObj', debug.color, debug.msg, itemObj);
154 return itemObj;
155 } catch (error) {
156 console.error('getItemObj error:', error);
157 }
158};
159
160const getUserData = async (checkoutData, initData) => {
161 // Extract data from init
162 const initCustomer = initData?.customer || {};
163 const initEmail = initCustomer.email || initData?.email || null;
164 const initPhone = initCustomer.phone || initData?.phone || null;
165
166 // Extract data from checkoutData
167 const checkoutCustomer = checkoutData?.order?.customer || {};
168 const checkoutEmail = checkoutData?.email || checkoutCustomer?.email || null;
169 const checkoutPhone = checkoutData?.phone || checkoutCustomer?.phone || null;
170 const billingAddress = checkoutData?.billingAddress || {};
171 const shippingAddress = checkoutData?.shippingAddress || {};
172
173 // Determine the primary data source for user info
174 const email = checkoutEmail || initEmail || null;
175 const phone = checkoutPhone || initPhone || null;
176 const customerId = checkoutCustomer?.id || initCustomer?.id || null;
177 const firstName = billingAddress?.firstName || shippingAddress?.firstName || initCustomer?.firstName || null;
178 const lastName = billingAddress?.lastName || shippingAddress?.lastName || initCustomer?.lastName || null;
179 const street = `${billingAddress?.address1 || shippingAddress?.address1 || ''} ${billingAddress?.address2 || shippingAddress?.address2 || ''}`.trim();
180
181 // Hash email and phone
182 const email_hashed = await hashValue(email);
183 const phone_hashed = await hashValue(phone);
184 const firstName_hashed = await hashValue(firstName);
185 const lastName_hashed = await hashValue(lastName);
186 const street_hashed = await hashValue(street);
187
188 // Create the final user data object
189 const userData = user_data === 'email' ? {
190 email: email,
191 sha256_email_address: email_hashed,
192 } : {
193 id: customerId,
194 email: email,
195 sha256_email_address: email_hashed,
196 phone_number: phone,
197 sha256_phone_number: phone_hashed,
198 address: {
199 first_name: firstName,
200 sha256_first_name: firstName_hashed,
201 last_name: lastName,
202 sha256_last_name: lastName_hashed,
203 street: street,
204 sha256_street: street_hashed,
205 city: billingAddress?.city || shippingAddress?.city || null,
206 country: billingAddress?.country || shippingAddress?.country || null,
207 region: billingAddress?.province || shippingAddress?.province || null,
208 postal_code: billingAddress?.zip || shippingAddress?.zip || null,
209 }
210 };
211
212 if (debug.status && debug.detail) console.log('%c%s userData', debug.color, debug.msg, userData);
213
214 return userData;
215};
216
217const GTAG_Event = (event, data) => {
218 try {
219 data.event_callback = () => {
220 if (debug.status && debug.callback) console.log(`%c%s ${event} event sent successfully`, debug.color, debug.msg);
221 };
222
223 gtag("event", event, data);
224 if (debug.status) console.log(`%c%s ${event}`, debug.color, debug.msg, data);
225 } catch (error) {
226 console.error('GTAG_Event error:', error);
227 }
228};
229
230function isEmptyObject(obj) {
231 return (
232 Object.keys(obj).length === 0 ||
233 Object.values(obj).every(
234 (value) => value === undefined || value === null || value === ""
235 )
236 );
237}
238
239function cleanObject(obj) {
240 return Object.fromEntries(
241 Object.entries(obj).filter(([_, value]) => value !== undefined && value !== null && value !== "")
242 );
243}
244
245const checkoutEventHandler = async (event, eventName) => {
246 const checkoutData = event.data.checkout;
247
248 if(debug.status && debug.detail) console.log('%c%s checkoutData', debug.color, debug.msg, checkoutData);
249
250 const productData = checkoutData.lineItems.map((item) => {
251 const itemData = getItemObj(item.variant);
252 return {
253 ...itemData,
254 quantity: item.quantity || 1,
255 };
256 });
257
258 const allDiscountCodes = checkoutData?.discountApplications
259 .filter(discount => discount.type === 'DISCOUNT_CODE' || discount.type === 'CODE')
260 .map(discount => discount.title) || null;
261
262 // Extract shipping tier titles
263 const shippingTiers = checkoutData?.delivery?.selectedDeliveryOptions
264 .filter(option => option.type === 'shipping')
265 .map(option => option.title) || null;
266
267 // Set user data
268 const user_data = await getUserData(checkoutData, initData);
269 gtag('set', 'user_data', user_data);
270
271 let evObj = {
272 items: productData,
273 transaction_id: checkoutData?.order?.id || null,
274 payment_type: checkoutData?.transactions?.[0]?.gateway || null,
275 coupon: checkoutData?.discountApplications[0]?.title || allDiscountCodes.join(', ') || null,
276 discount: checkoutData?.discountApplications[0]?.amount || checkoutData?.discountsAmount?.amount || 0,
277 value: totalValue_option ? getTotal(checkoutData) : checkoutData?.totalPrice?.amount || 0,
278 currency: checkoutData?.currencyCode || initCart?.cost?.totalAmount?.currencyCode,
279 shipping: checkoutData?.shippingLine?.price?.amount || 0,
280 shipping_tier: Array.isArray(shippingTiers) ? shippingTiers.join(', ') : shippingTiers,
281 tax: checkoutData?.totalTax?.amount || 0,
282 user_data: user_data,
283 };
284
285 if(block_items_id){
286 evObj.ecomm_prodid = evObj?.items.map(item => item?.pid);
287 evObj.ecomm_totalvalue = evObj?.value;
288 evObj.ecomm_ordercount = initCustomer?.ordersCount || 0,
289 evObj.ecomm_category = evObj?.items.map(item => item?.item_category);
290 }
291
292 evObj = cleanObject(evObj); // Clean the object to remove undefined, null, or empty values
293
294 if(px_config.GADS?.conversions[eventName] && !isEmptyObject(evObj)){
295 GTAG_Event("conversion", {
296 send_to: `${px_config.GADS?.id}/${px_config.GADS?.conversions[eventName]}`,
297 ...evObj,
298 });
299 }
300};
301
302// Handle checkout_completed event
303analytics.subscribe("all_standard_events", async (event) => {
304 try {
305 if (event.name === "checkout_completed" && px_config.flags.checkout_completed && !oneTimeEventHandlers.checkout_completed) {
306 oneTimeEventHandlers.checkout_completed = true;
307 await checkoutEventHandler(event, 'purchase');
308 }
309 } catch (error) {
310 console.error('checkout_completed error:', error);
311 }
312});
313
314const oneTimeEventHandlers = {
315 checkout_completed: false,
316};
IMPORTANT:
Once again, ONLY copy; don’t paste it yet.
Before you move on, we have an important note. We keep updating these code blocks with the latest information. Please make sure to checkout the Shopify - Google Ads Guidebook to make sure that you have the latest code.
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:
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.
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
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;
What is Google Ads 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:
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.