Building a B2B GTM Engine - Chris O'Neill - Medium

23 Jun.,2025

 

Building a B2B GTM Engine - Chris O'Neill - Medium

Marketing: Starter Gear

Marketing is the “starter gear” of the engine. Brand, product, and growth marketing work together to drive this gear and create a strong foundation for symbiotic marketing-sales interactions and high sales velocity.

Please visit our website for more information on this topic.

Brand Marketing

Brand marketing amplifies great product experiences through storytelling that brings depth and emotion to make a brand richer and marketing more meaningful. Doing so boosts brand awareness, helping your company achieve goals including product or regional expansion, or extending your appeal to new customer segments and decision-makers. Brand marketing also reinforces clarity and consistency through a brand identity that connects your company’s purpose and value to your ideal customers. The ultimate goal is to achieve resonance with customers such that they become your advocates. If anyone has ever gotten a tattoo of your brand, you’ve achieved very high brand resonance.

External communication plays a vital role in brand building. Maintaining a steady drumbeat of momentum ー product launches, additions to your team, partnership announcements, contributions to your community, among others ー is critical. In the early days, momentum helps establish credibility and relevance. As you hit your stride, momentum creates a sense of inevitability that your company will deliver on its mission, create an exciting category, and become an enduring company.

Product Marketing

Product marketing explains and sells the product after prospects become aware of your brand and actively consider and evaluate your product. There are three layers to this: “why” (an anthemic raison d’être), “what” (benefits and features), and “how” (delightfully designed, polished experiences).

  • “Why” is essential. Having an anthemic raison d’être for your product establishes the context and inspires your team. Slack’s “We Don’t Sell Saddles Here” memo is a stellar example of getting this right. Stewart Butterfield, Slack’s Co-Founder & CEO, brilliantly articulates that Slack is selling organization transformation; that is their product’s “why,” the job they’re hired to do. The tone was consistent with an emerging challenger brand with a personal, playful, and memorable voice.
  • “What” includes the product features that bring your product promise to life by delivering clear benefits that solve real problems. Ideally, you imagine your ideal future customer and tell a story about their life with your product. It’s also helpful to express benefits in jargon-free language and link features to these benefits. Examples:
    Slack: Work more easily with everyone → Channels, Slack Connect, messaging, video & voice calls
    Asana: See who’s doing what and when → list view, timeline, boards
    Twilio: From first interaction to lasting connection → Marketing (text & marketing, lead alerts, call tracking), Customer Service (account security, IVR, chatbots), Operations (account notifications, appointment reminders)
  • “How” is the customer’s experience with your product. Everyone expects products to bring them joy. This is true for consumer and workplace tools and products alike. Companies that create differentiated experiences will win. Product and Marketing must partner to ensure the entire customer journey ー from initial intent to usage and renewal ー is thoughtfully designed and optimized over time.

fRetention matters above all else. Start with retention (% of customers active/paying after X days) and work backward. You can’t be successful if customers don’t stick around. Unless you have retention, your growth efforts will be wasted or sub-optimal. Is your product experience a part of their workflow or habit? Have customers experienced a lightbulb moment where they understand the core value of your product? Have you successfully set your customers up for success?

The first mile of a software product is typically an afterthought. Onboarding customers is not sexy. However, it’s important because every new customer is activated and onboarded. The last mile of acquisition is the first mile of product. It’s essential to get this right since almost all churn happens within 90 days. An effective onboarding process communicates your core product action and ensures customers experience an “aha” moment as soon as possible. This is sometimes referred to as “time-to-value.”

Stripe is an excellent example of a company that has sweated the details of documentation and onboarding and combined that with a clear understanding of their core action (transactions processed) and time-to-value (add seven lines of code and get started in minutes). As your product and company evolve, it’s challenging to maintain “a beginners’ mind” to continually develop, refine, and optimize developer and user journeys. Onboarding is not the action to “set and forget!” Activation and onboarding work are evergreen activities. Set a monthly reminder to sign up for your product as a new customer. Better yet, sit silently beside a brand new customer as they onboard.

Customers should feel that the product gets better the more they use it. For example, data gleaned from usage enables meaningful personalization or makes a key feature (e.g., search) more robust. Customers should also feel that the more they use the product, the more they have to lose if they stopped using the product. Perhaps your product becomes integral to their workflow or their identity. A skilled marketer can clearly and concisely communicate product benefits and consistently reinforce the value of remaining a loyal customer and advocate.

Growth marketing is a natural complement to brand and product marketing ー and involves attracting and delighting your future customers.

Growth Marketing

Growth marketing is a natural complement to brand and product marketing ー and involves attracting and delighting your future customers. It requires a nuanced, quantitative, and shared understanding of how growth happens from original intent through activation, usage, retention, and enlisting others.

Growth marketing starts with an understanding of how input/intent metrics drive outputs. The goal is to create an equation for your business that maps inputs to outputs. A growth map is one way to visualize this equation that allows teams to coalesce around facts, not opinions.

This work helps inform your “north star metric” ー the one input metric that matters above all ー and understand how this may evolve throughout your customers’ lifecycle and over time. Another way to think of your north star metric is the core action of your product. For example, nights booked (Airbnb), messages sent (Slack), notes taken (Evernote). It provides clarity and helps prioritize potential experiments and investments.

Beyond the growth map, cohort analysis is an essential complement to understand engagement. Specifically, you want to measure “growth” (size of each cohort), “engagement” (ratio of users in each cohort completing the core action of each product, e.g., messages sent), and “retention” (cohort performance over time).

Understanding how growth happens and how cohorts perform allows for rapid and systematic experimentation and precise and continuous measurement. Creating and maintaining a solid data infrastructure (raw data, pipeline) and robust set of tools unlocks great growth teams. With this foundation in place, there are five optimization levers ー the 5 Ps of growth marketing.

The 5 P’s of Growth Marketing

  • Pricing & Packaging is one of the most powerful — yet under-appreciated — levers. Understanding and optimizing pricing and packaging run the gamut. It presents many experimentation opportunities: price elasticity, the role of promotions and trials, how to bundle and package various features into compelling benefits, and how to evolve this by market, vertical, and segment over time and more. That said, pricing is hard to change. It’s a classic Type 1 — i.e., non-reversible — decision, and one must be very careful making it. Great pricing encourages easy adoption and aligns how you capture value with what customers perceive as most valuable. Slack’s “fair billing” pricing (i.e., billing only active users) is a great pricing example: informed by the “north star metric” (sending >2,000 messages), it encourages broad early adoption and smooths the expansion to other teams.
  • Partnerships can make your partners an extension of the marketing team. Co-marketing with partners supports the benefits of broader, integrated product experiences and can help you reach new audiences. Integrations with partners’ products can make your core product stickier. Creative partnerships enable you to piggyback off of the success of other platforms. For example, SEO and well-designed landing pages that include partners’ brands and products deliver meaningful referral traffic. Slack (AppDirectory) and Atlassian (Marketplace) drive outsized organic traffic and stickiness in their core product solutions by building a robust ecosystem of partners.
  • People. Enlisting your customers and community can amplify your efforts. Organic growth through word-of-mouth has always been the holy grail. Once product-market fit helps unleash your community. Referral programs are excellent sources of qualified traffic. Dropbox famously fuelled its early growth by including a simple, straightforward, and compelling offer (free storage) as part of the onboarding process. Intentional design helps. The most potent product experiences enable customers to create virtuous loops in the product as they engage with it. For example, Pinterest creates a powerful loop when a user discovers a pin, sends it to a friend, who then joins Pinterest, finds pins, and so on. Community engagement can take many forms: conferences, research, access to beta programs and team members, certifications, online forums, etc. These efforts are not about you. Stay focused on why people are attracted: to be informed, inspired, or entertained.
  • Point of View / Perspective. Content marketing helps shape conversations relevant to your customers and community. The goal is to establish your company as the authority on what matters to your customers and guide prospects with high-intent to consider what you offer. A well-written blog with fresh content is an excellent place to start. Podcasts are another ideal medium, though they require more significant effort and investment. New entrant, Clubhouse, removes much of the friction of podcasts and holds great promise. You don’t need to “manufacture” issues; instead, you need to listen to what’s on your community’s mind and offer a compelling and engaging point of view. Social channels (Twitter, Instagram, Facebook) offer reach and the ability to engage one-on-one or one-to-many. TikTok, Snap, Pinterest, and Medium can also be robust platforms and sources of referral traffic.
  • Platforms. Marketing platforms like Google, Facebook, LinkedIn, Pinterest, Amazon, and Twitter are useful sources of qualified leads. These platforms prime your GTM engine. Maximize organic traffic (e.g., SEO) and connect high-intent prospects to the right marketing action. B2B customers take time to make significant, complex decisions. You want to avoid paying for leads more than once. Aim to capture an or mobile number to educate and nurture engagement through your owned and operated channels (e.g., webinars, blogs, newsletters, events), and ideally, product trial and usage.

