How to detect mobile device on Google Tag Manager, DTM & Tealium

Wwwhhhooaaaa this form looks perfect AF! Lemme check how it looks on mobile ???

Mobile responsiveness is a task, isn’t it? The most beautiful features on desktop, might sometimes appear disastrous on a mobile device. If a similar situation is ruining the mobile experience of your website, and you’re looking for a way to show certain features only to your desktop audience or vice versa, here’s how you can do it.

I’ll be helping you detect the device type of your visitors and use that data to serve different (and pleasant) experience on different devices (desktop and mobile).

Following is a detailed procedure on how you can achieve it using Google Tag Manager, but we will also talk about how you can do it on Dynamic Tag Manager by Adobe, and Tealium. Let’s get started!

Detecting a Mobile Device on Google Tag Manager

We’re going to divide the job into three parts.

I – Variable creation
II – Trigger creation
III – Application

I – Creating a variable

We’re creating a variable which returns the value true for a mobile device, and false otherwise. This variable is our device detector!

1 – On your GTM dashboard, go to Variables and click on New.

2 – Give a relevant name to your variable, and under the Variable Configuration, choose Custom JavaScript. I’ve named my variable as Device Check.

3 – Thanks to, which is an open source for mobile detection scripts in various programming languages, we can get a JavaScript snippet for our variable. Choose JavaScript and save the .txt file. Then just copy the entire code from the file and paste it as the custom JavaScript of your variable.

Alternatively, you can also just copy the script from here.

function () {
 var a = navigator.userAgent || navigator.vendor || window.opera;
 if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4))) { return true; }
 return false;

Paste the above code as the custom JavaScript of your variable and click Save. Our variable has been created!

II – Creating a Trigger

Now that we’ve detected the device type, this triggers our next action : Decide what our visitor gets to see! Based on the value returned by our variable, i.e., true for mobile and false for desktop, we’ll create a trigger.

1 – On your Google Tag Manager dashboard, go to Triggers and click New.

2 – Name your trigger and under Trigger Configuration, choose Custom Event.

3 – Since we want this trigger to fire at every page hit, under Event Name, type .* and check the checkbox to enable Use Regex Matching.

4 – Now is when our variable and trigger come together. From the two radio buttons, choose Some Custom, and apply condition to include or exclude a mobile device. To exclude a mobile device, we want to go ahead with devices that return false to our variable. This is what our condition must look like –

The above condition excludes mobile devices. If you want to exclude desktops/tablets, you can put the value true in the last field.

So now, we’re ready to finally achieve our goal of excluding/including mobile devices!

III – Application

The whole idea behind this article came from our own experience with a pop-up form that worked just fine on my laptop, but fucked up on mobile devices. We wanted to hide the form from our mobile audience, solved it and thought you might need the solution some time! And so the example application here, is a Mailchimp subscriber pop-up form that we added to our website by creating a tag on Google Tag Manager. Here’s the tag without any trigger exceptions –

We edited the Triggering settings of our Mailchimp tag, and of course employed the trigger we created in Step II. To add a trigger to your tag, click the Triggering tab and choose the trigger you created earlier for the task (Step II). That’s all!

DIY – Test our form on your desktop and mobile device! Open on private window of your browser.

So that’s how you can use Google Tag Manger to detect device types. Let’s see how you can achieve it on DTM (Adobe’s Dynamic Tag Manager)

Detecting a Mobile Device on Dynamic Tag Manager or Adobe Launch

On DTM or Launch, the process is much simpler. While creating any kind of rule, you get an inbuilt condition to select the device type. Just select the device for which you want to fire the tag from the drop down, as shown in the screenshot below :

DTM mobile device rule

You see? It’s that simple!

Detecting a Mobile Device on Tealium

In Tealium, it is not as straight forward as Adobe, but it’s still pretty simple. Following are the steps:

1 : Adding data source
Create 2 Data Layer elements:
  • device_mobile
  • device_tablet

(You can name them whatever you feel suits your business logic)

Step 2: Fill up your data layer values using a javascript extension


  • Select the add extension option -> Go to the ‘Advanced’ tab > Select ‘JavaScript Code’
  • Name your extension and paste the following code in the configuration field.
    // global var to detect mobile devices based on user agent
    utag_data.device_mobile = ((function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4)))return true})(navigator.userAgent||navigator.vendor||window.opera))?'true':'false';
    // global var to detect tablets based on user agent
    utag_data.device_tablet = ((function(a){if(/ipad|android.+\d safari|tablet/i.test(a))return true})(navigator.userAgent||navigator.vendor||window.opera))?'true':'false';
  • !!! IMPORTANT: Set the scope to ‘Pre Loader’ !!!

