Tracking Offline Transactions with Universal Analytics



“We don’t do ecommerce, we just have a lead generation form.”

Google Analytics last fall shot some video talking about Universal Analytics that featured Dan Wilkerson and myself here at LunaMetrics. At one part of the video I talk briefly about Georges Seurat’s painting ‘Sunday Afternoon on the Island of La Grande Jatte’.

I’m gonna be honest, the inspiration for that analogy was from Ferris Bueller’s Day Off. At one point the characters go to the Art Institute of Chicago, and one character in particular, Cameron, stares at the painting as it steps further and further into the painting. If for some reason you’re culturally illiterate, here’s what I’m talking about:

My point was sort of the reverse. The picture of the little girl above, focused in, is a small part of the story, but in the past, that was all we had to go on. As analytics have proceeded over the years we’ve got bigger and bigger pictures as we step further back from the painting.


The picture of a girl becomes a girl and her mother walking amongst a wide variety of people, and is that water over there?


The more we see, the bigger a story we can tell.

So how does this relate to websites?

Universal Analytics Goes Offline

The majority of commercial websites out there don’t actually process a transaction on your visit to their website. Sometimes it’s a lead generation website, where the primary goal is to get someone to submit a contact form, and then later, maybe days, weeks, or even months, a transaction occurs somewhere else. It’s easy to tie your attribution to the form submission, but much more difficult to tie it to hard revenue numbers.

Marketers and third party tools have approached this in several different ways in the past. One common thing to do is to feed attribution information into the form submission, and then carry that along to the final transaction. This has the benefit of being able to assign some revenue numbers to specific campaigns, but loses the depth of that visitors experience. Let me give an example.

Here’s what most systems might show you when considering attribution:

Branded Campaign Visit => $100

Here’s what actually happened:

A visitor does an organic search on Google for “Widgets”.  He finds your website, and reads several of the great blog articles your team has written.  He clicks on your Facebook page link, and follows you on Facebook.  A week later he sees one of your promoted posts on Facebook, and clicks the link, changing his referral to being from your social media campaign. When he arrives he is given variation b of your new content experiment. He likes the new look and it’s encouraged him to convert, but he has to go do something ,and puts it off. The next day he does a branded search for your company, and sees one of your branded AdWords campaigns, clicks on that, again changing his referral information. He sees and clicks on a specific image banner on the home page to get to the form submission page, where he finally submits his information. Two weeks later he actually processes a transaction offline with you for your Widgets for $100.

What was lost?

Multi-channel attribution is non-existent. Our visitor might be better described as:

Organic (Not Provided) =>

Social Media Campaign (Facebook) =>

Branded Campaign =>


But did that content experiment sway his conversion? What was the value of that? What about the banner he clicked on? Shouldn’t it be also:

Organic (Not Provided) / Content A / Did Not View Banner =>

Social Media Campaign (Facebook) / Content B / Did Not View Banner =>

Branded Campaign / Content B / Did Not View Banner =>


How are you supposed to accurately judge all your campaigns if all you’re doing is Last Non-Direct Click Attribution? How are you supposed to accurately judge your content experiments if all you are measuring are form submissions, rather than the revenue generated which can be two wildly different metrics?

The answer is to use the Universal Analytics Measurement Protocol and track your users’ eventual conversions offline, tying the revenue to their visits.

How To Track Offline Conversions In Let’s Say 5 Easy Steps

Step 1: Get Universal

The Measurement Protocol requires Universal Analytics so if you’re still using Google Analytics Classic, or Traditional Google Analytics, you’ll need  to upgrade. Check out Alex’s post on upgrading here if you need to do that

Step 2: Set Up Custom Dimensions

You’ll need to go into the Google Analytics interface and set up at least one, if not two custom dimensions for your property. UID and CID.

UID will be our hold for a User Id. The full User ID functionality for Universal Analytics is coming soon hopefully, so you might as well get this rigged up and ready to go. It’s not absolutely required in this case, however our examples will be using it.

CID is the Client ID. This is the number that Google Analytics uses to identify a particular user/device/browser instance. On the web it’s normally stored in a first party cookie, or for a mobile app it’s generated randomly on the install. This one is key to having this whole thing work.

Step 3:

