Tracking Offline Purchases with Enhanced Ecommerce and Google Forms



If you’re an online retailer, you know the importance of measuring online marketing and advertising efforts and how valuable this data can be for decision making. With Google Analytics’ Enhanced Ecommerce tracking, you can get insight into your online sales and how products and promotions are performing.

But what if your customers are making their final purchases offline? Wouldn’t it be great if you could get data for offline transactions into Google Analytics, ultimately allowing you to tie your users’ online behavior to their offline purchases? Even better, what if you could just do this with a simple form, without downloading or uploading any data?

Well, great news! You can do all of this with the Measurement Protocol.

Sayf has written extensively about this in the past, so make sure to read his post for more detailed information on why tying offline transaction information to online behavior is important for accurate attribution. In this post, I’m going to walk you through an Enhanced Ecommerce example, using a Google Form and a Google App Script.

The Objective:

To use the Measurement Protocol to tie offline transactions to online users, in order to better understand their path toward purchase and what drove them to our site.

The Requirements:

If multiple service representatives are taking customers’ orders offline, we need a standard, easy way for all of them to send transactional data into Google Analytics.

In Google Analytics, we want to see the same types of Enhanced Ecommerce data for offline transactions that we are already collecting for online purchases.

We want a tool that we can edit and troubleshoot quickly, without constantly involving a team of developers or designers.

With the objective and requirements in mind, we chose to build a custom Google Form that when submitted, sends a Measurement Protocol hit to Google Analytics. In addition to the form and App Script, we also had to do some preliminary setup on the site, as well as within Google Analytics and Google Tag Manager. You could try this solution if your orders typically don’t contain more than 2 or 3 products; any more and you will probably want something more automated.

Step 1: Create Custom Dimensions for Client ID and “Guest ID.”

We set up two user-scoped Custom Dimensions, called Client ID and Guest ID. The Client ID is really the important piece that we need.

When a user is browsing your website, their Client ID is what identifies them as a person. The Client ID is sent to GA with every hit (pageviews, events, etc.) If we can send this transaction to GA with the same Client ID, then GA will associate it back to the user that was browsing on the website. This means all of the great data about how that user found your website and what they browsed on your website is attached to this same transaction.

In our situation, it would be unreasonable to ask customers to provide the entire Client ID over the phone, so we created a shorter Guest ID based on the Client ID. The Guest ID is optional, but we chose to create it for this specific example.

If you are able to get the Client ID from another source (like if customers previously filled out a form on your site), there’s no need to create the Guest ID.

Step 2: Get the Client ID and Guest ID data using Google Tag Manager.

We pulled the Client ID from the tracker object with Google Tag Manager and sent it with a non-interaction event, similar to this method:

Within Google Tag Manager, we created the Guest ID from the Client ID by removing the “.” and then base-36-encoding it. At this point, we also enlisted the help of a developer, who placed an empty <div> tag on all pages with an ID of “guest-id.” We were then able to populate that <div> with the Guest ID, allowing customers to view their “code” on any page of the website.

We’ve included the code at the bottom of this post for doing the tough parts, you’ll need to decide where and how to display the Guest ID that it’s visible to the user calling in.

If you’re not sold on the idea of placing the Client ID on all of your site’s pages, no worries – you can display the Client ID or Guest ID wherever you’d like. For example, maybe you’d rather have it at the top of a user’s profile page or accessible from a specific URL, like


Step 3: Build the Google form.

Since we’re using Google Forms and its built-in features, this is the easiest part. We were more concerned with functionality than design, so we created a basic form that looked like this:

Offline Transaction Google Form

Along with Guest ID, the customer service reps needed to enter total transaction revenue and product details (name, price, quantity). You can see the full list of form fields that we used below.

Step 4: Create the App Script.

The original App Script was borrowed from Daniel Waisberg (who also wrote the foreword for this awesome book on Google Tag Manager). Thanks to Dan Wilkerson, LunaMetrics’ Software Developer, who engineered the Guest ID solution and modified the App Script.

Our version of the script not only maps the form fields to Measurement Protocol parameters, but base-36-decodes the Guest ID and returns it to the original Client ID format. It also adds additional required Measurement Protocol parameters like hit type and version, then sends the payload to via HTTP POST request.