Step 3: Create your load rules

Detect Mobile device in Tealium Step 3
Build your load rules:
  • is Mobile true: device_mobile / equals / true (if you want to trigger things on mobile devices)
  • is Mobile false: device_mobile / equals / false (if you do NOT want to trigger things on mobile devices)
  • is Tablet true: device_tablet / equals / true (if you want to trigger things on tablet devices)
  • is Tablet false: device_tablet / equals / false (if you do NOT want to trigger things on tablet devices)

Step 4: Use your load rules / Save / Test / Publish / Have a drink (This is important)

How we can help

So that’s how you can take control of what your visitors see, depending on their device type. And there’s so much you can do with it! I hope this article was helpful. Feel free to reach out to us for any queries that you might have. Also, if you don’t have time to learn and apply the magic of analytics, that’s what we are here for! We are a crazy team of Google and Adobe Certified Analytics Experts who eat, breathe, sleep and dream Analytics. And we’ve made it our purpose and passion to electrify your business’s potential through Analytics.

Contact us here.

Found it informative? Leave a comment! You can also give us a thumbs up by sharing it with your community. Also did you know that you can light up our day by subscribing to our blog? Subscribe here –

Page Naming in Digital Analytics

Page Naming in Digital Analytics is the most fundamental requirement of Implementing Analytics on your Website. Yet, time and again I discern a casual approach towards it.

Now, human nature is more risk averse than reward motivated. So, let me tell you what you are losing first with a casual page naming.

In Sitecatalyst/Report and Analytics, several reports like your pathing reports, your clickmap reports are essentially based on your Page names. So, if you screw up your Page Naming you miss a lot on your other goodies.Plus, Pages report is very very special. It is an out of box s.prop(traffic variable) with special powers. You can drill down all other reports based on pages report. Thus, it is one of those reports which will be kind of ubiquitous in your Analytics reporting and thus it gets extremely important for the organization to do the page naming exercise with devotion.

Page Naming is not retroactive. Let me elaborate – Suppose you casually named your pages, then one fine day someone in your organization is struck by lightening and the fellow declares – dude! we need to have clean page naming. Very well dude! But, the problem in Sitecatalyst will consider the modified/updated names as entirely new pages! So, you will not get historical data combined with the fresh data for a page whose name has been modified. Instead, you will get data in two separate rows as two separate pages.

If you don’t give your webpage a name for Analytics, Sitecaalyst will automatically fetch the URL as the page name. Now, few screw ups here –

  • and are essentially the same page, but to Sitecatalyst they are entirely separate pages!
  • If your page is Dynamic using some swanky Rich Internet Applications, then all the pages will be clubbed as one because the content of the page changes but the URL remains the same. So, all pages will be reported as one!
  • How good are you with reading URLs and separating one from the other in a table full of 50 URLs? I am pathetic at it. Please give me names
  • In Sitecatalyst tables, the rows have a limited space to display Data. You are wasting precious real estate with http://www…….yada yada
  • ClickMap uses the s.pageName variable to identify ClickMap pages. If the implementation changes on a page where s.pageName is a different value, ClickMap does not show historical data. Thus, you end up getting partial data for links on a page.
  • The partial data issue is equally applicable to your pathing reports also. Pathing reports – Next page, Next page flow, previous page, previous page flow et al, in all these reports you select the page name as the criteria, not the URL.

I hope, you now understand the importance of page naming. If you are scared that “freak! but, my page naming is screwed.” then dude, you should be!

Now, I will present some points from the implementation side, some strategies to implement the page naming variable and some cheats to clean your page naming implementation, yeah yeah don’t be scared.

*popping fingers*

So, Now from implementation point of view Pages report is populated by s.pageName variable which has a query string parameter as pageName or gn in the Adobe Analytics image request. As i mentioned above it is a traffic variable and thus has a character limitation of 100 bytes, this means input beyond 100 charachers to this variable will be truncated.

Now, various ways through which you can feed value to this variable –

  • Server side –

Better suited for Dynamic pages

  • Hard code –

Suitable when you have very less number of pages and you are dealing with a team which is Analyticsally challenged. So its like –dude, don’t do anything else, don’t touch anywhere, just place this code on your webpage and tell me once done, again don’t touch anywhere. Dynamic pages are difficult to hard code, totally avoid it. 

  • Page Name plugin 

This plugin needs some configuration and it uses the structure of the URL to populate page names. Use this plugin only when you have a clean URL structure. 

I will make an entry on this plugin in some other blog.

  • document.title