Partnerships: Turbo Gear

Partnerships can turbo-charge your growth by expanding the customer value proposition and reducing time to market. There are three main types of partnerships: integrations, brand associations, and joint distribution.

  • Integrations with complementary products can unlock additional value for your customers. These are sometimes called “whole product” partnerships that increase revenue with a more robust solution and reduce time to market. Examples:
    Shopify partnering with Stripe to facilitate payments on its platform.
    Okta partnering with Palo Alto Networks to layer authentication and deliver remote access to an internal network.
    Cloudflare partnering with DataDog to make analyzing Cloudflare logs and metrics easy.

Think about the most significant partnerships that help you address more of your customers’ problems. These integrations tend to reduce churn and deliver significant SEO benefits as you draft off other brands and platforms’ success.

  • Brand Association between two brands with relevant communities can increase brand awareness and drive qualified traffic for both brands. Imagine you’re a company like Brex that targets startups. Forming a partnership with accelerators like Y Combinator or TechStars would allow you to offer compelling benefits to garner outsized mindshare and drive highly qualified leads. You might also consider affiliations with other communities like SaaStr (business software), Startup Grind (startups), ShopTalk (e-commerce), or RockHealth (life sciences).
  • Distribution allows you to tap partners’ brand, customer base, and reach. Co-marketing and channel/reseller programs extend reach by gaining access to additional segments and markets. Co-marketing is an effective way to cross-promote complementary products and services and improve sales efficiency. Beyond logos, case studies, and special offers on websites, robust co-marketing programs involve data and list-sharing to understand intent further earlier in the buying cycle and launch creative programs that attract attention and volume. Channel partners help sell your product or service in segments or markets where you lack capability or presence. While there are many different approaches, the main benefits are built-in trust, speed, and efficiency from your channel partners’ established relationships. There are potential challenges, including brand risk, channel conflict, and margin compression.

Sales: Power Gear

Brand, product, and growth marketing and effective partnership programs help drive your power gear: sales. There are three steps to building robust sales:

  • Finding GTM fit
  • Accelerating sales velocity
  • Enabling sales processes and tools

Finding GTM Fit

Bob Tinker and Tae Hea Nahm coined the term “go-to-market fit.” Finding GTM Fit requires excellence at finding urgency, picking and optimizing the “right” sales model, and building a repeatable sales playbook.

  • Find urgency. Who is your buyer (company, industry, title) — also known as the ideal customer profile (ICP)? Why do they have a sense of urgency now (pain, use cases, adapting to pandemic)? What is the macro trend or wave that shapes your prospects’ needs? How do they make significant purchasing decisions? How best to find them? The answers to these questions inform whom to target with scarce outbound efforts and prioritize inbound leads. Quality is more important than quantity here. Most teams waste time on prospects who don’t fit the ideal profile. Your target segment should feel uncomfortably small at first. Leads are generated through warm introductions, associations, conferences, and lead lists (e.g., Clearbit, LinkedIn).
  • Decide on the “right” sales model. Once leads are identified and qualified, it’s crucial to settle on a sales model that matches how your target customer decides to buy products like yours. There are three main models: sales-led (your traditional “enterprise,” high-touch model to win committee decisions), marketing-led (low-touch that brings together a buyer and decider), and product-led (zero-touch where the initial buyer is the decider. Think: Slack, Dropbox, Atlassian, Zoom).
  • Build a repeatable sales playbook. The physics of the customer journey informs a playbook to find and win customers consistently. A great playbook answers four key questions: what are the steps in the customer journey? What’s the “lightbulb moment?” What is said/done at each stage? How does the rest of the company support each stage?

Building a Repeatable Sales Playbook

A repeatable sales playbook starts with initial outreach — typically by — to prospects, emphasizing relevance to your targeted decision-makers’ needs and pain. Initially, prospects don’t care about how great your product is, and they certainly don’t care about your product features (“speeds and feeds”) or vague promises to save time and money. The goal is to catch their attention. The best way to do this is to teach them something, to share information that might offer them an advantage. The best salespeople challenge prospects. My incredible team at Google showed Walmart’s CMO a dashboard highlighting how Amazon was eating their lunch — by market and product category. We showed him that 5% of the consumer electronics category shifted online each year and that Amazon was scooping up close to 50% of that revenue. That got his attention and the first meeting in Bentonville. The same team also educated Macy’s leadership team on how, when, and why consumers bought mattresses, starting with extensive online research. The common denominator? Get creative. Do the work.

Persistence pays off. Subsequent follow-ups are part of the playbook and should be additive to initial outreach, not just nagging or “bumping back to the top of your inbox.” Again, try to personalize and humanize your outreach. Experiment with different approaches that help you stand out. Then measure and optimize three critical metrics for your : open rate, click-through rate, and response rate.

Once you secure a meeting, pre-call preparation is vital. You’ve worked hard and creatively to get to this meeting. Don’t waste this precious opportunity. Research leads and prospects, then translate insights into a pre-call document identifying what elements of your value proposition are likely most resonant. It would help if you also understood how the company positions itself and recent press — positive and negative — as potential fuel for your solution.

Prepare what you will say during the meeting. Most meetings follow a predictable rhythm and flow. Outline key talking points and flow for discussion, highlighting who says what, when. This can be scripted out, although it’s essential not to sound scripted or “salesy.”

Objection handling is an essential and typically predictable part of any meaningful sales discussion. Create an inventory of objections. Ask t questions to tease out their objections. Home in on the 2–3 that really matter, and have excellent objection handling on these.

The “Wow” or “lightbulb” moment is usually the demo. This is your chance to flip the proverbial light-switch — when you clearly show how the product addresses your customers’ pain. It’s best to use the prospect’s actual data, if possible, to make your solution more meaningful and tangible. Great sales reps can convince the decision-maker at this point and move to close them.

The close is essential. You have to ask for the sale. Make a specific proposal, next steps, timing, and then follow up until the deal is closed.

Accelerating Sales Velocity

With a repeatable sales playbook, you can experiment to accelerate your sales velocity. This can be expressed in a formula:

