by Rob Newhouse
Analytics & Measurement Consultant
7 February 2017
Salesforce is one of the most popular customer relationship management systems (CRM) around and right now thousands of businesses rely on it to put exact figures on their marketing return on investment (ROI). To achieve the full picture of ROI on marketing, it can be as simple as tracking submissions on a PPC-only or email-only landing page, but what about web leads that come from multiple channels and are all forced through the same set of contact forms?
Integrating your marketing analytics with your CRM is a popular topic and many assume it’s as straight-forward as downloading a plugin and popping in your account number. However, this is not the case. It was much easier with Classic analytics, using the values available in the _utmz tracking cookie. However, since the release of Universal Analytics, and the use of the less accessible _ga cookie, the disconnect between marketing attribution data and the Salesforce system seems to have become greater, but it still follows the basic steps:
There is no native Analytics integration for Salesforce, despite hordes of forum users requesting it for the last six or seven years. After searching for integration methods, we have found that most resources were only capable of last-click attribution (not good enough for us!), and none have been updated for Universal Analytics.
The method below is based on the Professional edition of Salesforce and we’re using Contact Form 7 as this is an extremely popular plugin.
To see Universal Analytics data in your Salesforce leads, follow these steps:
Create the following fields in your lead records in Salesforce:
Our Salesforce consultant helped us set this up so that the fields appear under ‘Google Analytics’ for each lead: this helps us to break all leads down by the same source/medium as we would do in Analytics. You can do this for any fields you require to be sent to the CRM along with the lead. We’ve included the content and term here.
Salesforce uses a series of ID numbers to map incoming values onto these fields so your code and forms need to reference these IDs when they are submitted.
The quickest way to access all the IDs is to use Salesforce’s web-to-lead generator which will contain the necessary IDs to send the form values to Salesforce – make sure you include your GA fields as you’ll need all of these for the next steps.
Install the following code on every page of your website (at least every page where there’s a form). The code we used here is based on the getSetReff code provided by innertrends on github, which emulates the values Universal Analytics uses and makes them available for us to use. It’s optimised for Tag Manager, so this is what we’re firing on every page (you’ll have to wrap it in a script tag to get it to work in GTM):
function getSetReff() {
if (!Array.prototype.filter) //Array.filter() isn't included in IE until version 9.
{
Array.prototype.filter = function (fun /*, thisArg */ ) {
"use strict";
if (this === void 0 || this === null)
throw new TypeError();
var t = Object(this);
var len = t.length >>> 0;
if (typeof fun !== "function")
throw new TypeError();
var res = [];
var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
for (var i = 0; i < len; i++) {
if (i in t) {
var val = t[i];
// NOTE: Technically this should Object.defineProperty at
// the next index, as push can be affected by
// properties on Object.prototype and Array.prototype.
// But that method's new, and collisions should be
// rare, so use the more-compatible alternative.
if (fun.call(thisArg, val, i, t))
res.push(val);
}
}
return res;
};
}
var _reff = [];
_reff = dataLayer.filter(function (value) {
if (value.setDomain) return value;
});
if (_reff.length === 0) _reff[0] = {
'setDomain': document.location.hostname
};
function rC(k) {
return (document.cookie.match('(^|; )' + k + '=([^;]*)') || 0)[2]
}
function sC(n, v, d) {
dd = new Date();
dd.setTime(dd.getTime() + (d * 24 * 60 * 60 * 1000));
e = typeof d != "undefined" ? ";expires=" + dd.toGMTString() : "";
document.cookie = n + "=" + v + e + ";domain=" + _reff[0].setDomain + ";path=/";
}
function gcP(p) {
if (document.location.search.indexOf(p) != -1) {
return ("" + document.location.search.split(p + "=")[1]).split("&")[0];
} else {
return "not-set";
}
}
//every pageview
var __asc = (typeof rC("__sreff") != "undefined" ? rC("__sreff") : "");
var __apc = (typeof rC("__reff") != "undefined" ? rC("__reff") : "");
var __tsc = t__apc = [];
var __rf = __tpc = res__apc = __gsr = __nwss = "";
var __cmp = "utm_campaign";
var __mdm = "utm_medium";
var __srcs = "utm_source";
var __flag = 0;
//referrer or params?
if (document.location.search.indexOf(__cmp) != -1 || document.location.search.indexOf(__mdm) != -1 || document.location.search.indexOf(__srcs) != -1) {
__gsr = "//campaign::c:[" + gcP(__cmp) + "]m:[" + gcP(__mdm) + "]s:[" + gcP(__srcs) + "]";
} else {
__gsr = document.referrer;
flag = 1;
}
//console.log(__gsr);
//get referrer domain & verify adwords
__gsr = ((document.location.search.indexOf("gclid") != -1) ? "//campaign::[adwords]" : __gsr);
__gsr = ((typeof __gsr == "undefined" || __gsr == "" || __gsr.indexOf(_reff[0].setDomain) != -1) ? "(direct)" : __gsr.split('/')[2]);
if (__asc) {
__tsc = __asc.split(".");
__tsc[1] = new Date().getTime();
__tsc[2]++;
__asc = __tsc.join(".");
sC("__sreff", __asc);
} else {
__tsc[0] = __tsc[1] = new Date().getTime(); //start time = current time
__tsc[2] = 1; //first pageview
__asc = __tsc.join(".");
__nwss = 1;
sC("__sreff", __asc);
}
//if new session
if (__nwss == 1) {
res__apc = (__apc != "" ? __apc + "|" : "");
sC("__reff", res__apc + __gsr + "&" + __asc, 730);
} else {
t__apc = __apc.split("|");
__tpc = t__apc[t__apc.length - 1];
__tpc = __tpc.split("&")[0] != "" ? __tpc.split("&")[0] : __gsr;
res__apc = (t__apc.length == 1 ? "" : (t__apc.slice(0, -1).join("|") + "|"));
if (__gsr == "(direct)" || __gsr.indexOf(__tpc.split("&")[0]) != -1) {
sC("__reff", res__apc + __tpc + "&" + __asc, 730);
} else {
sC("__reff", __apc + "|" + __gsr + "&" + __asc, 730);
}
}
document.getElementById("ID FOR MEDIUM").value = gcP(__mdm); /* Campaign_Medium */
document.getElementById("ID FOR CAMPAIGN FIELD").value = gcP(__cmp); /* Campaign_CampaignName */
if (__gsr == "(direct)") {
document.getElementById("ID FOR SOURCE FIELD").value = __gsr; /* Campaign_Source */
} else if (__gsr == "" || gcP(__srcs) == "not-set") {
document.getElementById("ID FOR SOURCE FIELD").value = document.referrer; /* Campaign_Source */
} else {
document.getElementById("ID FOR SOURCE FIELD").value = gcP(__srcs); /* Campaign_Source */
}
return rC("__reff");
}
getSetReff();
The final section of the tracking code is what populates the hidden fields: you’ll need to customise to match your field IDs that you exported in step 2, for example:
document.getElementById(“ID FOR MEDIUM“).value = gcP(__mdm); /* Campaign_Medium */
This code can be modified to identify any of the values in the _ga cookie. We’re most interested in source, medium and campaign, but you could do the same thing for term and content for PPC traffic.
Step 1, 2 and 3 are the pre-requisites to accessing and reporting on the data – now we’ve got to bridge the gap between the data we’ve captured on your website and the final destination in the CRM. We do this by injecting the values into hidden fields and pushing them to Salesforce via the form.
First, create hidden fields that are able to contain the GA values. You’ll need to use the IDs you’ve exported in step 2 and attached them to the HTML of your forms, it should look something like this:
We’re nearly done! Now all you have to do is push the values to Salesforce using a PHP function. Remember to read carefully and input your own Organization ID, etc. to get it to work for you.
$submission = WPCF7_Submission::get_instance();
$data = $submission->get_posted_data();
$first_name = $data['your-firstname'];
$last_name = $data['your-lastname'];
$company = $data['company'].$data['_post_url'];
$email = $data['your-email'];
$phone = $data['phone'];
$website = $data['your-website'];
$seobudget = $data['seobudget'];
$ppcbudget = $data['ppcbudget'];
$memberStatus = $data['memberStatus'];
$serviceInterests = $data['serviceInterest'];
$GaMedium = $data['N0Y00000ABxTe'];
$GaSource = $data['N0Y00000ABxTj'];
$GaCampaign = $data['N0Y00000ABxTo'];
$GaContent= $data['N0Y00000ABxTk'];
$GaTerm = $data['N0Y00000ABxU3'];
$post_items[] = 'oid={YOUR_ORGANIZATION_ID}; // Replace this by your OID value
$post_items[] = 'first_name=' . $first_name;
$post_items[] = 'last_name=' . $last_name;
$post_items[] = 'email=' . $email;
$post_items[] = 'company=' . $company;
$post_items[] = 'URL=' . $website;
$post_items[] = 'phone=' . $phone;
$post_items[] = 'Campaign_ID=' . $campaignID;
$post_items[] = 'member_status=' . $memberStatus;
$post_items[] = 'lead_source=' . $leadSource;
$post_items[] = '00N0Y00000ABxTe=' . $GaMedium;
if(!empty($first_name) && !empty($last_name) && !empty($email)) // Replace _WOCF7 ID with form that you want to use. Remove it completely for all forms
{
$post_string = implode ('&', $post_items);
// Create a new cURL resource
$ch = curl_init();
if (curl_error($ch) != "")
{
// error handling
file_put_contents('cf7data.txt', 'Curl Error: ' . curl_error($ch));
}
$con_url = 'https://www.salesforce.com/servlet/servlet.WebToLead?encoding=UTF-8';
curl_setopt($ch, CURLOPT_URL, $con_url);
// Set the method to POST
curl_setopt($ch, CURLOPT_POST, 1);
// Pass POST data
curl_setopt( $ch, CURLOPT_POSTFIELDS, $post_string);
curl_exec($ch); // Post to Salesforce
curl_close($ch); // close cURL resource
}
}
Now, when a form is submitted, the hidden fields will populate the relevant fields in the lead record in Salesforce. And we’re done!
Get our news, insights & advice delivered to your inbox
Five fresh insights to boost your nursery marketing
We asked 421 UK parents about their nursery search and discovered five fresh insights to boost your nursery marketing.
England fall short, but betting searches score big at Euro 2024
Dive into our latest Summer of Sports blog, where we unpack the key insights from a summer that captivated the nation. As Euro 2024 concludes, we explore how England's run to the final fuelled a surge in online betting and what this means for brands looking to capitalise on future international tournaments. Discover actionable strategies to leverage these trends and boost your market share in the ever-growing world of sports betting.
ChatGPT key content tells – How marketers know when you’re using AI
AI can streamline content creation, but it often leaves tell-tale signs like overuse of colons, repetitive language, and American spellings. Check out our checklist of things to look out for to master how to use AI when creating content.
Call us on 01525 715 520 or complete the form below, and one of the team will get back to you.