"Ugh, I can't tell what Analytics is seeing! Wouldn't it be nice if it had some form of logging?"

Well, it sort of does actually. We'll get to that in a minute.

Tying your Analytics data to particular users of your application is probably one of the best things you can do to clarify usage patterns. This takes the form of their User-ID feature, since their built-in Client ID isn't and cannot ever be 1:1 to a user. I encountered a slew of randomized and only semi-correct information tossed around on this topic, even from the mouth of Google itself. Clearly, it can be pretty frustrating getting User-ID working.

Here's the write-up I wish I had before all the wrangling. Foremost, prepare to dev cycle against a staging version of GTM and GA. In my early moments with the products, I deemed them so opaque that my only hope was to toss it changes, wait 24 hours, and check the result. However, by the end of it I learned it's totally possible to establish a feedback loop with the assistance of some tools.

Staging instances

Connect separate staging instances of Analytics and Tag Manager to all environments but true production. This gives you a place to dev cycle against user IDs, and isolate test page hits so they won't bleed into your production figures.

In the end, you'll want four instances, and four keys—production GA and GTM, then staging GA and GTM. Each pair goes into their respective environmental configuration. For us, this meant dotenv-rails's .env file, heroku config, and Vue's dev.env.js / prod.env.js.

Configure Analytics

You'll now configure your staging version of Analytics. Aiming to match configuration as closely as possible, you'll do these steps for production too once it's all working.

  1. Enable User-ID (in Admin > Tracking Info). This is how GA refers to this whole concept.

  2. Create a Custom Dimension (in Admin > Custom Dimensions). This is how Analytics lets you join their data to your user ID, and is hardcoded by index number beginning with 1.

Configure Tag Manager

Tag Manager's role here is passing data between your site and GA. Your User ID comes into existence in GTM's concept of their Data Layer. You then connect those values to GTM variables, which in turn are passed to any service, in this case Analytics.

  1. Set a dataLayer variable that receives the user ID from your view called userId.

  2. Create a tag for Google Analytics. Pass that user ID variable as:

    • A field under Fields to Set. Name it &uid. The Analytics User-ID view filters by this value.
    • A Custom Dimension. Match the index number to the one given to you above.

Flow of data through GTM

Snippet on your site

Now, you can copy in the snippet preceded by a dataLayer Javascript variable definition:

<script>dataLayer = [{'userId': '12345'}];</script>

<!-- Google Tag Manager -->
<!-- End Google Tag Manager -->

In my testing, your variable here must come before the GTM snippet. You'll replace the value of 12345 with your actual user ID via templating. For example, in Slim you'd use string interpolation:

  dataLayer = [{'userId': '#{current_user.some_public_facing_id}'}];

I recommend using a UUID or some other random alphanumeric ID so that you can identify yourself in when testing. Your staging Analytics instance will have everyone's data mixed together, so two environments could have user ID 6, but they'd be represented as one.

Does it work?

The true test, of course, is seeing your User IDs appear in Analytics. In checking this, note that real-time is truly real-time. You should have a User-ID view and an "all site data" view. Visit your site, go to Real-time and see yourself in "all site data," then switch to your User-ID view. After a couple of seconds, you should see the same data point appear in the other Real time.

Contrast that with all other reports. Take the All Pages view of Behavior. When setting your secondary dimension to your user ID custom dimension, I observed the data can take up to 10 minutes to appear and solidify.

During your initial stages of dev cycling, opt for the real-time report. Once that's working, come around to testing out the slow stuff.

Debugging tools

You're not seeing the data. Of course, it's never the first try.

Your first tool is Tag Assistant, a Chrome extension. As these products are firmly in Google-land, I found it was only available in Chrome. It lists out the instances of GTM inclusion on the current page, their ID, variables passed, and instances of Analytics it's including. Start with this, ensuring you have only one instance of GTM included and verifying your snippets are connecting to the staging version of each by comparing their IDs.

Analytics has a baked-in debug mode that shows you what variables it receives from GTM as Javascript console output. This is the closest you'll get to Analytics' internal workings, and carries more weight than the Tag Assistant's Data Layer tab. I observed my variables being passed just fine in Tag Assistant, but were still undefined in the console. Try both of the methods below until you see the values coming through.

This mode is toggled via GTM. Click into to your Analytics tag, open More Settings, open Advanced Configuration, and find Use Debug Version.

Alternative Method

I found that in one instance, the dataLayer method worked just fine, but in another no dice. If you still can't get your values to appear in Analytics debug mode, perhaps it's the nature and order of your Javascript.

Try this. Rather than setting dataLayer, set window.userId and grab it via Tag Manager.

window.userId = "#{current_user.some_public_facing_id}"

In Tag Manager, create a Custom Javascript variable. Its contents are simply:

function () {
  return window.userId;

Reference this instead from your Analytics tag when setting both dimension1 and &uid.

Going Live

Tag Manager aims to match a deployment cadence by implementing its own versioning. In fact, it even supports publishing changes to different environments. However, I didn't really enjoy its take on that, which is why I went with different instance IDs entirely.

You can deploy your staging GTM environment by exporting it then importing it to production via Admin > Export Container / Import Container. Don't forget to change your Analytics instance ID.

Boom. With that, you've made the marketing department very happy.

More blog posts