Tracking Offline or Phone Sales In Google Analytics
The Problem
There are a lot of circumstances where an online conversion is hard to achieve or where people prefer to pick up the phone and make contact. For example, high value or complex products where the website has little chance of satisfying all of a visitors questions and anxieties about making a purchase. Often some of a websites products sell well online and others only sell offline leading to an inaccurate picture of conversion rate across the product range. In these situations we lose the ability to track against the keyword and source any offline conversions or sales that are made.
Prompt a return to the site after sale
One way of dealing with this is encourage/trick your converted visitor into returning to the website and viewing a conversion page. This can be done by sending them an email and asking them to click a link to confirm their details (or something similar). The page you send them to in the email will be a special offline only thank you page that holds your analytics code and other tracking codes you may want to add such as Adwords tracking. This email can either be a manually created one (for smaller scale websites) or automated by your website software.
How about pulling sale values into the tracking codes?
A more complex use of this method might see you code the URL you send them to with an order ID parameter (i.e. www.mywebsite.com/offline-sales-thanks-page.html?orderid=12345 ). You can then program your web page to pull out of your sales database the required information that you need to populate the relevant ecommerce fields needed to track actual order values etc.
Prevent false repeat conversions
There is a possible problem with this method in that people will often click the link in the email more than one time meaning you capture multiple conversions for one sale. A possible solution to this is to use javascript and cookies to write a simple script that will only run the tracking code the first time the page is viewed.
Try putting the following code in the header.
<script type=”text/javascript”>
var querystring = location.search.substring(1);
var str;
var val;
var ret;
if (querystring.length > 1) {
str=(querystring.indexOf(’leadID=’) + 7);
val=(querystring.substr(str));
querystring = “yes”;
}
function getCookie(name) {
var sPos = document.cookie.indexOf(name + “=”);
var len = sPos + name.length + 1;
if((!sPos) && (name != document.cookie.substring(0, name.length))){
return null;
}
if(sPos == -1){
return null;
}
var ePos = document.cookie.indexOf(’;', len);
if(ePos == -1) ePos = document.cookie.length;
ret = document.cookie.substring(len, ePos);
return unescape(document.cookie.substring(len, ePos));
}
function setCookie(name, value, expires, path, domain, secure){
var today = new Date();
if(expires){
expires = expires * 1000 * 3600 * 24;
}
document.cookie = name+’='+escape(value) +
((expires) ? ‘;expires=’ + new Date(today.getTime() + expires).toGMTString() : ”) +
((path) ? ‘;path=’ + path : ”) +
((domain) ? ‘;domain=’ + domain : ”) +
((secure) ? ‘;secure’ : ”);
}
</script>
And then this code before the final </body> tag.
<script language=”JavaScript” type=”text/javascript”>
if(!val == false){
var c = getCookie(val);
if(!c){
setCookie(val, ‘tracked’, 1000);
var gaJsHost = ((”https:” == document.location.protocol) ? “https://ssl.” : “http://www.”);
document.write(unescape(”%3Cscript src=’” + gaJsHost + “google-analytics.com/ga.js’ type=’text/javascript’%3E%3C/script%3E”));
try {
var pageTracker = _gat._getTracker(”UA-xxxxxx-x”);
pageTracker._trackPageview();
} catch(err) {}
//Enter Anymore javascript tracking codes you have here. You could also add the GA ecommerce tracking here if you can program you site to pull in the correct values.
}
}
</script>
Note I have removed the <script></script> tags from the GA code above as this already sits in a javascript block. For the <noscript> part of the Adwords tracking this can be omited (and not track anything where javascript is turned off) or added seperately after the code above but wouldn’t remove repeat conversions.
With the code above the page you send the customer to must be tagged with ?leadID=(a unique id)
The above method is one of many ways to go about tracking offline sales. While it has it’s flaws it offers great benefits when you have a high proportion of offlne sales.
4 comments4 Comments so far
Leave a reply

Hi Paul,
This is a great article, and very well presented, especially for an often over-complicated topic.
Love the idea of capturing the user’s email address over the phone, then using it to reconcile AdWords and Analytics cookies. Sounds extremely simple and effective, but I’d be interested to know the response rate of emails sent to clicks received.
Alan
Super cool.
This addresses a problem that can be huge, and that is very easy to have go unnoticed.
I’m hestant to add URL parameters, due to duplicate content concerns. Do you have any thoughts on this?
This post is brilliant because it points out a problem that may go unnoticed and because the soltions are so clever.
Hi Alan – Glad you found it interesting.
How many people actually click through from the email to the phone tracking page depends largely on how you go about it and how you word the email. Make it sound super important and clear that they should click through and more people will do it.
In our experience we have found about 50%-70% of customers via this route actually register a conversion.
Of course you need to implement a good way of reconciling the actual phone sales with phone conversions so you can uplift the values you are seeing in analytics accordingly.
Hi SFGreg
I wouldn’t be too concerned about the duplicate content issues because:
a) it’s not a value content page. Do you really care if a ‘thanks page’ gets listed in Google with a parameter on it. WHat would it rank for anyway? It wouldn’t have any internal site links to it – only from the email!
b) People aren’t going to link to this page.
If you are bothered about it then feel free to exclude the page from the google index or use canonical tags. But I can’t see the issue.