Once we have our Custom Dimensions defined, it’s time to go onto our website and actually grab the data. For the UID this can be anything. I often will use a uniqid() php function to generate a unique id, but you can do it however you like. Just keep in mind it can’t be personally identifiable information. So no emails or social security numbers please. Create this UID on first page load, store it in a cookie and in your session, so that you can pass the UID into GA as a Visitor level custom Dimension:

ga(‘create’, ‘UA-XXXXX-X, ‘’);
ga(‘set’, ‘dimension1’, ‘PUT THE UNIQUE ID HERE’ );
ga(‘send’, ‘pageview’);

The CID is a little more complicated. We need to grab that from the tracker or the cookie. This JavaScript works nicely.

ga(function(tracker) {
clientId = tracker.get(‘clientId’);

This will only pull the cid value for the visitor AFTER the page has been tracked and Universal Analytics exists on the page, so you should put it after your UA tracking code. You can easily put its value into a hidden input field in a form this way and pass it into your back end system for storage with the user information:

ga(function(tracker) {
clientId = tracker.get(‘clientId’);
document.forms[0].cid.value = clientId
<input type=”hidden” id=”cid” name=”cid”>

Step 4:

So now, hopefully, in your system you’ve collected the cid and pass it along with the user id and other information about the user that your marketing software might care about.

Eventually some of these users will complete transactions, and when that happens you’ll make a measurement protocol hit. You can automate it in your systems, or you could do it manually if you don’t have a tremendous number of transactions. (But automating it would be probably better). I’ll leave it up to you how you want to automate it into your system.

For a transaction you’d make at least two http requests. One for the transaction, and another for the actual item. If you have multiple items, you’d have multiple item hits. They’d look something like this:

Here’s how those break down: 

Transaction Hit: 

v=1  //v always equals 1 for now.

&tid=UA-XXXXXX-X  //insert the correct property id here

&cid=YYYYYYYYYYY//the cid you captured from the user on form completion goes where Y goes

&t=transaction  //it’s a transaction

&ti=ZZZZZZZZZZZZ   //this is a transaction id we generated dynamically. As long as this is unique, you can even create this at the time this measurement hit is generated. If you have specific transactions id’s in your system you could pass them here, or set it to be a random id like uniqid() above. Something like: 52ea5aab1f0c2

&tr=1100 //the purchase value of the transaction

&cd1=23bc5c58a4a4b //this is the custom dimension for slot 1, with our userid

Item Hit:

v=1 //always 1 again

&tid=UA-XXXXXXX-X //again modify for your property id

&cid=YYYYYYYYYYY //same cid as the transaction, and the initial user

&t=item //it’s an item hit

&ti=ZZZZZZZZZZZZ //the same transaction id as passed in the transaction hit

&in=Widget //the product name

&ip=1100 //product price

&iq=1 //product quantity

&ic=IF5739 //sku, whatever yours is. If you don’t have a sku you could make one, or you could use this area for additional product information. Just remember that the SKU needs to be unique per transaction. If you send the same SKU for multiple items in a transaction, only the last one will get recorded. So if you use it for concatenating something like product color etc, just be sure that it remains unique as well. If you want to use it for more generic product category stuff that is used for multiple products, you can concatenate on some sort of unique hash at the end which you can strip off later in reports.

&cd1=23bc5c58a4a4b //and the user id again for the custom dimension

With pretend numbers in place these hits might look like this: 509493873&t=item&ti=52ea5aab1f0c2&in=Widget&ip=1100&iq=1&ic=IF5739&cd1=52ea5a8bc6a4a

You can also send a virtual page hit, but it’s not necessary. I’ve done it both ways, and I’ve yet to determine which way I like better. We tested these by sending a page hit for some transactions , and not for others. The page hit we sent on half the later transactions were sent prior to the transaction and item hit:

v=1 //always 1

&tid=UA-XXXXXX-X //again the property id

&cid=YYYYYYYYYYYYYYYYY // again the cid of the initial user

&t=pageview // this one is a virtual pageview

&dp=/offline/conversion //this is the page

&dt=offlineconversion //this is the title

&cd1=23bc5c58a4a4b //the userid again for the custom dimension

This does not appear necessary, but I am mentioning it so the results make sense.

Results in the Reports

Here’s how it looks like in the standard reports. After some initial visits and form submissions, the data looks like the following screenshots. Visits, goal completions, but not page value, no transaction information, no revenue.

Acquisition - all traffic - ecommerce - before

Traffic reports generated show visits but no revenue or conversions…

Acquisition - all traffic - goal 2 - before

We see goal completions for forms though. 25% conversion rate on the inquiry form! Not bad. I guess those are the good source/mediums….

Conversions - ecommerce - overview - before

No ecommerce of course… At least until the next day when we sent the measurement protocol hits.

Acquisition - all traffic - ecommerce - after

Now not only do we see the visits, and their form completions, but we see who actually eventually converted, and for how much. We had a 40% conversion rate from bing/referral but not a single transaction from those guys. though is looking pretty good, particularly for average order value…

Conversions - ecommerce - overview - after

And now our ecommerce report is full of lovely yeast and beef extract products for our fake Marmite store…


If you process revenue in some way offline, and haven’t tied it back into your Google Analytics data yet, what’s stopping you? With Universal Analytics it’s easy to pull back from the painting and view a bigger picture than just the little girl with the white hat. Get better insights into your site today by using offline conversions and the measurement protocol.

Sayf is a former LunaMetrician and contributor to our blog.

  • James

    So if I understand correctly:

    Assign USER ID to random visitor, they fill out form with their name attached. You save this to your systems.

    Guy walks in offline store and buys the widget, you get his name and add it to the system.

    You (or automate) match that offline name, to the name recieved from the form which has a USER ID attached.

    Then send that mapping to GA to assign that conversion to the original source.


  • Pawel


    great article – thanks for sharing. I just wanted to clarify one thing — CID contains visitor level identifier, right? If so then if a user visits our website once from google organic on january 31st and submits a form, we will have reported: 1 visit (google / organic), 1 goal conversion (100% CR), 0 ecommerce transactions (0% ecommerce CR). Lets assume now, that then this user purchases a product on February 2nd and we send transaction hits to Google Analytics. Then if we report data for February 2nd we will have 1 visit (google / organic), 0 goal conversions (0% CR), 1 ecommerce transaction (100% ecommerce CR). The data for the full range (January 31st-February 2nd) will look like this: 2 visits (google / organic), 1 goal conversion (50% CR), 1 ecommerce transaction (50% ecommerce CR). Am I right?

  • Sayf Sharif

    James, that’s correct, you could do that. As long as you can identify them on the site, and pass their CID and/or User ID to your system, and then can later identify them on your POS in the real world brick and mortar store, you can match that revenue in GA to that user.

  • Sayf Sharif

    Pawel, If I understand you correctly then yes that’s how it should appear.

  • Hi Sayf,

    Thanks very much for this, it really helped me understand how Universal Analytics can now be used to track the entire customer journey.


  • Maggie

    Thanks for this great article, Sayf. I have one question: if UA is in Google Tag Manager, how can I make sure the CID is pulled after the page is tracked?

  • How are you able to match an offline visitor and sale to a specific, anonymous website visit?

    If we had a way to collect personal info, and all online visitors provided their personal info before making an offline purchase, I can see how you could match transactions to unique visitors, but GA prohibits the collection of personal info and only a small percentage of people ever submit their personal info normally.

    So how can we match an offline transaction to an online GA UID or CID, assuming the above limitations are true?

    How were you able to match your transactions to the UID/CID in your example?

    And finally, how were you able to use the measurement protocol to send the correct, required transaction data and ensure that it was properly attributed to the correct online user profiles in the correct GA Property? Meaning what app(s), script(s) or platform(s) were actually used to send the right transaction data to the right place in GA?

    One more question actually, if the cost data upload occurs later than the actual transactions took place, is it possible to define the correct time and date of the transaction in GA?


  • Sayf Sharif

    We can assign a User ID to anyone, the hard part is tying it to other devices for instance. For that we’d need to have some sort of identifying login. However the CID is the id of the cookie, and that is something that identifies the visit in GA. As I showed above, we can take the CID from an otherwise anonymous visit, and pass that with a form submission. Then we can associate all offline transactions with that CID.

    The subject of personally identifiable information (PII) within Google Analytics is an ongoing one, but the key part is “identifiable to Google”. A hashed value, or just an ID number that you associate in your database, are completely allowed. So we keep their otherwise personal information offline in our own database, but we can still use and assign a userid or use the cid.

    So to answer the third question and reiterate, we can capture the CID from a user, and then alter use that CID to pass the transaction. The system matches the transaction automatically via the CID.

    As far as sending the correct transaction data, that’s really up to you to create your measurement protocol hit with the correct revenue information, etc, but as far as the property, you’ll notice that one of the parameters of the hit is the property ID. You can use various means to send this data, it could be done automatically within an offline system, in a Google Doc, built manually by hand, it just needs to make that http request to Google, from wherever it makes it.

    the transaction comes in as when the hit takes place. You can’t redefine that unfortunately. The best you can do is automate the system so that the offline transaction hit occurs at the same time, or roughly the same time, as the offline transaction itself.

  • Sayf Sharif


    Well, to not require luck, you’d have to force tag order. There are a variety of ways to do this. It’s a little easier if you’re using a custom html tag for your google analytics, rather than the inbuilt tag. You can just add a datalayer.push event to the end of that code and then have another tag that fires on that new event, which grabs the CID code, and pushes it also into the datalayer, and then you’d grab the CID as a macro value and can use that after that based on an additional chained event, etc.

    chaining events like that in tag manager really is it’s own blog post I think.

  • Great post Sayf,

    I will try and use this strategy for a client who is using Zoho for tracking. Do you know of any successful implementations of offline sales conversions with Zoho?


  • Sayf Sharif

    I do not believe I know anyone using Zoho in this way. Good luck!

  • Mark H


    I am about to do that. Via auto-tagging, I will pass GCLID into landing pages and form submits will go into Zoho and carry on the GCLID. Using offline conversions, I will attach the actual conversion to the GCLID giving me a full picture. But the next thing…


    So, I’m guessing this is not for Adwords, and so is a full holistic coverage across all web properties. Right?

    Basically, what you’ve outlined functions like gclid but independent of Adwords.

    If your answer is yes, is there a way without needing to code to generate the unique IDs and be able to do all this by just using tag manager?


  • Sayf Sharif


    So we’re not really generating Unique ID’s so much as grabbing the ID of the user’s cookie itself in this case. It’s unique, we’re just not generating it, GA is.

    The scripts above could be used in GTM as a custom javascript macro to grab it, and do something with it in GTM. The key is to make sure you have that CID of that user, not the GCLID. The CID identifies their device/browser cookie, and will let you reference them again in the future.

    However you’d need the code at least in GTM to grab the CID, and then you’d need to do something with it to capture it in some way, so you could reference their offline behavior later.

  • Joe


    Sorry if I have missed this but what scope are we setting on the custom dimensions?

    ALso is the user ID supposed to be session based? I Just wondered how this equates if the user starts using different browsers during the process.



  • Sayf Sharif

    Scope should be User level.

    If you’re using the new User ID feature, and your user is logging in, then you can use that, and track the pattern across browsers.

  • Sofia Agboatwalla

    Hi Sayf,
    I am using the Measurement Protocol to pass the client id along with events. I am able to view the events when I log in to Google Analytics. Where can I see any data based on Client Ids? I have created a custom dimension called CID as per the article above:
    ‘You’ll need to go into the Google Analytics interface and set up at least one, if not two custom dimensions for your property. UID and CID.’
    I have also set up a custom report with Metric Group: Event/Session With Events and Dimension Drilldown->Custom Dimensions->CID but am unable to view any data based on CID. Please advise.

  • Sayf Sharif


    Are you passing that CID as a custom dimension value as well? Sending the CID with the hit, will record it as that CID in GA, but it won’t automatically pass into a custom dimension named CID. You’d need to also pass it as a custom dimension value (like cd1 in the measurement protocol hit) for it to be seen in GA within that dimension.

    If you ARE passing it as a dimension, and the dimension is set up correctly within GA, then I am not sure, you might have some sort of syntax error in your hit.

  • Mark H

    Thanks Sayf! That clarifies the part about not needing to generate. Would this apply to cross-domain tracking as well?

  • Sayf Sharif

    It should, you just need to send the right information with the measurement protocol. When you send an offline hit, there’s no cookie to base it off of, so it’s sending the hit to GA, which then based on the hit determines the visit, etc.

    The problem with cross domain tracking stems from having multiple cookies, so the lack of a cookie in this case generally will solve the problem.

    Imagine if you had 2 website domains, and an offline hit.

    User hits and gets a CID of 123
    User hits and gets a CID of 456 and then submits a form.
    That form submits the CID (456) which later is used by:
    Another Server sends an offline hit with CID 456

    So in that case you’d have 2 users.

    If you do cross domain on and what happens is this:

    User hits and gets CID 123
    User hits which is linked by through cross domain tracking and is ALSO assigned CID 123.
    User submits form with CID 123 attached.
    Server sends measurement protocol hit with CID 123

    One user, across 2 domains, and an offline hit.

    Hope that helps.

  • Chris

    Hi Sayf,

    Brilliant article, thanks.

    Would I need to remove my standard e-commerce tracking code for this to work?

    I’m looking to implement this on a site where payments are taken off-site, so e-commerce tracking is sketchy at best!

    Thanks, Chris

  • Sayf Sharif


    It works independently, so if you want to replace sketchy online tracking, with more accurate offline tracking, then yes I”d remove the online stuff if it’s not accurate, and replace it with more accurate offline measurement.

  • Hi Sayf,
    I haven’t a free custom dimension for storing the cid.
    Is there a possibility to obtain it with “Core Reporting API” in java? I’m looking for all 230 pre-defined google dimensions, but it seems that cid doesn’t exist. Can you help me? Thank you for all. Onofrio

  • Sayf Sharif

    It’s not in the Core Reporting API. You’ll need to use a custom dimension for it unfortunately. Are there any of your used custom dimensions that you can spare?

  • Onofrio

    Hi Sayf,
    thank you very much for your response.
    If this is the only way, I will use a custom dimension.
    Thank you. Regards. Onofrio

  • Alex

    Thank you Sayf, fantastic Article!

    I have got a question regarding the calculation from Pawel, that shows that the measurement protocol hit causes another session and therefore reduces the overall conversion rate. Would it be possible somehow, not just to tie the offline and online user together, but to add offline hits (e.g. a transaction) to a specific session? I have a customer who has got a manual review process after the web conversion and I only want to count the reviewed conversions.

    Second, I would like to ask, if a measurement protocol hit with a cid automatically gets the channel (organic, campaign, etc.) of the session that the saved cid had or is it handled as a “direct” session?

    Thank you, alex

  • Sayf Sharif

    yes it causes another session. One thing you can do is have those hits go into a specific /offline/ folder, and then filter that from your main views, and keep them in your conversion/goal views. Or maintain one view without them to get true engagement numbers.

    There isn’t currently a way to add something to someones session after that session is over in this manner that your’e referring to.

    As far as the source, you can modify that in the measurement hit itself, or you can set it as a direct, etc. I think by default it would be a direct visit.

  • Musakkhir Sayyed

    I have created custom metric named as “OrderValue” with scope type as a Hit and formatting type as an integer. The goal is to upload this metric value in GA against custom dimension. I have created One Custom Data Set and two .csv files are uploaded with given schema.


    Both csv files contain valid data, but in Custom reporting, The ordervalue is not reflected. Please note that I am planning to load the integer value in ga:metric3 against ga:dimension2. Is there some restriction on the type of values that go under custom dimensions. The value I have is “864364158.1408537764” which I think can be treated as string by GA.

  • Sayf Sharif

    Musakkhir, I apologize for not replying sooner, hopefully you already solved this problem. There’s I think a restriction on string length, but those values should be able to be placed into GA. The problem must be occurring somewhere else in your code.

  • Nicholas

    Very helpful article, Sayf!

    Quick question, if I send hits to a Goal page and I want those to be attributed back to the original, or last actual, traffic source, do I need to append that data to the payload? It’s matching up fine in all standard reports, except for MCF and Attribution, which are the most important. In those, all ‘direct conversions’ are being attributed to Direct.

  • Sayf Sharif

    It would in general be considered a new session if it happened later, and therefore ‘direct’ unless you otherwise specify. You could send with the hit a specific new source like “offline” or something, which would separate it from direct, but because your’e sending an offline hit, it’s hard for you to know the original source.

    Otheriwse, when you capture the user information (say they submit a form) you could pass with their id etc at that time to your system their source, and then use that with the offline hit.

  • Chris Morton


    I’m using GMT V2; I get a reference error when trying to set the hidden cid in the form.

    the ga function doesnt exist. Do you add this in GTM somehow?

  • Chris Morton

    To add,

    Does this code work when you are using GTM?

    ga(function(tracker) {
    clientId = tracker.get(‘clientId’);
    document.forms[0].cid.value = clientId

    I can get GTM to set the custom dimension but having no success with setting the hidden value for the form.

    • Sayf Sharif

      It may need some modification for use with GTM. I’ll take a look and possibly amend the post.

      • i found a work around when using GTM. In the page where I have the FORM I add the analytics.js code but don’t send the pageview hit. This seems to allow me to use the “ga function” later in the HTML and not send two pageview hits to GA.

  • For a non-techie person, is anyone interested in helping us out with closing the loop between leads and sales in Google Analytics? Please e-mail: – of course as a paid-project

  • Tomas

    Vote for to solve Time Stamp problems for ofline subbmitions

  • Vik

    Hi Sayf, as a non-techie, I’ve been researching the web and the Google Analytics Partner directory for professionals or service providers who assist businesses in tracking offline (in-store) transactions. For some reason all I could find were Call Tracking services. Would you be kind enough to point me to the right direction? Thanks.

    • Sayf Sharif

      Vik, I don’t have a specific service that I can recommend at this time. I wish I did. What I’ve seen so far is mostly custom solutions provided by partners like LunaMetrics through a company POS, or via some sort of offline method like importing transactions through a spreadsheet, via the measurement protocol, etc.

      • Vik

        Thanks Sayf. I wish it were more easily available.

  • Thanks Sayf, this was such a clear explanation!

  • Susan Rawlings

    This is so useful and clear. Thanks, Sayf!

  • Ken Whiteman

    Hi. Great article! I’m trying to get this set up through GTM. I’m using a data layer to get sales transaction data into UA. We have developed a way to get our hands on the CID during phone calls. Do I simply add ‘cid’:” to the existing list of data to override the CID field? The data layer seems to be working appropriately aside from tying the cid to the user. Do I also need to set up a custom variable in analytics to do that? I’m a bit of a noob and any tips you could give me would be very much appreciated.

    dataLayer = [{
    ‘store’: ‘admin site’,
    ‘pageType’: ‘transaction’,
    ‘supportId’: ‘”.strtoupper($support_id).”‘,
    ‘ecommerce’: {
    ‘purchase’: {
    ‘actionField’: {
    ‘customerID’: ‘”.$customers_id.”‘,
    ‘id’: ‘”.$order_number.”‘,
    ‘affiliation’: ‘Phone Order’,
    ‘callType’: ‘”.$dial_in_type.”‘,
    ‘revenue’: ‘”.$revenue.”‘,
    ‘shipping’: ‘”.$shipping_charge.”‘,
    ‘actualShipping’: ‘”.$actual_shipping.”‘,
    ‘COGS’: ‘”.$total_product_cost.”‘,
    ‘profit’: ‘”.$profit.”‘,
    ‘coupon’: ‘”.json_encode(utf8_encode($coupon)).”‘,
    ‘discount’: ‘”.$discount.”‘,
    ‘processed_by’: ‘”.$processed_by.”‘,
    ‘action’: ‘purchase’






  • EL

    Is it possible to tie a transaction to past events that are tracked in GA? For example, we are tracking lead form submissions as events, with a custom dimension that store a unique GUID at the time of submission. A few days or weeks later, a sale is generated and we want to credit the revenue to one of the leads submitted.

    This blog seems to tie a transaction to a visitor-level custom dimension. Is it possible to tie it to a hit-level custom dimension instead?

    • Sayf Sharif

      I guess my question would be “why is the guid value placed into a hit level custom dimension on the event?” Is it going to change on that browers like it’s on a public computer? The event itself is a hit, but you could pass that value in as an id for a user id or just a user scope custom dimension, and then pair it later.

      My general recommendation for this sort of situation though is to use the Measurement Protocol to later send an actual transaction hit, or other appropriate hit, with the CID or UID of the user, that way you get true attribution for it, as the offline hit just becomes a new session of that user. Without tying the hit to a specific userid or cookie id it won’t work.

      • EL

        Gotcha. One question: How does GA know to associate a Measurement Protocol transaction to a recorded previous hit data? in your example, all hits data has dimension1 as session id, then some days later we send a transaction Measurement Protocol with cd1 = a previous session that we matched offline. Since we never tell GA to use cd1 as key to match the offline data (like we have to do in Data Import), how does GA know to attribute that transaction to a particular session?

  • Ken Whiteman

    Hi Sayf,
    I’ve gotten this working for the most part. I am creating a six letter “customer ID” whenever a new visitor (unique google CID) comes to the site. We’re uploading it through the GTM data layer on every page view on the customer facing site and setting it as a user level scope. When a phone order comes in, we ask the customer for their Customer ID that is displayed in the footer and insert it into the transaction data layer on the transaction page on our admin site. We’ve verified that it is correctly tying the sessions and conversions together to one user, which is what we were hoping for. The ultimate goal of all this is to have the transactions credited to specific adwords campaigns so we can track actual ROI. Unfortunately, it appears that the admin site orders, while tying to the correct user, are being attributed to Direct and are not being reported to adwords as a conversion. Do you know if it is possible to force Analytics to ignore the attribution of the last click when it comes from a specific page? Or is there another way to skin this cat?


    • Sayf Sharif

      What I suggest is to use the Multi-Channel Funnels and the Attribution features of Google Analytics to use different attribution models than last click. You can see the various positions of the adwords campaigns in the customer path that way.

      • Ken Whiteman

        Thanks! That makes sense and it looks like the customization features allow devaluing URLs, which would allow us to essentially erase our admin site from the attribution. It looks like the attribution model is defined at the view level, not the property level, though. We have adwords account linking set up and right now two views are set up to synchronize. When a transaction happens, does the attribution model automatically calculate the conversion value to pass to Adwords? We are trying to get the actual CPA data so our SEM firm can measure the effectiveness of their campaigns.

  • Is there a way to send the date/time of the transaction?

    • Answering my own question after a long research:

      Unfortunately there isn’t a way to include a timestamp in the measurement protocol.

      • Sayf Sharif

        You could pull the date time either through using a secondary dimension looking at the transactions page, or you could create a custom report that is a flat table that shows the date, hour, and minute.

        Alternatively you could fire an event at the same time as the transaction, that contains the transaction id, and other information about the transaction in the event dimensions, or in custom dimensions, including a timestamp of your own formating. You could use that information, or you could pull it out of GA and tie it to your other ecommerce data on your own terms.

  • I’m having some confusion about some things:
    -cid should be the client ID correct? and google assigns this? I see it being assigned to in someexamples, so I’m not sure how/why.
    -uid is the new-ish param we should use for user id correct?
    -I’m testing doing offline conversions using both the google-assigned client id and the user id I’ve assigned. My primary goal is to load data into GA so I can look at which demographics slices perform the best. But my user id view doesn’t seem to show the demographics options… are these disabled in user id views? (I would prefer to use the user id if possible because it’s easier for me to assign, but I’ll extract the client id if necessary)
    -my conversions get loaded a day after the user first hits my site- so the conversions show up a day after. I understand I can’t put a timestamp on the transaction to force it to align, and I’m not a fan of putting it a new value (as discussed below), is there perhaps a way I can start the transaction on day 1, then add items to it later so they appear on that date?

  • would you consider updating the samples with the new uid param?

  • I’m adding ecommerce conversions after a 1 day delay, but it looks like they are not getting associated back to the original user. I see the conversions show up, but they’re like a separate/new user, but one without any user level info-ie, it doesnt know anything about the browser type, or demographics, or mobile-vs-desktop etc.

    is there some kind of timeout for when the conversion should get loaded back within? Does the clientid expire after some time?

  • Carlton van Putten

    I hope you are still paying attention to comments on this post. I am struggling with Google UA accepting and using cid they way you describe. When I send google’s own CID back to them in the measurement protocol cid parameter it doesn’t have the affect of tying the event to to customers online journey as I expected. What am I doing wrong?

Contact Us.

Follow Us



We'll get back to you
in ONE business day.
Our Locations
THE FOUNDRY [map] LunaMetrics

24 S. 18th Street
Suite 100

Pittsburgh, PA 15203


4115 N. Ravenswood
Suite 101
Chicago, IL 60613


2100 Manchester Rd.
Building C, Suite 1750
Wheaton, IL 60187