The Ultimate Guide to Universal Analytics Integration with SalesForce


Bill Gates once said,

“The most meaningful way to differentiate your company from your competitors, the best way to put distance between you and the crowd is to do an outstanding job with information. How you gather, manage and use information will determine whether you win or lose.”

With the announcement of Wave, SalesForce Analytics Cloud, it’s now more important than ever to measure clients’ 360 journey to connect the dots between business user data (e.g. sales data in SalesForce) and web and mobile behavioral data (e.g. user interactions data in Google Analytics).

In this post, we’re going to show you how to do that!

Our Story

To improve profitability, every company (regardless of size) requires multiple tools to understand their customers and potential customers.

In our organization, we use Google Analytics to improve the effectiveness of our web and mobile presence as well as to track and understand the behavior of our online visitors and how they interact with our digital properties (Website, Mobile App, YouTube Channel, Facebook page, Twitter Profile,…). When our (online) visitors convert to leads, we rely on our CRM platform, SalesForce, to track the history of our prospects’ and customers’ offline and online interactions. We track every single conversation possible – from emails, calls, meetings, and documentations.

While Google Analytics itself gives us the ability to measure the effectiveness of our marketing campaigns in terms of what channels bring visitors to our “front door”, we were missing the link between real live sales conversions and the original (online) lead generation/traffic sources.

Our sales team receives a flood of leads and sales, talking to many prospects and meeting with many customers. We need to link the valuable information they gather with what brought these leads to us in the first place. This missing link led us for many years to inaccurate conversion attribution, bad budget allocation, and incorrect strategic business focus.

Corrective Action

In order to make better-informed decisions on marketing, budget allocation, and strategy, we need to have clear visibility into the sales cycle not only from the point of live contact, but from the possible origin of online inquiry.

To do that, we integrated the two tools that tell us this (SalesForce and Google Analytics) in the following way:

  1. Pass as much relevant Google Analytics visitor behavioral information as possible to SaleForce with every form submission
  2. Pass the final lead status and offline activities from SalesForce back to GA.

Technical Challenge: New integration method with Universal Analytics

Marrying data from different sources is nothing new. But when marriage gets a little stale, sometimes you have to find new ways to spice it up! :) Our legacy solutions were heavily dependent on the Google Analytics _utm cookies that are generated by the classic ga.js tracking code, in which session and campaign information are stored in the tracking cookies.

In the new Universal Google Analytics, all tracking happens at the server-side level and the single _ga cookie generated by the new analytics.js does not contain any session or campaign information.


We adjusted our classic integration method with a solution that works with all GA tracking code versions, including the latest version of Universal Google Analytics tracking code. All needed code was bundled in one JavaScript file called GASalesforce.js

Passing GA data to SalesForce

By following the steps below, you’ll be able to pass users’ campaign and session information into SalesForce every time a form is submitted:

1. Setup SalesForce Custom Fields
Create the following 8 fields in SalesForce:
create custom fields in salesforce

  • Visitor ID: a unique, persistent, and non-personally identifiable ID string representing a user.
  • Medium: The marketing channel. Possible medium include: “organic”, “cpc”, “referral”, and “email”.
  • Source: The referral origin. Possible sources include: “”, “”, and “direct”.
  • Campaign: Name of the marketing campaign.
  • Content: Additional campaign identifier.
  • Term: The words that users searched.
  • Count of Sessions: The number of visits to our site including the current session.
  • Count of Pageviews: The number of browsed pages prior to the form submission.

2. Add Hidden Fields to Forms
Add the 8 variables created in the previous step as hidden input fields to all forms in your website in which you want to track in Salesforce.

3. Setting Visitor ID
Value of the Visitor ID hidden input field can be read from the backend system (This is the same value that we will use later to set a Google Analytics custom dimension).

4. Setting Campaign and Session Information
The values of the hidden fields can be read from the JavaScript file referenced in step 7. The code will generate GA cookies and parse out the campaign variables from the cookies and make them available in the 7 following variables: source, medium, term, content, campaign, visit_count, and pageview_count.

