Google Forms & The Measurement Protocol

Universal Analytics Form & The Measurement Protocol

A few months ago the Google Analytics team launched the Measurement Protocol, a powerful way for developers to send requests to Google Analytics from anywhere. This brings measurement to the next level, from websites and Apps to any customer touch point.

In this article I present the Universal Analytics Form, a solution I developed with my colleague Eduardo Cereto Carvalho, Web Analytics Specialist at Google. The form is an easy-to-use solution to implement the Measurement Protocol to upgrade your current tracking capabilities. Basically, we will use a Google Form and an App Script in order to send requests to Google Analytics using the Measurement Protocol. Sounds cool, doesn’t it? I think it does!

Use Cases

Here are a few cases where you might want to use this solution.

Integrating Offline Transactions into Google Analytics

Suppose you distribute coupons for store purchase in your website; and suppose you make some investment in online advertising. If that’s the case, you should be really eager to understand how much of your ad spending brought in terms of store revenue.

Using this solution, your store cashiers will be able to use a Google Form to update the coupon number and other information on Google Analytics. This way you will be able to link the offline spending to acquisition channels (and other info) for any customer. It is extremely important to keep in mind that Google Analytics Terms of Service strictly forbids to add personal identifiable information (PII) to your data collection, so make sure not to add information like name, surname, username, social security number, etc (see section 7 of link above).

While it is not very difficult to add a coupon ID to the form and get information about the purchase (as you will see in the video below), it might be a bit more challenging to have an ID that can link the offline to online information. The approach I would recommend is to use the Client ID command to retrieve a user Client ID and add it to the coupon. This way, the cashier will be able to fill it in the form too and the cycle will be closed.

Integrating Call Center into Google Analytics

Integrating Call Center data to your analytics data would be somewhat similar to the approach described above. However, it would require an additional step: during a call to complete a transaction, the call center will need an ID number in order to link the transaction to online activity. This can be done by asking the visitor to click on a button on the site that gets the Client ID on Google Analytics (see link above) and shows a popup with that number.

Integrating anything into Google Analytics

Logging expenses details into Google Analytics may also be an useful (and interesting) activity. Using this method, you can use a form to log all transactions you make during the day into Google Analytics. Then you can analyze your personal and/or business finances using Google Analytics powerful reporting and analysis UI. Remember: no PII.

Implementations Details

Below is a video explaining the method proposed in this article. In order to make the explanation clearer we used an example of a website that advertises online and direct visitors to a website where a discount coupon is offered (for purchases in a brick-and-mortar store).

Here are the steps required in order to implement the Universal Analytics solution (as explained in the video):

  1. Think profoundly about what information you need to collect in order to measure your goals. Read through the Measurement Protocol parameter reference to learn more about all the options available to you.
  2. Create a Google form and add one question to collect each data point that you will need. This will define which data will be collected and where it will be displayed on your Google Analytics reports.
  3. Copy the Script below and paste it into your Script Editor on Google Forms (find it on the "Tools" menu). Click Save.
  4. Edit the Script to match your data collection details (read the comments we left on the Script below for you). Click Save.
  5. Add a trigger for the Script to run every time a form is submitted. On the Script page, click on Resources and then on All your triggers. Click on No triggers set up. Click here to add one now and then click on save for the default trigger. You will need to provide permissions for the App, click OK.
  6. Set up Custom Dimensions on Google Analytics interface to work with the dimensions you added (if you decide to use Custom Dimensions). It might be helpful for you to read this article explaining what are custom dimensions.
  7. Make sure the relevant people fill the form every time data becomes available.
  8. Login to Google Analytics and have fun.

The Script

Below is the Script that you will need to copy to your Form. We tried to add as many comments as possible to guide you, but feel free to ask questions in the comments below if you have any.

var GA_TRACKING_ID = 'UA-xxxxxxxx-y';

// maps each form field to a field in GA
var data_mapping = {
  0: 'cid',   // User ID
  1: 'tr',    // Transaction Revenue
  2: 'ta'     // Transaction Affiliation
}

