Online-To-Offline Attribution Made Simple


The biggest issue facing most B2B lead-generation organizations today is attributing their best leads—you know, the ones that end up becoming paying customers—back to the marketing activity (or activities) that drove them to the website: paid campaigns, specific content, all that good stuff.

Turns out, it’s not so hard to bridge the gap between your CRM, marketing automation (MA), and web analytics platforms if you know where to start. It’s a process called “closed-loop analytics.”

Researching an Integration

Here at Portent, we use HubSpot for marketing automation and as our CRM. So, naturally, we were chomping at the bit to integrate with Google Analytics for our online-to-offline attribution.

If you’ve ever looked into this kind of integration before, Google’s documentation for integrating with popular CRMs is non-existent, with the exception of Google Analytics 360’s integration with Salesforce Marketing Cloud, which is exclusive to folks paying for the expensive, premium version of GA. There really are no best practices for this for free GA users. It’s the wild west out there.

So where does one begin? The key is setting a non-PII (Personally Identifiable Information) User ID, which will serve as a way to join the online and offline data sets together in the reporting layer. (Note: Google Analytics doesn’t accept PII like email addresses or phone numbers.)

Setting a Unique Identifier

Portent developer extraordinaire, Andy Schaff, formulated a simple script that serves two purposes:

  1. To set a random unique identifier cookie for each website visitor (called RUID for short).
  2. To pass that ID as a hidden form field into any lead form the visitor fills out during their visit.

Here’s the script:

function setCookie(cname, cvalue, exdays) {
  var d = new Date();
  d.setTime(d.getTime() + (exdays*24*60*60*1000));
  var expires = "expires="+ d.toUTCString();
  document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
function getCookie(cname) {
  var name = cname + "=";
  var decodedCookie = decodeURIComponent(document.cookie);
  var ca = decodedCookie.split(';');
  for(var i = 0; i <ca.length; i++) {
    var c = ca[i];
    while (c.charAt(0) == ' ') {
      c = c.substring(1);
    if (c.indexOf(name) == 0) {
      return c.substring(name.length, c.length);
  return "";
// searches all input elements on the page with an id that starts with "_guid_" and writes the provided value
function populateFormFields(value) {
  var inputs = document.getElementsByTagName("input"), item;
  for (var i = 0, len = inputs.length; i < len; i++) { item = inputs[i]; if ( &&"_guid_") == 0) { // starts with _guid_ document.getElementById( = value; } } } // if cookie "ruid" does not exist, generate and write if (!getCookie("ruid") || getCookie("ruid") == "") { var ruidCookie = ""; var chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; var length = 10; for (var i = length; i > 0; --i) ruidCookie += chars[Math.floor(Math.random() * chars.length)];
  // set "ruid" cookie with our alpha-numeric value. expires in 182 days, or ~6 months
  setCookie("ruid", ruidCookie, 182);
  // set the "ruid" cookie value to the form field upon initial creation. this is an edge case for when a user first lands on the page
} else if (getCookie("ruid")) {
  // set the "ruid" cookie value to the form field.


You might say “this looks like gibberish to me” and wonder how to deploy it to your website. Fortunately, this can be rolled out using a custom HTML tag via Google Tag Manager without bothering your developer.

Passing the RUID into Google Analytics

While you’re there deploying the RUID script in Google Tag Manager, you can also, conveniently, send it to Google Analytics with every pageview that occurs, even before a visitor fills out a form.

You do this by setting a User-Defined Variable which scrapes the value of the RUID cookie.

Screenshot of setting a user-defined variable for a RUID cookie in Google AnalyticsScreenshot of setting a user-defined variable for a RUID cookie in Google Analytics


After the variable exists, you can send it to Google Analytics with every hit as a Custom Dimension using the Google Analytics Settings Variable.

Screenshot of setting the RUID cookie as a custom dimension in Google AnalyticsScreenshot of setting the RUID cookie as a custom dimension in Google Analytics


Note: This also requires a User-Scoped Custom Dimension to be set up in Google Analytics (which generates the Index number “1” seen in the screenshot above).

Sending the RUID into Your CRM

The last important step before you get to your beautiful new closed-loop analytics report is setting up a field in your CRM system to receive the hidden RUID form field established earlier in Andy’s script.

Most CRM and MA platforms have the capability to establish “Custom Fields” that can be associated with any incoming contacts or leads to enrich the database with business-specific information. The creation of these fields and including them in the website lead forms is a slightly different procedure for each platform. Here’s an explanation of the process for several popular platforms.

We’ll be using HubSpot in our example, but we’ve included instructions to configure this field in other popular CRM and MA platforms.

Setting up Custom Properties in HubSpot

To generate a custom property in HubSpot, you go to Settings > Properties > Create a property.

Setting up Custom Fields in Pardot

To generate a custom field in Pardot, you go to Admin > Configure Fields > Prospects. Only Administrators can create this.

You can also set these fields to map to your Salesforce instance.

Setting up Customer Fields in Marketo

To generate a custom field in Marketo, you go to Admin > Field Management > New Custom Field.

Setting up Custom Fields in Eloqua

To generate a contact field in Eloqua, you go to Settings > Fields & Views > Add + > Add Contact Field.

Joining CRM Data to Analytics Data by RUID

Once you have the RUID appearing in both your CRM and Google Analytics, you can use data blending in Google Data Studio.

If you can export Lead Status information out of the aforementioned CRM platforms by User ID and store it in Google Sheets, you can join the data to any information we have in Google Analytics around that User ID (i.e., all of their web sessions, campaigns, content).

Here’s what our blend looks like:

Screenshot example of data blending in Google Data StudioScreenshot example of data blending in Google Data Studio


Once the blend is set up, you can get tables like these to introduce lead quality data to web analytics data:

Screenshot example of a table that introduces lead quality data to web analytics dataScreenshot example of a table that introduces lead quality data to web analytics data

Tada! More Info on Your Best Leads

Now that you have a fairly straightforward way to tie online and offline information together, you can start thinking about things like Lead Scoring and bringing any PII associated with your IDs back into dashboards for your marketing and sales teams.

The post Online-To-Offline Attribution Made Simple appeared first on Portent.

Related Posts