Sales Velocity = (# * $ * %) / T

# = number of leads, $ = average contract value, %= conversion rate, T = time to convert

Predictive models score prospects based on online behavior (e.g., searches, installation of a software development kit (SDKs) from competitors, upvotes, comments, etc.) and company characteristics (e.g., size, location, etc.). This prospect score represents an estimated value of a particular user segment/cohort before they visit your website. Predicted value informs acquisition spending by segment and the best way to handle each lead.

High quality leads with a high propensity to convert should be handled with as little friction as possible, ideally with excellent documentation and well-tuned user flow and first-mile experience. Sales teams naturally gravitate towards these leads, even though marketing automation and self-service are likely the best choices. A better use for sales teams is providing a near-real-time response to high quality leads with a lower propensity to convert (or a longer sales cycle) or focusing on getting more business earlier (e.g., high average contract value with more seats or higher tier product/usage).

Understanding intent before a prospect visits your website informs outbound marketing. Outbound (e.g., , chat, sending physical goods, etc.) works very well when reaching prospects with high intent. Building a system that surfaces intent and scores each lead allows personalized online journeys and experiences. It’s also possible to identify key decision-makers and enable sales teams to effectively reach out to high-value prospects in a personalized and timely manner. These initial conversations shouldn’t feel “salesy,” but like a genuine desire to understand their specific problem and reason for visiting your website. Don’t try to name your children on your first date; aim to understand and offer to be truly helpful. The goal is near-real-time outreach because reaching a decision-maker when they’re engaged and have revealed high intent. This single tactic typically increases sales conversion by almost 50%.

Optimizing lead flow requires clear accountability and dynamic lead routing. Once a lead is scored, and the optimal treatment is determined, it is assigned in Salesforce to a representative who is given 12–24 hours to initiate contact. If this doesn’t happen, then another representative should do so; alternatively, send an automated /chat. Dynamically route more leads to high-performing reps and fewer leads to low-performing reps.

Once a customer has signed up, sales representatives should remain involved in the handoff to Customer Success. This handoff kicks off the activation that ensures customers experience your product’s magic as soon as possible.

Enabling Sales Processes and Modern Tools

There are several critical enabling sales tools and processes including,

  • A standardized system of action. Every sales team member must be master your repeatable playbook. Sales enablement platforms (e.g., Guru, Seismic, Hubspot) provide instant access to knowledge, messaging, and personalized content proved to be the most effective for any buyer interaction. This ensures consistency and accountability and allows measurement and optimization at each step of the sales playbook.
  • Sales compensation. Incentives for sales reps and their manager include territory definition, team, individual quotas, and compensation covering the initial sale, expansion, and renewal. Technology companies often try to “reinvent” things. Resist the urge to do so around sales incentives; the tried and true methods work. David Sacks has an excellent post on this, including the simple math to optimize sales compensation for your company. Here is a related post on quota calculations and a tool to model your growing sales organization.
  • Sales performance management. Beyond just measuring quota achievement, it’s essential to measure various inputs such as quantity and quality of prospect interactions. This helps objectively assess performance to incentivize high-performing sales reps and determine how to coach low-performing sales reps. This is an emerging category with dozens of companies and tools to consider. The best teams ingrain measurement and continuous improvement in their culture.
  • Voice of the customer. Listening to your customers helps optimize sales and success playbooks. Another key benefit is to integrate learning from sales and support into your product development process. Primary research and key sales insights prioritize where to spend product development calories to ensure happy current and future customers.

Customer Success & Support: Performance Gear

Customer Success and Support help you tune-up performance and find areas for expansion and growth while you’re on the road.

Customer Success: Land, Expand, Explode!

Customer love fuels excellent companies. Customer success is a vital way to earn that love with a scalable, repeatable, proactive process that ensures customers get the most out of your product. Managing churn all comes down to ensuring proper usage in the first 90 days. This involves a dedicated team with a clear and robust checklist of the things that the best accounts do. The more customers use products in the first 90 days, the less likely they are to churn; getting this right is the number-one driver of net retention.

A separate Expansion team can use data and dashboards to identify other opportunities to expand your product to additional teams within an existing customer. These dashboards also serve as early detection systems to alert your team to take proactive action and provide input to product roadmap decisions.

Beyond expansion, explosive growth requires every customer to have at least one champion who is a product expert and evangelist on your behalf. Once identified, the champion should receive the royal treatment: invited to join advisory panels, featured in case studies, provided early access to products, sent schwag, invited to meet your team. Internal champions are often overlooked but are essential to help you navigate your customers’ organization and ensure your message is landing in the right way with key decision-makers and influencers. Champions galvanize a community of end-users and act as a lubricant for any GTM engine.

Success is about proactively ensuring customers get the best product experience possible. Service is about the reactive response when things don’t go as smoothly as planned.

Customer Service/Operations: Turning a negative into a positive

Your company’s mission requires service to match the elegance of your product. While the service bar has been set very low by most companies, your goal is to reach leading hospitality and technology companies’ service levels. Indeed, striving for remarkable moments can be more achievable and more cost-effective than you might imagine.

Optimizing your service model is a journey characterized by step-function improvement and constant catch-up to product and sales. Service models break with scale; it’s not unusual to reinvent the model every time you add a zero to average selling prices. Knowing this and preparing for it is critical, especially when it comes to hiring decisions. While difficult, it’s easier to move upmarket than it is to go down market. Once you move from an average contract value of $10,000 to your first $100,000 contract, your organization will figure out how to support this customer. The opposite is not true, making it hard to move downmarket. Staffing service teams with intelligent, resourceful, creative leaders will keep you ahead of the curve. Several well-run companies groom high-potential leaders in service roles early on — customer service gap surface where your engine is leaking oil. Service can be a strategic weapon and a high-ROI activity to ensure low churn/high cohort health.

Beyond the regular service channels of , chat, , and website contact forms, social — especially Twitter — is an excellent channel for customer communication on support issues and customer feedback. Not only is Twitter a high-leverage way to support customers, but it also enables near-real-time human interaction, transparency, and a chance to strengthen your brand by resolving issues in memorable and fun ways.

Regardless of how you meet your customers’ service needs, it is essential to measure customer satisfaction (“transactional” CSAT), response, and resolution times, and invest in training, tools, analytics, and resourcing to exceed expectations consistently.

Customer service metrics are some of the many things that robust internal systems should track in an automated and seamless manner.

Internal Operating System

Thanks to the cloud, we now have data on virtually every customer interaction, and it’s possible to instrument and measure almost all aspects of a customer’s journey and product usage. Weaving together these data, tools, and processes are challenging but essential to scale your operations. Doing so ensures a single view of the customer and their journey with your company. It provides an objective view of how your product and organization perform and highlights actions needed to close experience gaps.

A robust internal operating system includes four features:

  • Customer Journey: Collecting data around prospect intent lead-scoring, customer decision-making processes, and paid and organic marketing activity. The centerpiece is a growth map that mirrors the equation of your business and links inputs to critical outputs. The goal is to instrument your customers’ journey across all engagement methods (e.g., website, , chat) so that you understand why customers behave or feel a certain way. This also includes cohort data that track behavior over time.
  • Sales System of Action and Performance Measurement: Mapping and tracking each step of your sales playbook is essential to learning and optimizing over time. Your operating system includes a system of action ー CRM, marketing and nurture platforms, content management systems ー and a centralized place to measure customer-facing employees and teams’ performance.
  • Personalization Engine: Personalization leads to higher engagement through feature recommendations and context-specific suggestions to get the most out of a product or community. Doing this consistently and at scale requires understanding usage at the individual, team, and company levels.
  • Product Experience: Uncover and measure how well your product is delivering vs. expectations and how likely customers recommend (e.g., Net Promoter Score). This also includes tracking technical product performance such as uptime, latency, crashes, and bugs.

An internal operating system is akin to the system and dashboards that Formula 1 racing crews use to capture and monitor performance. During a race, a car generates 1,500 data points per second. The crew translates these data into real-time dashboards that inform changes to race strategy and how to fine-tune the car’s engine and equipment. Your product and GTM engine generate signals that can help you adjust as you chase your dream.

In Summary

A modern and effective GTM engine powers all customer interactions and propels you closer to your vision. To build a robust engine, you must understand and leverage each one of its gears. By drilling in on marketing, partnerships, sales, success, support, and your internal operating system, you can build a machine capable of winning customers and delivering exceptional experiences that drive sustainable, long-term growth.

— — — — — — — — — — -

Special thanks to several people whose perspectives, leadership and wisdom helped shape my thinking on building an effective GTM engine: Gary Briggs, Nicolas Darveau-Garneau, Jason Lemkin, Jonathan Metrick, David Sacks, Julian Shapiro, SzeJack Tan, Sarah Tavel, Bob Tinker, Brett Willms, and Kelly Wright. Thanks to my teammates and fellow GTM builders and mechanics, it’s been exhilarating to experiment together and build and scale some remarkable engines.

This is a living document, and I welcome feedback. Please add in comments or reach out to my on LinkedIn.

Enhanced Ecommerce Guide For Google Tag Manager

Enhanced Ecommerce is certainly one of the finest reporting user interface features that Google Analytics has to offer. Enhanced Ecommerce, as the name implies, is a set of dimensions, metrics, and reports, which combine to provide you with a fairly complete view into how users are interacting with your products in your webstore. The main downside of Enhanced Ecommerce is, as with all good things, that it’s complicated to implement.

Luckily, there’s Google Tag Manager. Theoretically, you could implement Enhanced Ecommerce through Google Tag Manager without ever adding a single line of functional logic into the codebase of your web site. You could do everything by simply scraping the Document Object Model (DOM). However, as we have hopefully learned over the years - GTM is a tool with which fastidiousness trumps fast.

Whenever you’re working with dataLayer, for example, you’re investing into the stability of your data collection process. Thus, even though I will be talking about DOM scraping further on in the guide, the focus here will be on a setup where the front-end produces HTML documents and/or JavaScript that populates the Ecommerce values into the dataLayer without using DOM scraping or other client-side hacks to do the job.

There is a lot of information in this article. Much of it is already covered in Google’s excellent Enhanced Ecommerce Developer Guide, but there are plenty of gotchas that I might have covered in earlier articles (see the Further Reading chapter), or which I might not even have written down before.

NOTE! This is an implementation guide. If you want to know how Enhanced Ecommerce works or how to map your site into relevant interactions, you’ll want to look at Google’s support center documentation.

X

The Simmer Newsletter

Subscribe to the Simmer newsletter to get the latest news and content from Simo Ahava into your inbox!

How to read this guide

Obviously, it would make sense if you read the guide from top-to-bottom. However, I fully acquiesce that the loquaciousness of my rhetoric might be tedious to some in all its verbose glory. Also, sometimes I write douchy things like that.

So, depending on what your role is in the implementation project, there might be only some chapters that are relevant for you. However, don’t neglect to consult with all the stakeholders in the project! It doesn’t make sense for a developer to write code without understanding what the code is needed for. Similarly, it doesn’t make sense for the person operating Google Tag Manager to utilize the dataLayer structures without understanding the limitations of the back-end or front-end systems.

If you are a developer, tasked with implementing the dataLayer objects, you’ll want to read the following chapters (in order):

  1. Introduction
  2. Populate the Data Layer
  3. A word on scraping the DOM
  4. Combining different data types in a single EEC hit
  5. Product-scoped Custom Dimensions and Metrics
  6. Remember: be consistent
  7. Data types: Actions and all its sub-sections
  8. Data types: Impressions and all its sub-sections
  9. Data types: Promotions and all its sub-sections

If you are the person tasked with setting up EEC via the Google Tag Manager User Interface, you’ll want to focus on the following chapters (in order):

  1. Introduction
  2. Differences (and similarities) to Standard Ecommerce
  3. Send the data to Google Analytics using the Data Layer
  4. Send the data to Google Analytics using a Custom JavaScript variable
  5. Page View or Event tag
  6. Data types: Actions and all its sub-sections
  7. Data types: Impressions and all its sub-sections
  8. Data types: Promotions and all its sub-sections
  9. Debugging the setup
  10. Golden rules of Enhanced Ecommerce

As I said, I still wish you’d spend the time reading the entire guide. I don’t think there’s any irrelevant information to anyone working on the project, and it makes sense to understand the full complexity of the implementation rather than focus only on the things that are directly relevant to your work.

Introduction

Implementing Enhanced Ecommerce requires an overview of the following components:

  • The various data types that can be sent to GA (Actions, Impression Views, Promotion Views).

  • How the 'ecommerce' object is compiled and pushed to dataLayer (or generated with a Custom JavaScript variable).

  • How this data is sent with a tag to Google Analytics.

All three of these components are necessary, and all three require some understanding of how Google Tag Manager works, how tags and triggers interact with dataLayer, and how the Enhanced Ecommerce data is sent to Google Analytics. These will all be covered in this guide.

Needless to say, if you want a robust implementation, interaction and co-operation with your site’s front-end developers is an absolute must. Typically, the front-end developers utilize page templates and server-side variables (using PHP or React.js, for example) to build the HTML structure of any given page. On Enhanced Ecommerce pages, it’s important that they integrate the front-end with whatever ecommerce system you have in use, so that this system produces the necessary values dynamically for the front-end developers to funnel through into the dataLayer.

For interactions that take place after the page load, such as cart interactions, the front-end developers might need update the site JavaScript to populate the dataLayer object with the necessary values in the client.

Or you can just throw caution to the wind and scrape everything off the HTML itself through Google Tag Manager. The purpose of this guide isn’t to recommend any specific course of action, but to highlight the different ways in which you can run the Enhanced Ecommerce implementation project.

Differences (and similarities) to Standard Ecommerce

If you’ve been running Standard Ecommerce through Google Tag Manager, there are mainly three major differences between that and Enhanced Ecommerce.

  • Standard Ecommerce only collects transactions (i.e. “Purchase” hits in EEC) - there are no other components to its funnel (in fact, there is no funnel).

  • Standard Ecommerce uses a different category format.

  • Standard Ecommerce doesn’t support Product-scoped Custom Dimensions and Metrics.

One thing to pay heed to is that you can collect both Standard Ecommerce and Enhanced Ecommerce hits to an Enhanced Ecommerce -enabled Google Analytics view! This means that if you leave your “old” tracking in place and run an Enhanced Ecommerce implementation in parallel, you might end up double-counting transactions.

Google Analytics does deduplicate identical transactions sent in a session, but it’s enough for some component in the two different tracking methods to differ for GA to collect the data twice.

Product Category is collected to a different dimension, depending on which method you are using. So if you populate the category key for a product using either method, the dimension you’re looking for in GA is going to be different.

Implementation guidelines

The following chapters will cover certain aspects of an Enhanced Ecommerce implementation. As I stated in the Introduction, how the values are populated into dataLayer depend on the integration between your site’s front-end and the Ecommerce platform you use. Some platforms such as WooCommerce for WordPress introduce this integration using a plugin, others such as Magento provide it out-of-the-box as a feature.

However, there are plenty of custom Ecommerce platforms and setups out there which require tinkering for them to produce the values into variables that your front-end developers can then utilize.

The next chapter, for example, simply instructs what the generic dataLayer object needs to look like. How you end up populating the values into the required keys is up to you, but typically it’s done in one of the following ways:

  1. The dataLayer.push() is written directly into the page template by whatever server-side mechanism you have for producing the templates.

  2. The dataLayer.push() is generated dynamically by your web server or the Ecommerce platform using typically a combination of JavaScript and HTTP requests.

  3. The key-value pairs are populated by scraping the page HTML using Google Tag Manager.

Populate the Data Layer

Enhanced Ecommerce requires a specific syntax for the objects pushed to dataLayer or generated with a Custom JavaScript variable. For example, a dataLayer.push() with the minimum required Ecommerce object for a Purchase looks like this:

Do note that Google Tag Manager only reacts to dataLayer.push() commands. No other array methods will do anything in GTM, so it’s imperative that you do not improvise with this. All the interactions with dataLayer must be done with push().

Within the push, all the keys listed under and including ecommerce are required. The event key is something I strongly recommend to add to every single dataLayer.push() object.

Now, you will need to populate the keys in the object with relevant values. For example, the value for ecommerce.purchase.actionField.id would need to be a unique identifier of the order itself. You could generate one randomly using JavaScript, but typically you’ll want to use the same order ID that was included in the actual transaction. That way you can later augment details about this transaction using Data Import, for example.

Similarly, you’ll need to collect details about the products in the transaction, and send any variant, brand, and category information as metadata, too.

How you do this really depends on what the integration to your Ecommerce system is like. It’s impossible to give generic instructions, because each Ecommerce platform differs in how it provides the values for you to exploit in other on-site code. But if you already have an Ecommerce system in place, I recommend you read through its documentation and try to find out how you can request or access these values and variables from this system.

Send the data to Google Analytics using the Data Layer

When you select the Use data layer option in the Enhanced Ecommerce settings of a Google Analytics Page View or Event tag (or a Google Analytics Settings variable), you instruct the tag to look into the Data Layer and pull the key-value pairs from the ecommerce object pushed most recently into dataLayer.

This sounds pretty straight-forward. All you need to do is make sure the object pushed into dataLayer follows the exact correct syntax, and that it’s pushed into dataLayer before (or in the same push as) the tag that accesses the data via Use data layer fires.

However, there are two important things to note here.

  1. The dataLayer.push() must be perfectly formed. There’s no way to modify it on-the-go if you activate the “Use data layer” option. So it’s absolutely vital that you specify and audit the object that is being pushed into dataLayer for Enhanced Ecommerce data collection.

  2. When a tag with “Use data layer” fires, it really only accesses the most recent ecommerce push. So, if you’ve split Product Impressions into multiple pushes and then fire the tag when the last one is done, if the tag has “Use data layer” checked, only the last impressions object is sent to Google Analytics.

Point (2) might sound counter-intuitive, but it actually makes sense. If GTM didn’t exhibit this behavior, then all ecommerce pushes done on a single page would tag along with all the subsequent Enhanced Ecommerce payloads. By sending only the most recently pushed object, this behavior can be avoided.

It’s precisely because of this behavior that I again strongly recommend to always include the event key in every single Enhanced Ecommerce object. Why? Because then you can use Custom Event triggers to fire your Enhanced Ecommerce tags at precisely the correct time, and the most recent object they access will always be the one that triggered the tag. That way you won’t lose any data because of pushes that didn’t trigger any tags.

However, you might want to take a look at the next section, too.

Send the data to Google Analytics using a Custom JavaScript variable

One of my main issues with the dataLayer object syntax for Enhanced Ecommerce in Google Tag Manager is its rigidity. The “Use data layer” option requires that you follow a very specific, unwieldy syntax.

This means that it might be a huge effort to get the data into the correct format in the first place. But then you also need to have a process in place so that you can update it with minimal delay, and so that you can audit it to make sure no data is lost.

So, thankfully, Google Tag Manager also lets you send the data using a Custom JavaScript variable.

Using the variable has a very simple logic. All the variable needs to do is return a valid ecommerce object. In other words, the variable needs to return exactly the same thing that the developers would push into dataLayer in a perfect world.

And how is this useful? Well, you could have the Ecommerce data pushed into dataLayer in any format, and then use the Custom JavaScript variable to transform it into a valid ecommerce object. This way, you don’t need to confuse matters with a rigid dataLayer specification, but rather the Ecommerce platform can push the data into dataLayer in whatever format suits it best. Then, with some JavaScript magic, you can pull this data through the Custom JavaScript variable into your tag.

Or, if you want to go the DOM scraping route, you can do all the scraping in the Custom JavaScript variable, and have it return a valid ecommerce object with all the key-value pairs in place.

You can also modify a valid ecommerce object in the dataLayer in case you need to add some dynamic updates to it (such as Product-scoped Custom Dimensions). For example, here’s me adding a Product-scoped Custom Dimension to all the products in a Purchase object:

With this simple example, I’m updating a perfectly valid ecommerce object (represented by {{Data Layer Variable - ecommerce}}), by adding a new field to every single product.

As you can see, I’m making a copy of the original variable with the JSON.parse(JSON.stringify(obj)) method. Because JavaScript copies objects by reference, any changes you make to the ecom variable would reflect in the original object stored in dataLayer. This might have adverse effects if the variable is run more than once, especially if you’re running calculations on any fields (the calculations would be done over and over again).

One additional important thing to note. Data Layer Variables are, by default, Version 2. This means that they will merge all the existing ecommerce pushes into one big ecommerce object. So when you create the variable for ecommerce, you might want to use Version 1. Read this article for more information.

Page View or Event tag

Whether you want to use a Page View or Event tag and how you setup your Custom Event triggers is completely up to you.

Personally, I always use Event tags. Why? Because if you use a Page View tag, you lack insight into what Enhanced Ecommerce events have been collected in Google Analytics. This might make debugging a broken implementation difficult. By using events, I can always look at the Top Events report to see all the Enhanced Ecommerce hits sent to GA.

You can even add things like order ID as the Event Label of these hits, so that you can really start debugging if the event for the order was sent but no transaction was actually received in the Ecommerce reports.

If you do use an Event tag, setting the nonInteraction field is, again, up to you. Personally, I set it to true when the event is sent with the page load, and false in all other instances.

But you do exactly what works best for you. Sometimes you might want to avoid events if you’re approaching the 500 hits per session limit. Not a good reason, but a reason nonetheless.

A word on scraping the DOM

Scraping the DOM refers to the habit of accessing the dynamic HTML representation of the page (the Document Object Model) directly with JavaScript and populating the Enhanced Ecommerce key-value pairs with values found on the page. On a receipt page, for example, you often see the order ID, the total value of the transaction, all products, shipping costs, and so forth. So you could just as well scrape these from the page rather than going through a complicated specification project with your front-end developers.

It’s not pretty, and it comes with a lot of baggage and technical debt. For one, you’re introducing a huge weak link in your tracking. If anything changes on the page, e.g. due to an A/B-test, it’s possible your scraper will break.

Furthermore, it’s fairly common to not include all details about products on the receipt page. Typically, just the name, ID, price, and tax of the line item is enough. This means you’ll miss all the other vital metadata such as product category, brand, variant, etc.

In other words, scraping might be the easy way to get some data quick, and for that it’s a great tool. But used on its own to carry the data quality of your entire Enhanced Ecommerce process? Not so much.

Combining different data types in a single EEC hit

Enhanced Ecommerce in Google Tag Manager allows you to send more than one data type in a single Enhanced Ecommerce hit. This is because all the data types are deconstructed into parameters of the Google Analytics request, and as long as each parameter only has a single value, you can combine them to your heart’s content.

However, you can’t combine them in any way you like. The rule of thumb is that each hit can only contain one Action, one Impression, and one Promotion object. But it gets a bit more complicated than that, since there are more shared fields between the different data types, invalidating certain combinations. Here are the valid combinations you can send:

  • Impression View with Promotion View and Action

  • Impression View with one of Promotion View or Action

  • Promotion View with one of Impression View or Action

See the chapter titled Data types: Actions to understand what Actions comprise. Note that Impression Click and Promotion Click are Actions even if they’re listed in a different chapter (it was more logical to group them with impression and promotion views, respectively).

A typical mistake is to try to send a Product Detail View and a Product Add To Cart in the same push, or a Product Add To Cart and a Product Checkout in the same push. This isn’t valid, since these objects occupy many of the same parameter names (e.g. all the product keys), so by trying to populate them twice in the same hit, you end up making a royal mess of things.

Product-scoped Custom Dimensions and Metrics

With Enhanced Ecommerce, Google Analytics introduced Product-scoped Custom Dimensions and Metrics. These are extra metadata that can be added directly into the objects within a products array.

The dataLayer syntax is, again, fairly rigid. They must be named dimensionN and metricN (where N is the index number), and they must be embedded in the product object that is included in the products array. For example, this is a valid way to send a Product-scoped Custom Dimension into index 5:

As you can see, dimension5 is in the object within in the products array.

Because of this rather rigid way of adding the dimensions and metrics, I suggest taking a look at the Custom JavaScript variable option for mutating the object pushed into dataLayer into a valid Enhanced Ecommerce object.

The Product List

Product List is a very important attribute in Enhanced Ecommerce tracking. For one, it’s really one of the only places in Enhanced Ecommerce where some sort of attribution takes place. But also, it’s a great way to look at how different parts of the site contribute to the success of your ecommerce efforts.

The Product List is a key that you can add into the actionField object of all Action data types. You can also add it to Impression View objects directly.

The attribution works in a very specific way. When you send the list attribute in one of your Enhanced Ecommerce actions or impressions, then after that every single subsequent Enhanced Ecommerce action will be credited to that list as long as the product IDs in those subsequent actions match those of the one where you sent the list.

In other words, if you send a Product Detail View for a product with ID 123, and you use the list value “discount”, then every single subsequent Enhanced Ecommerce action for a product with ID 123 within that session will be attributed to that list.

As soon as the Product ID changes or you send some other list value, this funnel will break and a new one will start.

You’ll also see plenty of (not set) product lists in your reports. This is due to sessions expiring and new ones starting without any Product List information. Naturally, if your funnel doesn’t include a Product List for all possible interactions, you’ll see (not set) due to this, too.

Do note that attribution is always session-scoped, so if the session timeout is reached or the session is broken for some other reason, attribution will break, too.

If this sounds confusing, please read my article on the topic.

Local Currency

If visitors to your site can choose to shop with different currencies, you can utilize Google Analytics’ Local Currency feature to normalize these values once they hit your GA reports. All you need to do is specify the currency code either directly in the dataLayer object, or as a field in the tag which sends the Enhanced Ecommerce data to GA.

For example, here’s what a dataLayer.push() for a purchase made with Euros would look like:

Note that if you use a local currency, remember to set keys like revenue and price in that local currency (so no need to do any conversions in the client).

GA will then convert these local currencies to whatever currency you have configured in the Google Analytics view.

If you want to add this currency code as a field in the tag (or Google Analytics Settings variable), you can add it by browsing to Fields to Set, and adding a new field:

Field name: currencyCode
Value: EUR

Instead of “EUR”, you can use a variable that pulls the currency code from e.g. the Data Layer or a browser cookie.

Remember: be consistent

One very important thing about Enhanced Ecommerce is that it’s (mostly) hit-scoped. The only exception is the minimal attribution with Product Lists and promotions.

In other words, if you send a Product Category of T-Shirt with a product in a Product Detail View, that information will only be available to queries involving Product Detail Views and that particular product. Nothing carries over or persists to the subsequent hits.

You’ll need to include all metadata about all products and all actions in all Enhanced Ecommerce objects.

This is one of the reasons why DOM scraping is not a good idea. It’s rare to see the same information on every single page where you have Enhanced Ecommerce actions.

This is also one of the reasons why implementing Enhanced Ecommerce might be a headache to developers. It’s possible that the different parts of the funnel are governed by different systems. For example, a fairly typical CMS setup could handle Product Detail Views, but then cart additions are done using a SaaS cart service, checkout is done using PayPal, and purchase receipt page is yet another system.

In order to persist all product data from one page to another, you might need to introduce client-side persistence using cookies or browser storage, for example.

Data types: Actions

Actions are Enhanced Ecommerce events that include some type of user-initiated action. This isn’t always a clear definition, and e.g. Product Detail Views could arguably not be user-initiated actions. But that’s the definition that Google uses.

The following chapters will depict what the dataLayer object for each action should look like, and what a typical tag/trigger combination would be.

Goto GTM to know more.

Product Detail Views

Product Detail Views are typically sent when the user views details about a product. This is, again typically, on a dedicated product page, but it could just as well be expanded content in a search results list, or something else.

Data Layer composition

Available fields in the ecommerce object:

Key Type Example Comment actionField.list String 'Expanded content' Where the Product Detail View occurred. Useful if you want to see how different “lists” contribute to funnel success. products[].id String 'P' The SKU of the product. I recommend sending any variant IDs using a Product-scoped Custom Dimension. products[].name String 'T-Shirt' The name of the product. Any variant name can be sent with the variant key. products[].category String 'clothes/shirts/t-shirts' Product category of the item. Can have maximum five levels of hierarchy. products[].variant String 'Large' What variant of the main product this is. products[].brand String 'NIKE' The brand name of the product. products[].dimensionN String 'Blue' A Product-scoped Custom Dimension for index number N. products[].metricN Integer 3 A Product-scoped Custom Metric for index number N.

This is what the dataLayer.push() for a Product Detail View would look like with all the relevant keys populated:

Remember, if you want to use a Custom JavaScript variable instead, the variable must return the ecommerce object from the dataLayer.push() above.

Tag configuration example

Typical Event tag:

The trigger would be a Custom Event trigger with the following setting:

Event name: eec.detail

Add to Cart

The Add to Cart hit is sent whenever a product (or products) are added to cart. The quantity of each product needs to reflect the number of items that were added to the cart in this action, and not the final tally of each item in the cart.

Data Layer composition

Available fields in the ecommerce object:

Key Type Example Comment actionField.list String 'Search results' Where the Add to Cart happened. If there are multiple places on the site where products can be added to cart, it’s a good idea to differentiate between them using the Product List attribute. products[].id String 'P' The SKU of the product. products[].name String 'T-Shirt' The name of the product. products[].category String 'clothes/shirts/t-shirts' Product category of the item. Can have maximum five levels of hierarchy. products[].variant String 'Large' What variant of the main product this is. products[].brand String 'NIKE' The brand name of the product. products[].quantity Integer 1 The quantity of this product added to cart. products[].dimensionN String 'Blue' A Product-scoped Custom Dimension for index number N. products[].metricN Integer 3 A Product-scoped Custom Metric for index number N.

This is what the dataLayer.push() for an Add to Cart would look like with all the relevant keys populated:

Remember, if you want to use a Custom JavaScript variable instead, the variable must return the ecommerce object from the dataLayer.push() above.

Tag configuration example

Typical Event tag:

The variable in Event Label is a Data Layer Variable that points to ecommerce.add.actionField.list. This returns the Product List of the hit, if any.

The trigger would be a Custom Event trigger with the following setting:

Event name: eec.add

Remove from Cart

Remove from Cart is what you would send when items are removed from the cart. The quantity you send for each item needs to reflect the quantity that was removed in the action, and not the quantity of items remaining in the cart.

Data Layer composition

The Data Layer composition for Remove from Cart is identical to that of Add to Cart.

Similarly, the dataLayer.push() example would be identical, except the first key under ecommerce is named remove rather than add, and the event name is different:

Remember, if you want to use a Custom JavaScript variable instead, the variable must return the ecommerce object from the dataLayer.push() above.

Tag configuration example

Typical Event tag:

The variable in Event Label is a Data Layer Variable that points to ecommerce.remove.actionField.list. This returns the Product List of the hit, if any.

The trigger would be a Custom Event trigger with the following setting:

Event name: eec.remove

Checkout

A Checkout is sent when the user enters the checkout funnel. For every discrete step in the funnel, you send a checkout hit to GA. Steps are typically pages (on a multi-page checkout) or sections of the form (on a single-page checkout).

The products array should only be sent with the first step. Sending it with any other step will do nothing.

You can also add an option key to the checkout hit, in case you want to send extra details about the checkout step itself (such as selected payment method or shipment method). Alternatively, you can use the Checkout Option action to send the option information after the step has first been sent-

Data Layer composition

Available fields in the ecommerce object:

Key Type Example Comment actionField.step Integer 1 The number of the checkout step. These should be sent in order, where the first step is 1. You can define what these steps mean in the Google Analytics Admin user interface. actionField.option String 'Visa' You can send the option key if there is extra metadata (e.g. shipping or payment method) you want to send with the step hit itself. products[].id String 'P' The SKU of the product. products[].name String 'T-Shirt' The name of the product. products[].category String 'clothes/shirts/t-shirts' Product category of the item. Can have maximum five levels of hierarchy. products[].variant String 'Large' What variant of the main product this is. products[].brand String 'NIKE' The brand name of the product. products[].quantity Number 3 The quantity of the given product checked out. products[].dimensionN String 'Blue' A Product-scoped Custom Dimension for index number N. products[].metricN Integer 3 A Product-scoped Custom Metric for index number N.

This is what the dataLayer.push() for the first Checkout step would look like with all the relevant keys populated:

The dataLayer.push() for the second Checkout step where you also send the payment method would look like this:

Remember, if you want to use a Custom JavaScript variable instead, the variable must return the ecommerce object from the dataLayer.push() above.

Tag configuration example

Typical Event tag:

The variables {{checkout step}} and {{checkout option}} are Data Layer variables for ecommerce.checkout.actionField.step and ecommerce.checkout.actionField.option, respectively. They return the corresponding values from the checkout hit.

The trigger would be a Custom Event trigger with the following setting:

Event name: eec.checkout

Checkout option

A Checkout option hit is always sent after the corresponding Checkout Step has already been sent. So you can’t send a Checkout option hit for step 2 if you haven’t first sent a regular Checkout hit for step 2.

Use the Checkout option hit to send extra information about a checkout step. For example, if Checkout step 2 is where the user chooses the payment method, you’ll want to send Checkout step 2 when the user first lands on the payment method selection page, and then the Checkout option hit after they’ve clicked or selected the payment method.

Data Layer composition

The dataLayer.push() is very simple. In actionField, you indicate with step to which Checkout step this option should be attached (Integer), and option is the option value itself.

Remember, if you want to use a Custom JavaScript variable instead, the variable must return the ecommerce object from the dataLayer.push() above.

Tag configuration example

Typical Event tag:

The trigger would be a Custom Event trigger with the following setting:

Event name: eec.checkout_option

Purchase

The Purchase hit is, arguably, the most important hit in the Enhanced Ecommerce funnel. Without a reliable Purchase hit being collected, all the funnels, attribution models, goal values, conversion calculations, and transaction data become fairly unusable.

In other words, make sure most of the resources is invested in getting the Purchase hit right.

Data Layer composition

Available fields in the ecommerce object:

Key Type Example Comment actionField.id String order_ The unique order ID of the transaction. Should match the actual ID of the order. actionField.affiliation String 'Simo Shop' Extra details about where the purchase happened. actionField.revenue String '11.00' Total transaction value. You can include tax and shipping, or you can choose to send the revenue without tax and shipping. The value must not include anything else except number separated by a decimal point. Don’t use a comma as the separator, and don’t include any currency symbols. actionField.tax String '1.00' Tax paid. Same formatting instructions as with revenue. actionField.shipping String '2.00' Cost of shipping. Same formatting instructions as with revenue. actionField.coupon String 'SUMMER' The coupon code that was used for the entire transaction. products[].id String 'P' The SKU of the product. products[].name String 'T-Shirt' The name of the product. products[].category String 'clothes/shirts/t-shirts' Product category of the item. Can have maximum five levels of hierarchy. products[].variant String 'Large' What variant of the main product this is. products[].brand String 'NIKE' The brand name of the product. products[].quantity Number 3 The quantity of the given product purchased. products[].price String '10.00' The price of one item. Same formatting instructions as with revenue. products[].coupon String 'SHIRTSOFF' The coupon code used for this particular product. products[].dimensionN String 'Blue' A Product-scoped Custom Dimension for index number N. products[].metricN Integer 3 A Product-scoped Custom Metric for index number N.

This is what the dataLayer.push() for a Purchase hit would look like with all the relevant keys populated:

Remember, if you want to use a Custom JavaScript variable instead, the variable must return the ecommerce object from the dataLayer.push() above.

Tag configuration example

Typical Event tag:

The variable {{order id}} is a Data Layer variable for ecommerce.purchase.actionField.id, and it returns the transaction ID. The variable {{revenue}} is a Data Layer variable for ecommerce.purchase.actionField.revenue, and it returns the revenue of the transaction.

The trigger would be a Custom Event trigger with the following setting:

Event name: eec.purchase

Refund

The Refund hit should be sent if the user requests a refund of the product through the website.

Important: this does NOT remove the original transaction or negate it in any way. The Refund hit is a hit of its own, and will be used to populate metrics like “Refund Amount” and “Product Refund Amount”. This makes the Refund hit type fairly useless, in my opinion, but it might have its uses if you simply want to know whether refunds are requested via the website.

Data Layer composition

Available fields in the ecommerce object:

Key Type Example Comment actionField.id String order_ If the user requested a full refund of the order, then you only need to send the transaction ID with the hit. products[].id String 'P' If the user only wanted a refund for some items, you need to also send the id of each along with the quantity refunded. products[].quantity Number 3 The quantity of the given item refunded.

This is what the dataLayer.push() would look like for a completely refunded transaction:

This is what the dataLayer.push() would look like for a partially refunded transaction:

Remember, if you want to use a Custom JavaScript variable instead, the variable must return the ecommerce object from the dataLayer.push() above.

Tag configuration example

Typical Event tag:

The variable {{order id}} returns the transaction ID that was refunded. The variable {{total quantity refunded}} is a Custom JavaScript variable which returns the total quantity of all items that were refunded.

The trigger would be a Custom Event trigger with the following setting:

Event name: eec.refund

Data types: Impressions

Impressions are what you send when the user sees a listing of products in a Search Results page, for example. Basically, wherever you show a listing of products without going into enough detail for that to count as a Product Detail View, use impressions.

Impressions comprise of a “view”, where the user sees the product in a listing, and a “click”, where the user clicks a product in the listing (to go to its Product Detail page, for example).

Note that you might be tempted to send all the products on the listing page as impressions in a single hit. This might get you into trouble with Google Analytics’ maximum payload size of 8KB (that’s typically around 30-50 product impressions). To avoid this, you can do a number of things, such as automatically reduce the payload length, or split the impressions into multiple hits.

The best thing you can do, but also the most complicated thing to implement, is to create a true view listener, where impressions are sent in batches depending on what the user actually sees in the viewport. So when the user scrolls to a new set of product impressions, you send only those impressions in a hit once they’ve all entered the viewport. This requires a lot of coordination with your developers, but it’s well worth the effort.

Impression Views

Impression Views are collected when the user sees a product impression in some listing, such as Search Results, Recently Viewed Products, or Related Products.

With Impression Views, it’s important to populate the list field with a label that describes the listing where the impression view happened.

Data Layer composition

Available fields in the ecommerce object:

Key Type Example Comment impressions[].id String product_id The SKU of the product. impressions[].name String 'T-Shirt' The name of the product. impressions[].category String 'clothes/shirts/t-shirts' Product category of the item. Can have maximum five levels of hierarchy. impressions[].variant String 'Large' What variant of the main product this is. impressions[].brand String 'NIKE' The brand name of the product. impressions[].list String 'Related products' The list name where the impression was viewed. impressiosn[].position Integer 3 The position of the item in the list (e.g. was it the first item in the list, the second, the third, etc.). impressions[].dimensionN String 'Blue' A Product-scoped Custom Dimension for index number N. impressions[].metricN Integer 3 A Product-scoped Custom Metric for index number N.

This is what the dataLayer.push() would look like for a set of product impressions with all the relevant keys included:

Remember, if you want to use a Custom JavaScript variable instead, the variable must return the ecommerce object from the dataLayer.push() above.

Tag configuration example

Typical Event tag:

The trigger would be a Custom Event trigger with the following setting:

Event name: eec.impressionView

Impression Clicks

Impression Clicks (or Product Clicks) are technically Actions, but I decided to group them under Impressions since that’s where they belong.

An Impression Click is sent when an impression that the user has viewed is clicked. It’s an important metric to follow in case you are measuring Impression Views, because once you start collecting Impression Clicks, too, you can measure things like click-through-rates per product list, position, and individual impression.

Data Layer composition

Available fields in the ecommerce object:

Key Type Example Comment actionField.list String 'Related products' The list where the user first viewed the product and then clicked it. Make sure the value of the list attribute matches that sent with the Impression View. products[].id String 'P' The SKU of the product. products[].name String 'T-Shirt' The name of the product. products[].category String 'clothes/shirts/t-shirts' Product category of the item. Can have maximum five levels of hierarchy. products[].variant String 'Large' What variant of the main product this is. products[].brand String 'NIKE' The brand name of the product. products[].position Integer 1 The position of the impression that was clicked. products[].dimensionN String 'Blue' A Product-scoped Custom Dimension for index number N. products[].metricN Integer 3 A Product-scoped Custom Metric for index number N.

This is what the dataLayer.push() for an Impression Click would look like with all the relevant keys populated:

Remember, if you want to use a Custom JavaScript variable instead, the variable must return the ecommerce object from the dataLayer.push() above.

Tag configuration example

Typical Event tag:

The trigger would be a Custom Event trigger with the following setting:

Event name: eec.impressionClick

Data types: Promotions

Promotions are similar to impressions in that they, too, comprise a View and a Click. However, unlike any of the other Enhanced Ecommerce data types, promotions do not involve products. Rather, you are measuring the promotions themselves. These would typically be banners, product category highlights or something similar.

With promotion tracking, you can measure the success of your site marketing efforts, by seeing if viewing and clicking individual banners and advertisements lead to ecommerce success.

Promotion Views

Promotion Views are sent when the user sees a promotion on the site. As with impressions, you can send more than one Promotion View in a hit, but as with impressions, you need to be careful not to group too many views into one hit, as you might be in danger of breaching the 8KB size limit for the Google Analytics payload.

Data Layer composition

Available fields in the ecommerce object:

Key Type Example Comment promotions[].id String 'summer_campaign' Unique identifier for the promotion. promotions[].name String 'Summer Campaign ' The name of the promotion. promotions[].creative String 'front_page_banner_1' A name for the creative where the promotion is showing. promotions[].position String 'slot_2' Some way to distinguish the position of the promotion in the creative (e.g. second slide of a carousel).

This is what the dataLayer.push() would look like for a set of Promotion Views with all the relevant keys included:

Remember, if you want to use a Custom JavaScript variable instead, the variable must return the ecommerce object from the dataLayer.push() above.

Tag configuration example

Typical Event tag:

The trigger would be a Custom Event trigger with the following setting:

Event name: eec.promotionView

Promotion Clicks

A Promotion Click is collected when an individual promotion is clicked. It’s important to measure these if you are also measuring Promotion Views, because this way you’ll get a solid understanding of the click-through rate of individual promotions and how these promotions are involved in generating revenue in your webstore.

Available fields in the ecommerce object:

Key Type Example Comment promotions[].id String 'summer_campaign' Unique identifier for the promotion. promotions[].name String 'Summer Campaign ' The name of the promotion. promotions[].creative String 'front_page_banner_1' A name for the creative where the promotion was clicked. promotions[].position String 'slot_2' Some way to distinguish the position of the promotion in the creative (e.g. second slide of a carousel).

This is what the dataLayer.push() would look like for a Promotion Views with all the relevant keys included:

Remember, if you want to use a Custom JavaScript variable instead, the variable must return the ecommerce object from the dataLayer.push() above.

Tag configuration example

Typical Event tag:

The trigger would be a Custom Event trigger with the following setting:

Event name: eec.promotionClick

Debugging the setup

Once you have everything in place, you’ll want to debug your setup. The things you are looking for are:

  • Are all the keys configured in the dataLayer.push() (or the Custom JavaScript variable) getting picked up and being sent to Google Analytics?

  • Is the payload length too long?

  • Is there a risk of data duplication with some hits?

To debug these, you really only need three tools: GTM’s own Preview mode, the Google Analytics Debugger browser extension, and Google Chrome browser’s DevTools. Yes, there are plenty of other tools you can use, but these have proven to be more than enough in my own experience.

Preview mode

With Preview mode, you can analyze what fields were sent with your Enhanced Ecommerce -enabled Google Analytics tag. You can also compare these fields with what was originally pushed into dataLayer, or what the Custom JavaScript variable returned.

Once you have your ecommerce object either pushed into dataLayer or generated by a Custom JavaScript variable, the next step is to go to Preview mode, then browsing the site and generating the action that sends the ecommerce data to GA.

Here’s what you’re looking for in the Preview mode:

In the left-hand side, you’re looking for the Event name that you pushed into dataLayer with the 'event' key. Remember, you should add one in to every single push?

Click that event, and you should see your Enhanced Ecommerce tag in the list tags that fired. If you don’t, it means there’s something wrong with its trigger. So find the tag in the list of tags that did not fire, select it, and scroll down to its triggers. You’ll see a red X next to each trigger condition that failed, so double-check them and make sure the conditions pass when they should.

Anyway, if the tag DID fire and if it sent an event (or page view) hit to Google Analytics successfully, you’ll see Succeeded as its Firing Status. Double-check that the Enhanced Ecommerce settings are correct, too.

Now you know that your tag fired and that it sent the event/pageview to GA successfully. But what about the Enhanced Ecommerce payload? Were all the keys and values you configured included?

For this, you have plenty of options. You can use a tool like Google Tag Assistant which will tell you what parameters were included in the hit. Or you can use David Vallejo’s excellent GTM Debug Chrome extension, which has a great visualization of the Enhanced Ecommerce data.

The key is to see what data was included in the hit and to compare that against what was pushed into dataLayer or what the Custom JavaScript variable returned.

Personally, I simply use the Google Analytics Debugger extension. It uses the JavaScript Console of the web browser to output a log of all the interactions with Google Analytics trackers on the page.

For example, in my Purchase example above, this is what the GA debugger will tell me:

Here, you can see that the hit is missing the tax that I pushed into dataLayer. The key I used was orderTax, as you can see in the screenshot.

So now I open this guide again, scroll all the way to the Purchase hit, look at the Data Layer Composition example, and see my mistake. It shouldn’t be orderTax, it should be just tax.

I fix the dataLayer.push(), re-run the test and now I can see that everything works.

Here’s the most important thing about debugging Enhanced Ecommerce hits:

Never be satisfied with using Preview mode alone. Preview mode will only tell you if a tag fired, NOT if it sent the correct data to Google Analytics. You must debug the actual payload sent to Google Analytics, too. For this, Chrome’s DevTools are a great tool, but there are plenty of extensions out there that outline the data in a clear and concise manner.

Golden rules of Enhanced Ecommerce

Now follow some Enhanced Ecommerce tips that I consider absolutely vital for any implementation. I’ve accumulated them over years of practice, and I don’t hesitate to call them “rules” even if I’m typically very cautious to give any kind of recommendations to anyone.

So read through them, and if you have more suggestions for golden rules, let me know in the comments!

Do whatever you want

This is important. You can use Enhanced Ecommerce however you want. There’s no law that forces you to use the data types in the way that Google recommends you to.

For example, not all websites have a shopping cart. You directly buy products from product pages. In those cases, don’t send the Add to Cart event. Or, alternatively, send a dummy Add to Cart whenever the user moves to the checkout funnel.

It’s entirely up to you.

Heck, you can even use Enhanced Ecommerce for something completely unrelated to ecommerce. For example, you can use it to track content engagement on your site.

The Purchase action is most important

The Purchase action is absolutely the most important part of Enhanced Ecommerce. You can ignore or mess up all the other steps in the funnel, but you will never want to screw up the purchase hit. So many metrics and dimensions rely on the transaction data to be accurate.

When you’re calculating the investment for implementing Enhanced Ecommerce, add some extra buffer to getting the purchase right. It’s that important.

Only one action per hit

Remember to only send one action per hit. There are other limitations, too, but this is the most common mistake.

You might be tempted to send multiple Checkout steps, for example, but this would violate this rule.

You can only include a single action in a dataLayer.push (or in the returned object from a Custom JavaScript variable), so make sure to debug this thoroughly.

Include all the necessary details in every hit

Consistency is key. If you send product details such as product variant, brand and category in a Product Detail View, you’ll want to send these with all the subsequent actions (Add to Cart, Checkout, Purchase), too. Otherwise when analyzing the funnel using any of these dimensions as the primary dimension of analysis, you’ll only see data for Product Detail Views and not for any of the other steps.

There is no automatic persistence or attribution of product metadata - you must send them with every single hit.

Also, the metadata must be in the same format in every step. You can’t send brand: 'NIKE' in one step, brand: 'Nike' in another, and brand: 'nike' in another, and expect Google Analytics to treat these as the same value. They will generate three different rows with their own funnels when analyzed using Product Brand as the dimension.

There is some attribution

Note that there is some attribution in Enhanced Ecommerce; in Product Lists and Promotions, specifically.

When a product is purchased, this purchase will be attributed to the last promotion the user clicked (or viewed if there was no click) in the session.

Similarly, when any Ecommerce action is taken, this action is also attributed to the last Product List that was included in an earlier action, as long as the Product ID in these two actions match.

In other words, if you send a Product Detail View for product with ID my_shirt, using product_page as the Product List attribute value, then any subsequent action that also involves my_shirt will be attributed to the product_page list. Useful, right?

Just remember that attribution is session-scoped. If the session timeout is reached, or if the session cuts off for some other reason, any Product List and Promotion attribution information is lost. That’s why you might see (not set) in the corresponding reports.

Be wary of the payload size limit

Remember that the maximum payload length of a Google Analytics request is bytes. If you’re collecting Product Impressions, or if the typical cart size in your store is 30+ products, you’ll want to see if you’re approaching this limit.

The Google Analytics Debugger will output an error into the console in case you are trying to send hits that are longer than this limit.

See this article for information how to track payload length, and this for a little tool that automatically reduces the payload length.

Further reading

I’ve written a lot about Enhanced Ecommerce. The easiest way to find this content is to simply do a search on my site.

As for other content, here is a random selection of goodies found on the web:

  • Google’s Enhanced Ecommerce Developer Guide for Universal Analytics

  • Google’s Enhanced Ecommerce Developer Guide for Google Tag Manager

  • Google’s Enhanced Ecommerce Demo Store

  • Bounteous’ Enhanced Ecommerce Guide

  • Bounteous’ Enhanced Ecommerce Variable Pack

  • Google Tag Manager For WordPress Enhanced Ecommerce Guide

Summary

I hope this guide is useful! It is written as an implementation manual rather than a guide for Enhanced Ecommerce in general.

Google’s own documentation is excellent, but there are places where it’s a bit misleading. With this guide, I wanted to get all the relevant information into one place.

Note that I don’t mention Google Tag Manager For Firebase at all. There’s a reason for that: it’s still underdeveloped. There is basic support for Enhanced Ecommerce, but nothing for Product-scoped Custom Dimensions or Metrics, for example. Hopefully these will be introduced soon into the SDKs.

As always, any comments are much appreciated! Please let me know if the guide was useful and if I glossed over or neglected to add some important information. Thank you!

Are you interested in learning more about GTM Gearbox? Contact us today to secure an expert consultation!