5. Pass values to hidden fields. Logic should be put in place within the form to pass the values of the hidden fields to their corresponding fields within SalesForce when the form is submitted.

6. Download GASalesforce.js
Download it from here to your local environment.
Download GASalesforce.js

7. Cross Domain Tracking
If cross-domain tracking is needed, update GASalesforce.js with a comma-separated list of domains to set up automatic cross-domain link tracking.


8. Reference the GASalesforce.js file.
Placing the following code before the closing tag on every page of the site.

9. Make sense of the data!
Now after we successfully collected all campaign and session data in Salesforce, we can make more sense of it and can extract intelligence.



Passing Salesforce Data to GA

In this section, we’ll utilize a really cool new Google Analytics feature called Data Import to pass customers’ lead information from Salesforce into GA. With Data Import, data can be uploaded from different data sources and combined with the existing Google Analytics data to create one powerful and robust unified report.

The “key” that we’re going to use to marry the two data sets will be the Visitor ID. If Google Analytics finds matching keys, it will join the data in that row of imported data with the existing GA data.



Step One: Create Custom Dimensions
Since “Visitor ID” and “Lead Status” don’t exist as dimensions in Google Analytics, you’ll need to create them as a Custom Dimension.

Custom Dimension Name Scope
Visitor Id User
Lead Status User

You must pass your own visitor ID to Google Analytics as a custom dimension to represent each user who submitted one of your forms in question.

When you have a unique, persistent, and non-personally Visitor ID, set it directly on the tracker as in the following example:

Step Two: Create the Data Set
1. In Admin, go to the account and web property that you want to upload data.
2. Click Data Import under PROPERTY.
3. Click New Data Set.
4. Select “User Data” as the Type.
5. Name the Data Set: “Lead Status”
6. Pick one or more views in which you want to see this data.
7. Define the Schema:
Key: Custom Dimensions > Visitor ID
Imported Data: Custom Dimensions > Lead Status
Overwrite hit data: Yes
Click Save.

Step Three: Export Salesforce data
Export the lead status data from Salesforce into a CSV file.


Step Four: Upload the data
1. In the Data Set table, click “Lead Status”. That will display the schema page.

2. Click Get schema. You’ll see something like the following:

CSV header

This is the header you should use as the first line of your uploaded CSV file. The table below identifies the columns:

Visitor ID Lead Status
ga:dimension1 ga:dimension2

3. Update the exported CSV file to follow the below format. The first (header) row of your spreadsheet should use the internal names (e.g. ga:dimension1 instead of Visitor ID). The columns beneath each header cell should include the corresponding data for each header.

The CSV file should look something like this:

4. In the Manage Uploads table, click Choose Action > Upload files. Choose the CSV file you created.


Step Five: Create Custom Report
Since custom dimensions don’t appear in standard reports, create a Custom Report with our two dimensions (Visitor ID and Lead Status) and your desired metrics.

1. Uploaded data needs to be processed before it can show up in reports. Once processing is complete, it may take up to 24 hours before the imported data will begin to be applied to incoming hit data.
2. Data Import also now supports a new Query Time mode that allows linking data with historical GA data. Query Time mode is currently in whitelist release for Premium users.


And now you can analyze the online user behavior of only those who are marked offline as qualified leads.


Wow, this was a long post! But there you have it – very common uses cases for those of us ready to move their marketing optimization a notch up. I welcome your comments and other use cases our readers come across.