You’ll need to add this to the project using the Script Editor.

You can get the full script at the bottom of this post.

The following parameters were sent automatically with the hit upon form submission.

  • tid – GA tracking id (required)
  • v – version (required)
  • cid – Client ID (required)
  • t – event (required – either event or pageview hit type can be used with Enhanced eCommerce parameters)
  • ec – event category
  • ea – event action
  • el – event label
  • ni – set to “1” for a non-interaction event
  • pa – product action (required for measuring purchases)
  • ti – transaction ID (set to a random value)

These additional parameters were mapped to the form fields and their values would be entered by the customer service rep. You could also add additional parameters and form fields, like tax, shipping, SKU, etc.

  • cd4 – Guest ID
  • tr – revenue, including tax and shipping
  • pr1nm – product 1 name
  • pr1qt – product 1 quantity
  • pr1pr – product 1 price
  • pr2nm – product 2 name
  • pr2qt – product 2 quantity
  • pr2pr – product 2 price
  • pr3nm – product 3 name
  • pr3qt – product 3 quantity
  • pr3pr – product 3 price

The final hit looked something like this:

Step 5: Set up a trigger for the Google Form.

This is really simple. From your form, open your Script Editor (Tools > Script Editor). From the Script Editor menu, view the current project’s triggers (Resources > Current project’s triggers). Set up a trigger to run the script on form submission, which should actually be the default when you create a new trigger.

The Results:

If the customers could provide their Guest ID over the phone, the customer service reps were able to easily enter the other details into and submit the Google Form. In Google Analytics, we were able to view all of the offline transaction data in the standard Enhanced Ecommerce reports, alongside data for online transactions. We were also able see which sources and mediums drove offline transactions, providing insight into how our advertising and other marketing efforts were contributing to overall sales goals.

There are so many ways you could tweak this solution to work for any business or industry, so let us know how you’re using this or something similar!

Scripts We Used

GTM Custom JS Variable – {{Base36 Encoding and Decoding}}

GTM 1st-Party Cookie Variable – {{Value of _ga Cookie}}

This is just a 1st-Party Cookie variable that pulls in the _ga cookie value.


GTM Custom JS Variable – {{Guest ID}}

Google App Script

Kristen Perko is a Senior Consultant at LunaMetrics. Her background is in search marketing, with a focus on SEO, analytics, and social media. Kristen has a passion for integrating goals and strategy with analysis and loves helping clients find value in their data. In her free time, she enjoys hiking, cross-country skiing, painting and anything food-related.

  • Thanks for this article, Kristen. Exciting concept for bricks and mortar small businesses. Do you have any examples (real or hypothetical) using this workflow?

  • Brian Maher

    Another great article, thanks. Can you please explain how you populated the with the guest ID? Might it be possible to package this up in a pop up delivered by GTM? Would be great if someone clicked on a coupon link, pop up was triggered to open during call centre hours only etc

    • Kristen Perko

      Hi Brian,

      In this case, we used GTM to populate the guest ID. Dan wrote some JavaScript to get the Client ID, encode it, then looked for the ‘guest-id’

      on each page. If that

      existed, the guest ID text was added to the page. But this is definitely not the only way to provide visitors with the guest ID – you could certainly get creative with GTM! Jon Meck wrote a great post with a few different ideas: Creative Tag Manager – Ads, Promotions, and Visitor Messaging
    • Brian – you can populate the empty via javascript. If you need a real example, just let me know and I’d be glad to share.

  • Philippe Denis

    Just curious: does making those measurement protocol hits also inflate visits counts in GA? And if so how do you deal with this visits inflation?

    • Stephen Brown

      Not if it’s a non-interactive hit. In this case it is non-interactive: [‘ni’ , ‘1’].

Contact Us.

Follow Us



We'll get back to you
in ONE business day.
Our Locations
THE FOUNDRY [map] LunaMetrics

24 S. 18th Street
Suite 100

Pittsburgh, PA 15203


4115 N. Ravenswood
Suite 101
Chicago, IL 60613


2100 Manchester Rd.
Building C, Suite 1750
Wheaton, IL 60187