This one is pretty straight forward. It uses the the value in the <title> tag of your HTML page and uses that as the page name. It is one of the most common approaches to automate the process of page naming. The only drawback which i have witnessed is at times multiple pages have the same title though their context is different. And what you gonna do bro when a page does not have a <title> tag?

  • Outsource your page naming to an Indian company. eClerx does a very good job with it. We will look at each and every page of your website and give it a clean name with valid context. Hint – there is something called processing rules *bling bling*

Now, some strategies to have page names. The three Cs of Awesome page naming –

  1. Conciseness – Keep it short
  2. Clarity – Keep it easy to understand
  3. Context – Ensure that the end user is understanding the right thing

Now, the small s – Structure! why structure?

The page Naming is still not that simple. It very much depends on the structure of your website and how vast and deep is your website. if it is a biggie then just one s.pageName will not be sufficient. You have to use other variables that are giving the detailed description of the webpage.

If you have a proper structure in your s.pageName, then you can use the this structure to feed values to other variables as well. like variable which is used to populate the site sections report.

A few examples –

Now, lets take a hypothetical website – (born narcissist) , now i sell super hero collectibles. I sell comics, costumes, merchandise, videos and hope 🙂

Now, lets take a webpage where I am selling Batman’s Poster where Bruce Wayne meets Bruce Wayne. So, what should be the ideal page name?

Merchandise | Batman | Poster | Bruce meets Bruce

Now, this is concise, it is easily understood and conveys the right information and it is structured.

I can use this same variable, perform a channelextract and populate other variable like my for site sections reports. What are the advantages of using same variable to populate others? Automation bro!

Now, some cheats-

1. How to find pages with no page name?

Simple, go to your pages report. In the filter box type http . This will give you the list of pages with no page name. Again this thing won’t work if you are using the page name plugin. That’s why i said that use page name plugin only when you have clean URL structures

2. How to find Mutiple URLs populating same page name?

One, you go to pages report. Drill them down with the report which is being used to capture page URLs. Here if you can discern that different URLs are having same page name then you get your answer. Now, again this thing is not advisable for massive websites

Two, outsource it to an Indian company. eClerx does a very good job with that 🙂 We will audit each and every page of your site and then report the pages where different contexts are sharing same page name.

3. How to fix page names without altering the site?

Processing rules bro! Use the condition when URL matches overwrite s.pagename to some page

Now, again as i said the data is not retroactive and it will be a birth of a new page in your analytics reports. So, what you can do is use new variables – one prop and one eVar to store the new page name and henceforth refer to them, and maintain record of what has been replaced for any historical comparisons.

I hope you found what you were looking for and I was able to convey my message properly. Please feel free to reply back to me your thoughts. I sincerely welcome any suggestions, critique.

If you want to contribute any more information, you are most welcome. Please share it if you feel this is worth sharing.

Till then, stay thirsty, stay awesome and spread positivity 



How to Track AJAX site in Adobe DTM (Dynamic Tag Manager)


To Track Ajax based websites using Adobe DTM we need to use the Direct Call Rules.

Essentially, these are situations in which the content of the page changes without any change in URL or HTML elements. For example, a multi step form where in different steps of a form appear based on user interaction without any change in page URL

To implement Direct Call Rule, you will need support from the Dev team

The Dev team needs to call the function “_satellite.track(“Name of action”) ” in a JavaScript after successful rendering of the required user experience. Please note “Name of action” is just an example, it can be anything based on the business case.

Then, you need to mention the Direct Call String in the “String” field of Direct Call Rule condition in the DTM interface. In our example, string will be Name of action

Please note, _satellite.track only notifies DTM about existence of a condition that needs to be tracked. It does not tell what to track

_satellite.track tells DTM when to track

_satellite.track doesn’t tell DTM what to track

We need to configure the Adobe Analytics settings within the Direct Call Rule in DTM interface to tell DTM what to track

For example eVar1=”Step 1″

We can also use Data Elements to do this.

Now, what if we want to capture something which is not pre populated within the Data Layer?

Under such condition we need to dynamically create the Data Elements as well.

We can create Data Elements dynamically by using the _satellite.setVar(“Name of Data Element”,Value) function. This function also needs to be passed by the developer.

So, lets say user selects a particular option from drop down in the form and then completes step 1 of the form such that the page URL does not change. The developer will need to pass something like this in the JavaScript function.


var FormElement = JQuerycode to capture dropdown option;

_satellite.setVar(“Form Dropdown selection”,FormElement);

_satellite.track(“Form Step 1 complete”)


Once, the above has been configured on the page, we need to go to Direct Call rules, under condition we need to write Form Step 1 Complete and then we can configure any of the custom variables by typing in %Form Dropdown selection% in the value field for that variable.


Kindly leave your comment below.

If you would like to receive our latest posts kindly subscribe to the blog


Sanmeet Singh Walia

Founder, DataVinci