68 thoughts on “The Ultimate Guide to Universal Analytics Integration with SalesForce”

  1. Thanks for posting this. Maybe I am missing something but the included JS file looks like it has its own GA tracking script in it? Isn’t this post about Universal Analytics integration?

  2. Yes, in this post, we assumed you already migrated your tracking code to Universal Analytics. By now all tracking happen at the server-side level and campaign information are not saved in the cookies.

    Since campaign information need to be available in the cookies for such integration, we bundled all required code in the GASalesforce.js. We first fire a legacy GA.js tracker using a dummy account ID. The GA.js tracker will generate all _utm cookies that contain the needed session and campaign information. Then functions are added to:

    extract the “_utma”, “_utmb”, “_utmc” and “_utmz” strings.
    extract the “Count of Sessions” value from the _utma cookie
    extract the “Count of Pageviews” value from the _utmb cookie
    extract campaign information (medium, source, campaign name, term & content) from the _utmz cookie

  3. Also can you clarify regarding the VisitorID? Is that something your script is generating? I don’t see it in there but could have easily overlooked it.

  4. Hi Allaedin,

    Maybe a stupid question:
    If I understand it correctly, should we replace the universal analytics code with your (awesome) snippet above? Or should we combine the two on our landingpages?

    Hope to hear from you!

  5. Hi Mark,

    Please keep your Universal Analytics tracking code as is. The provided snippet was only meant for the UTM cookies creation and for extracting the session and campaign information and making them available to be sent to SalesForce or to your favorite CMS.

    Good luck :)

  6. Thank you! :D
    Will definitely have to have a closer look at this.
    I had been using your previous solution for Classic tracking and it works a treat!

    To my way of thinking the major downfall of Universal Analytics is that ga.js has to be relied upon in order to get this type of information.

    Quick question, if cross domain tracking isn’t required, should any other line(s) be commented out apart from the following:

    var domains = [“”, “”];
    _gaq.push([‘sfga._setAllowLinker’, true]);

    Whole section between
    /******************* Set Up Cross Domain Tracking *******************/
    can be excluded

    Bronwyn :D

  7. This maybe (and probably is) a very silly question, but I’m confused as to where the GAsalesforce.js is to be installed or uploaded? Should I put it in Tag Manager? I didn’t quite grasp the whole “Download to local environment” part.

    Thanks in advance.

  8. Kyle,

    You have two options:

    1. If you are using Google Tag Manager:
    i- Create a “Custom HTML” tag in GTM and call it “GA SalesForce Code”
    ii- Copy the content of gasalesforce.js into the new tag
    iii- Add around the JavaScript code
    iv- Add a Firing Rules (All Pages)
    v- QA and then Publish the tag
    2. If you are NOT using Google Tag Manager:
    i- Upload the gasalesforce.js to your local environment. (i.e.
    ii- Reference the GASalesforce.js file by placing the following code before the closing tag on every page of the site.

    Good luck,

  9. Hello Allaedin,

    Can I do the integration with Universal Analytics and Microsoft Dynamic CRM?

    BR, Hozaifa

  10. Hello Allaedin,

    What is the exact moment where I have to call to the following set command?

    ga(‘set’, ‘dimension1?, ‘vid20140930-005?);

    For example, when the submit button of the form is clicked?

    Thank you in advance

  11. Aitor,

    Since the dimension in question is User scoped and since the value is manufactured explicitly by the web developer for the site, it can be set at any time after the creation of the Visitor ID itself.

    Ideally, it would be set immediately after creation of the ID for that particular visitor.

    Remember that Custom Dimensions, once set, are actually sent to GA along with the next pageview or event hit that is sent to GA. So it should be contrived such that it is set just before another hit is actually sent.

    Good luck,

  12. Two questions

    Is this not a short term solution to a big issue that is coming down the line as do google not remove the classic GA in two years time

    also how do i generate a dynamic user id can you recommend a post please

  13. Hi Will,

    > Is this not a short term solution to a big issue that is coming down the line as do google not remove the classic GA in two years time
    One long term solution is keep a local version of the urchin.js file or the ga.js file and use it when Google sunsets the legacy ga.js code. Also, you can code this and create your own cookies of the campaign data that you wish to pass to SalesForce or to any 3rd part systems.

    >how do i generate a dynamic user id can you recommend a post please
    Ideally this value should come from your backend system to ensure its uniqueness, but you always can use the visit’s time-stamp combined with other values (i.e. yyyymmdd-hhmm-xyz 20151219-1536-007)

  14. This is fantastic and clear documentation of what to do with the loss of direct access to the _utm cookies, specifically _utmz, after moving to analytics.js. Do you have any concern with ga.js no longer being hosted? How about a JS to parse the UTM values into a different cookie and pulling it out for these kinds of uses? Since I am sure most of your clients are using GTM now. Can you revise this document to show how to implement via Google Tag Manager?

  15. Django,

    >Do you have any concern with ga.js no longer being hosted?
    Honestly, I don’t! Every concerned company should keep a local version of the file to be used later when Google decides to sunset the legacy code.

    > How about a JS to parse the UTM values into a different cookie and pulling it out for these kinds of uses?
    Yes, possible.

    > Can you revise this document to show how to implement via Google Tag Manager?
    Probably, the only item that you need to use GTM for is step #8, which is including the reference to the JS file.

    In the case of GTM, you will need to:
    1. create a “Custom HTML Tag”.
    2. Copy and paste the Javascript code provided in step # 6 [GASalesforce.js] into the textbox. Be sure to enclose Javascript snippets inside HTML script tags.
    3. Apply a firing rule = “All Pages” to the tag in question.

  16. Hi again,

    so 5 months gone by and I’m just now seeing you responded to my question – thank you! Still stuck, however. I’m using GTM , but it’s unclear to me what should be omitted from GASalesforce.js when I copy it over to the custom HTML tag. Everything else is set up and ready to go!

  17. Allaedin.

    Great post! I’m looking at doing this sort of integration – however there are a couple of points I’d like to clarify. As background, I’m using free UA, with UserID implemented.

    It looks to me as if the data being passed from GA -> Salesforce would only able to be last-click attribution campaign data. Is this right?

    Given that one of the drivers for this integration is being able to apply non-standard attribution models to Salesforce data, is there scope for doing this in GA having passed the relevant sales data from Salesforce -> GA on conversion by setting a goal that identified this, or are there limitations when using the free version of GA?

  18. Hello! Does this integration bring in the visitor’s IP address, or any other location data? I’d like to assign the lead to the right territory manager. Thanks!

  19. Hello again, do we need to activate User-ID (Admin > Property > User-ID) in google analytics in order to enable this integration?

  20. Great post Allaedin! Thanks for doing it. Question for you: Will this implementation work for a use case in which there’s a new data point that gets manually assigned to an existing visitor record using Salesforce after the original Google Analytics information is sent? For example, a situation in which a visitor applies to participate in a auction and his/her application is rated subsequently for their likelihood of submitting a bid. In a case like this, it would be helpful to import this manually assigned rating along with the rest of the visitor record back into Google Analytics to assess from which sources the highest-value visitors arrived on the application page. Any insight you can provide would be much appreciated!

  21. Hi,

    I’m interested in how the cross domain tracking works using this code. It says “cross domain” link tracking in the instructions – does this imply that the .js file has code to automatically update any site link URLs that link to the root domains listed as domain variables in step 7?

    If not, I’d be interested to learn how this code actually implements cross domain tracking.



  22. Thanks so much for posting this. I am having an issue implementing it; how is the data from the attached gasalesforce.js file being tied to the hidden input fields? Do I need to add

    document.getElementById(“txt_medium”).value =medium; etc. to the .js file?

  23. This isn’t working for me. I’m not sure how to assign the variable to the form… is it something like “document.getElementById…”?

  24. Hi, thanks for this great article.

    “2. Data Import also now supports a new Query Time mode that allows linking data with historical GA data. Query Time mode is currently in whitelist release for Premium users.”

    Does this mean that if I set hit scoped Custom Dimension and want to use it as a key to import values of other hit scoped Custom Dimension to Google Analytics it won’t work in non-Premium?

    For example, if I want to import transaction status (hit scoped Custom Dimension 2) by transaction ID (hit scoped Custom Dimension 1).

  25. Great script. You could be more professional though, and host it in a repository and more importantly with an explicit license.

  26. Hi,
    Great article.

    How did you match visitor IDs (coming from analitics) with user names and surnames in SFDC? Analitics do not provide user name and surname info?


  27. How do I know if I need cross domain tracking? I am just using one domain (and of course salesforce) so I assume this is not needed?

    Also still not working, I have added the Source, Medium, Ca,paign to the form as hidden fields, added the javascript ‘Salesforce Code’ to every page via Tag manager and created the fields in Salesforce but nothing is happening.

    Am I missing something?


  28. Hi Allaedin! Thank you for the post. We’ve been working on this implementation for a few days and we’re a little stuck… the form is successfully referencing the gasalesforce.js file and we edited that file to reference our domain name, but it’s not parsing any of the variables. I’m a little confused about the Visitor ID step (labelled as step 3 above) and I haven’t done anything for that step… I’m wondering if this is causing the issue. Can you give more specific instructions for what needs to be done to set the visitor ID?
    Thank you!

  29. Thanks for writing this post.

    I am not getting from where to start? I am totally new to google analytics.

    If I am providing domain ( then how the records are inserted in my salesforce org. Do I have to give username and password in the script?

    Please help

  30. Hi Allison,

    Great post!

    Would it be possible to store which pages the users have been looking at in Salesforce? It could be great for segmenting users in Salesforce. What about other parameters in GA like convertion rate is it possible to export these from GA to Salesforce also?

  31. Same question as Christopher – is it possible to “record” and export both first interaction and last interaction utm parameters? Thanks!

  32. Hi Allaedin. Thanks very much for the post.

    I understand the Visitor ID is set by the backend system. But I still find this part quite confusing. Would you be able to provide an example of exactly how you generate your vid string?

  33. so i created the hidden fields added to the landing page including the js etc
    but nothing coming into salesfore, all the fields still empty after run serveral tests still got nothing
    i there something i still missed?

  34. how to make this work with eloqua?
    i have a form not submit directly to salesfoce
    it would submit to eloqua first before sync to salesforce

  35. Hi! Thank you for this article!
    But wgat about Measurement Protocol? Is it possible to import data to GA from SF using MP?
    And am I right that we can add also a hidden field GCLID to get information about adwords campaign or there is no need?

  36. Hi,
    Can you elaborate on the effect of adding cross-domain tracking to this JS? I assume both domains would need to run this JS, in my case using GTM.
    We are already auto-linking via the UA tags with valid GA accounts. If ‘’ is connecting to ‘’ do I still need to setup the cross-domain tracking here as well?

  37. Could you use this method to pull custom UTM tags from the URL into salesforce fields.

    For example, if I was to dynamically populate name, email and contact number into the UTM tags (through Google URL Builder), would this be a suitable method of then autofilling this data into the form (visible or otherwise)?

  38. I can’t seem to get your JavaScript code to generate the cookie values required to post to Salesforce even though I’ve added your code as well as made sure that the Universal Analytics code has been implemented.

    When I look at the code of my page, I can see that the the Universal Analytics has generated some values as cookies, but nothing that you suggest appears.

    Would be interested in seeing how to get this to work.

  39. Do you (or anyone who has visited this page) have a working example? I’m still having difficulty extracting any of the values that are supposed to be generated by the script.

  40. I got it to work! For those of you that haven’t been able to use it successfully, I got it work after discovering the following:

    Typically you transfer values with JavaScript to form fields using document.getElementById(“field”).value= “something”. However, this doesn’t work with hidden fields unless you use a trigger of some sort. While obviously not foolproof, I used an onBlur event with a visible form field to populate the hidden fields.

    Secondly, I discovered that my syntax had a slight error:

    document.getElementById(“field”).value = medium; fails

    document.getElementById(“field”).value=medium; works

    Hope this helps anyone looking at this nifty solution!

  41. Dear Mike,

    I am sratching my head on implementing this.

    It will be really great if you can kindly share some kind of step by step screen shots on implementing this.


Leave a Reply

Your email address will not be published. Required fields are marked *


You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">