function trackForm(e) {
  var data = [],
      item,
      res = e.response.getItemResponses();
 
 
  for (var i=0; i< res.length; i++){
    item = res[i].getItem();
    if(data_mapping[item.getIndex()]) {
      data.push([
        data_mapping[item.getIndex()],
        res[i].getResponse()
      ]);
    }
  }

 
  data.push(

    ['tid', GA_TRACKING_ID],   // Uses the ID you provided in the beginning of the Script.

    ['v'  , '1'],   // The protocol version.

//  ['cid', Math.floor(Math.random()*10E7)],   // Remove the backslashes starting this line if you don't have a UID, this will set a random value.

    ['t'  , 'transaction'],   // The Hit type, must be one of the following: 'pageview', 'appview', 'event', 'transaction', 'item', 'social', 'exception', 'timing'.

    ['ti', Math.floor(Math.random()*10E7)],   // Assigns a randon value to Transaction ID.

    ['z'  , Math.floor(Math.random()*10E7)]   // Cache Buster.

  );
 
  var payload = data.map(function(el){return el.join('=')}).join('&');
 
  var options =
   {
     'contentType': 'application/json',
     'method' : 'post',
     'payload' : payload
   };
 
  UrlFetchApp.fetch('http://www.google-analytics.com/collect', options);
}

Happy Analyzing! And let us know if you have any comments, questions or suggestions. Also, we would love to know how you are using the Form, leave a comment below.

Related Content

  1. Google Universal Analytics For Offline Behavior
  2. Google Universal Analytics: A User-Centric Approach
  3. Collect & Process Data Wisely [cartoon]

Subscribe To Our Newsletter For Monthly Updates



Your e-mail will be kept private

Abiodun | September 2013

Am not too savvy with js.
I tried it, customized some part and I got this error
TypeError: Cannot read property "response" from undefined. (line 11, file "Code")

Here is my code

var GA_TRACKING_ID = 'xxxxxxxx';

// maps each form field to a field in GA
var data_mapping = {
0: 'cid', // User ID
1: 'tr', // Transaction Revenue
2: 'ta' // Transaction Affiliation
}

function trackForm(e) {
var data = [],
item,
res = e.response.getItemResponses();

for (var i=0; i< res.length; i++){
item = res[i].getItem();
if(data_mapping[item.getIndex()]) {
data.push([
data_mapping[item.getIndex()],
res[i].getResponse()
]);
}
}

data.push(

['tid', GA_TRACKING_ID], // Uses the ID you provided in the beginning of the Script.

['v' , '1'], // The protocol version.

['cid', Math.floor(Math.random()*10E7)], // Remove the backslashes starting this line if you don't have a UID, this will set a random value.

['t' , 'event'], // The Hit type, must be one of the following: 'pageview', 'appview', 'event', 'transaction', 'item', 'social', 'exception', 'timing'.

['ec' , 'googleDocs'],

['ea' , 'formSubmission'],

['el' , 'Data2Insights'],

['ti', Math.floor(Math.random()*10E7)], // Assigns a random value to Transaction ID.

['z' , Math.floor(Math.random()*10E7)] // Cache Buster.

);

var payload = data.map(function(el){return el.join('=')}).join('&');

var options =
{
'contentType': 'application/json',
'method' : 'post',
'payload' : payload
};

UrlFetchApp.fetch('http://www.google-analytics.com/collect', options);
}

Also, Is it only via custom dimension to access the hits?

I was also puzzled with the custom dimension. How do one set custom mapping?

Forgive my newbie :)

Daniel Waisberg | September 2013

Hi Abiodun. Looks like you mixed a few things.

First, I can see your GA tracking ID is still xxxxxx, not sure you left for privacy reasons or because you forgot to update... But that's the first thing.

Second, the code below, which are the dynamic parameters that will be replaced by the form response should go in the first part of the code. So the following:

['ec' , 'googleDocs'],
['ea' , 'formSubmission'],
['el' , 'Data2Insights'],

Should actually substitute the following (make sure the format is as below):

0: 'cid', // User ID
1: 'tr', // Transaction Revenue
2: 'ta' // Transaction Affiliation

As for Custom Dimensions, they are completely optional, take a look at the Parameter Reference linked in the article to learn more about all methods you can use.

And I strongly recommend you to take another look at the video :-)

Good luck!

Pedro | September 2013

Any tips how to get CID effectively and accurately pair offline and online data? :)

Daniel Waisberg | September 2013

That is definitely the one million dollar question Pedro! One thing is certain: your visitors must present him/herself in both medium, so you would need some form of signin.

In my example above I describe a way to do it for Coupons; once the coupon is requested you can retrieve the CID and add it to the coupon before generating it, which will enable you to link the behaviors on and offline. For call centers you would need some kind of customer action, in the lines of "go to the website and click on a button on the footer" (this will trigger GA to create a popup with the CID for the customer to read to the call center).

In summary, you will need to be creative!

Abiodun | September 2013

I checked the video as suggested, I battled this all day today. Please help!

Here is the Google form url https://docs.google.com/forms/d/1JZq4FH0BbnYZ0402Wy3bqRL4UIfzxAdqisQRGYz...

- I don't have a 'cid' so I chose the randomly generated number option.
- Am trying to the hit as send as event
- I left the UA out deliberately
- I changed the 't' to an event
Am I missing something? .js Newbie ;) Here is my code.

var GA_TRACKING_ID = 'XXXXXX';

// maps each form field to a field in GA
var data_mapping = {

0: 'ec', //Title
1: 'ea', //jobDescriptionn
2: 'el', //Name

}

function trackForm(e) {
var data = [],
item,
res = e.response.getItemResponses();

for (var i=0; i< res.length; i++){
item = res[i].getItem();
if(data_mapping[item.getIndex()]) {
data.push([
data_mapping[item.getIndex()],
res[i].getResponse()
]);
}
}

data.push(

['tid', GA_TRACKING_ID], // Uses the ID you provided in the beginning of the Script.

['v' , '1'], // The protocol version.

['cid', Math.floor(Math.random()*10E7)], // Remove the backslashes starting this line if you don't have a UID, this will set a random value.

['t' , 'event'], // The Hit type, must be one of the following: 'pageview', 'appview', 'event', 'transaction', 'item', 'social', 'exception', 'timing'.

['ti', Math.floor(Math.random()*10E7)], // Assigns a random value to Transaction ID.

['z' , Math.floor(Math.random()*10E7)] // Cache Buster.

);

var payload = data.map(function(el){return el.join('=')}).join('&');

var options =
{
'contentType': 'application/json',
'method' : 'post',
'payload' : payload
};

UrlFetchApp.fetch('http://www.google-analytics.com/collect', options);
}

Daniel Waisberg | September 2013

Abiodun, did you complete the following step and provided access for your app to run?

Add a trigger for the Script to run every time a form is submitted. On the Script page, click on Resources and then on All your triggers. Click on No triggers set up. Click here to add one now and then click on save for the default trigger. You will need to provide permissions for the App, click OK.

Abiodun | September 2013

I did all those steps actually. permission granted and script linked to my account.
See here
https://dl.dropboxusercontent.com/u/51751349/Data2Insights%20%20%20Googl...

Daniel Waisberg | September 2013

My comment above actually referred to the trigger, not the permission, see minute 08:32 on the video, I think that might be the problem.

Leticia Palos | October 2013

Hi!

How to set up google analytics to use Analytics Universal Form?

Regards

Daniel Waisberg | October 2013

Hi Leticia,

To use the form you will need to set up Universal Analytics. However, if you have a standard Google Analytics account and would like to migrate to Universal Analytics I would recommend you to wait a few weeks. The Analytics team just announced last week that there will be an automatic solution for migration soon.

Hope it helps!

Chris | October 2013

Nice script. Also appreciate the use cases. I don't have an opportunity right now, but I'd see this being great for events where registrants get discounts on purchases at local businesses or within a hotel complex.

Anonymous | October 2013

Wow - I love love this approach, do you think we can use this to do returns on an ecommerce transaction.

Avinash | October 2013

Wow, thats exactly what I am looking for.

I am slightly modifying your scrip to capture an event for every submission and in the process I would like to capture the e-mail address of the person who submits it. Can you give me the function which captures the e-mail address at every submission.

Anonymous | November 2013

Thanks for giving valuable information,
The above code given Hole page analytic’s,

But i am creating one Webpage,In that page i can place two buttons
I want to analyze that two buttons analytics using Google analytic’s?
It’s possible using google analytics?
if possible how can i do this one plz provide some code ans guidence

Daniel Waisberg | November 2013

I think you should be looking into Event Tracking

If you use the standard Google Analytics (ga.js) check this article.

If you use Universal Analytics (analytics.js) check this article.

Happy analyzing!

Ellen | February 2014

Thank you for explaining this all. I´learned a lot.

You write :
The approach I would recommend is to use the Client ID command to retrieve a user Client ID and add it to the coupon. This way, the cashier will be able to fill it in the form too and the cycle will be closed.

But when you make a form like this, I think you can use the coupon number to link it with a the client ID. So this way you would link purchase and coupon. By reading and seeing the video, I was thinking, that you did that. I´am not a real programmer. My question is: with this code in the form, do you send the coupon code to Universal Analytics or not?
And can you do that?

Thomas | April 2014

This is a fantastic video - thank you!

I am trying to think of a way to customize the conversion amount for this form submission. I have a field called "donation amount" and would like for my form to send a conversion equal to the amount submitted in that field. Can you think of a way to accomplish this?

I've sent several other people here - thanks again for this tutorial!

Post new comment
The content of this field is kept private and will not be shown publicly.
Refresh Type the characters you see in this picture.
Type the characters you see in the picture; if you can't read them, submit the form and a new image will be generated. Not case sensitive.  Switch to audio verification.
Online Behavior © 2012