• Courses
    • Courses
    • Course bundles
  • Blog
  • Services
  • Resources
    • Youtube channel
    • E-books and Guides
    • GTM Recipes
    • View All Resources
    • GTM Community
    • GA4 community
  • About
    • About
    • Contact
  • Login
  • Courses
    • Courses
    • Course bundles
  • Blog
  • Services
  • Resources
    • Youtube channel
    • E-books and Guides
    • GTM Recipes
    • View All Resources
    • GTM Community
    • GA4 community
  • About
    • About
    • Contact
  • Login

June 1, 2021

Transfer UTM Parameters From One Page To Another with GTM

Updated: June 1st, 2021. 

I have completely redone this solution to support more cases and require less configuration. However, in some situations, the older version of this solution is recommended. If the destination URL contains a hashmark (#), you should try using the older version.

====

Imagine this. You’re running a promo campaign that brings traffic to a certain landing page (e.g. landingpage.com). After the visitor clicks the main Call-to-action button (e.g. GET YOUR DISCOUNT), he/she is redirected to another page (2ndpage.com) which asks a visitor to do the final action, install the app, fill in the form, sign up, etc.

When the conversion is completed, a Google Analytics event is fired. Unfortunately, when you look at your GA reports, what you’ll see is that all conversions are attributed to the landingpage.com. Technically, this is correct because all visitors landed on the 2ndpage.com from landingpage.com, but you’d like to see the original source which brought the visitor, wouldn’t you?

Normally, you’d need to implement cross-domain tracking here but in some cases that is not possible (I’ll explain them a bit later).

In this blog post, I’ll show you how to transfer UTM parameters (or basically any URL parameters) from the initial page landingpage.com to the subsequent one (2ndpage.com) if the cross-domain tracking cannot be implemented.

The problem explained

Say, that you’re promoting a product that is available in the App Store (for example, Shopify App Store). We’ll call it Lorem Appsum. Its App Store page isn’t sufficient to list all the benefits, cool features, etc. So you decided to create a separate landing page that you’ll drive traffic to. You have also marked all inbound links (stored on other websites/forums/etc.) that lead visitors to that landing page with UTM parameters.

That new landing page contains key selling points, descriptions of features, video, and a big GET APP NOW button (Call-to-action, a.k.a. CTA). Perfect. The visitor lands on the initial page, he clicks that CTA button, lands on the App Store page and installs the app. Heres’ the scheme of the entire visitor journey:

Visitor journey

Notice that UTM parameters are lost after the visitor clicks an appstore.com link on loremappsum.com page.

The problem is that Google Analytics will attribute this conversion to loremappsum.com, although it would be more beneficial to see the values of the initial UTMs.

 

Why not implement GA cross-domain tracking?

In the case of app stores, usually, creators/developers are not allowed to edit Google Analytics tracking code, therefore cross-domain tracking cannot be configured properly.

This is what we faced with Omnisend (when I was working there) at Shopify Appstore. We were allowed to set Google Analytics Tracking ID, and that’s it. Unfortunately, in order to make cross-domain tracking work, we also needed to enable allowLinker option on the receiving domain (app store) but that was not possible.

So we had to improvise and this blog post is the solution to the problem.

 

 

 

The Solution – Overview

Update: This is version 2 of the solution. With it:

  • you will be able to transfer any query parameters (not only UTMs)
  • you will not need to create URL variables
  • you can decorate links of multiple domains
  • and query parameters that you want to transfer are optional (this means that if utm_campaign is not present in the URL, the solution will still work). 

====

One of the solutions is to transfer UTM parameters from loremappsum.com and automatically add them to all links which redirect users to appstore.com/loremappsum. We’ll do this with Google Tag Manager and a custom script.

Important: if you notice that the script is not working in some situation, please let me know and I’ll see what I can do to fix it.

<script>
(function() {
  var domainsToDecorate = [
          'domain1.com', //add or remove domains (without https or trailing slash)
          'domain2.net'
      ],
      queryParams = [
          'utm_medium', //add or remove query parameters you want to transfer
          'utm_source',
          'utm_campaign',
          'something_else'
      ]
  // do not edit anything below this line
  var links = document.querySelectorAll('a'); 

// check if links contain domain from the domainsToDecorate array and then decorates
  for (var linkIndex = 0; linkIndex < links.length; linkIndex++) {
      for (var domainIndex = 0; domainIndex < domainsToDecorate.length; domainIndex++) { 
          if (links[linkIndex].href.indexOf(domainsToDecorate[domainIndex]) > -1 && links[linkIndex].href.indexOf("#") === -1) {
              links[linkIndex].href = decorateUrl(links[linkIndex].href);
          }
      }
  }
// decorates the URL with query params
  function decorateUrl(urlToDecorate) {
      urlToDecorate = (urlToDecorate.indexOf('?') === -1) ? urlToDecorate + '?' : urlToDecorate + '&';
      var collectedQueryParams = [];
      for (var queryIndex = 0; queryIndex < queryParams.length; queryIndex++) {
          if (getQueryParam(queryParams[queryIndex])) {
              collectedQueryParams.push(queryParams[queryIndex] + '=' + getQueryParam(queryParams[queryIndex]))
          }
      }
      return urlToDecorate + collectedQueryParams.join('&');
  }

  // borrowed from https://stackoverflow.com/questions/831030/
  // a function that retrieves the value of a query parameter
  function getQueryParam(name) {
      if (name = (new RegExp('[?&]' + encodeURIComponent(name) + '=([^&]*)')).exec(window.location.search))
          return decodeURIComponent(name[1]);
  }

})();
</script>

Once the visitor lands on loremappsum.com AND the Page URL contains utm_medium, utm_source, or any other URL parameter (that you’re interested in), the tag will fire. It will scan the entire page and look for links that contain the domain(s) of the final landing page, in this case, appstore.com.

If the script finds the link, it will:

  1. Fetch URL parameters (e.g. UTMs) from the browser’s address bar.
  2. And will add those parameters to that spotted link (which contains “appstore.com”).

So instead of appstore.com/loremappsum, all links on loremappsum.com will be automatically modified to appstore.com/loremapsum?utm_medium=referral&utm_source=promo &utm_campaign=blackfriday2017. Here’s the updated visitor flow:

Updated Visitor Journey

 

This solution does not cover 100% of cases

There are situations where this solution will not work properly:

  • If the URLs that you wish to decorate contain #, try using the older version of the solution
  • If the URLs that you wish to decorate already contain query (a.k.a. URL) parameters from the Custom HTML tag, they will not be replaced. The script will append them to the URL (therefore, you will end up with duplicate parameters).

Notice more situations where the script does not work as expected? Let me know in the comments and I’ll see what I can do.

 

The Solution – Implementation in GTM

In Google Tag Manager, create a custom HTML tag and paste the JavaScript code that I provided in the previous chapter.

Now, we need to do some configuration.

 

Edit the list of domains

On line 3, you’ll see this domainsToDecorate array:

  var domainsToDecorate = [
          'domain1.com', //add or remove domains (without https or trailing slash)
          'domain2.net'
      ],

Here you must enter the domain(s) of the final landing page(s). If a visitor lands on the intermediary landing page, the script will be looking for links that contain the domain(s) from the domainsToDecorate array.

In other words, if the journey is some website > loremappsum.com > appstore.com, then you must enter “appstore.com” in the domainsToDecorate array.

If you want to decorate URLs of just one domain, you can keep just one domain. If you want to add 4 domains, you can do that as well. Just make sure you don’t leave any typos, missing commas or apostrophes.

If you want to be more specific and decorate only some links, you can be even more specific. Instead of the appstore.com, you can enter appstore.com/your-app.

Here is an example with just one domain (obviously, you should replace that domain):

  var domainsToDecorate = [
          'appstore.com'
      ],

 

Add URL parameters you want to transfer

Next, you must edit the list of URL parameters you want to take from the page URL and transfer them to particular outbound (outgoing) links.

If for example, Page URL (where a visitor currently is) is https://www.loremappsum.com/?utm_medium….., then those parameters (e.g. utm_medium) will be added to all the URLs of the appstore.com, e.g. https://appstore.com/loremappsum/?utm_medium…

queryParams = [
          'utm_medium', //add or remove query parameters you want to transfer
          'utm_source',
          'utm_campaign',
          'something_else'
      ]

What’s cool with the recent update of this solution is that:

  • You don’t have to create GTM variables for each parameter
  • You can transfer any URL parameter (a.k.a. query parameter), not only UTMs
  • The parameters you entered in the queryParams array are all optional. If Page URL does not contain, say, utm_campaign, the script will still work just fine
  • UTMs can contain a “+” sign as well. It will be transferred just fine and will not be encoded to %2B.

Here’s an example of what the setup could be:

queryParams = [
          'utm_medium',
          'utm_source',
          'utm_campaign',
          'ref'
      ]

Save the tag. Now, it’s time for a trigger.

 

Trigger

You don’t want to fire this Custom HTML tag on every page. Instead, you should activate it only when the URL contains at least one of those query parameters that you want to transfer. Let’s continue our example where I entered these query parameters in the Custom HTML tag:

queryParams = [
          'utm_medium',
          'utm_source',
          'utm_campaign',
          'ref'
      ]

So, if any of these parameters are in the URL, the Custom HTML tag should fire. Every parameter in the URL should also contain an “equals” sign (=), therefore, our trigger’s condition should be like this:

  • Trigger type: DOM ready
  • Fire on some DOM Ready Events
  • Page URL matches RegEx (ignore case) utm_medium=|utm_source=|utm_campaign=|ref=

What I did here is that I have added “=” after every parameter and then separated them with a pipe ( | ), which in Regular Expressions means “OR”. Of course, we could write a more optimized expression such as:

utm_(medium|source|campaign)=|ref=

or something even slimmer but even the first example will work just fine. If you don’t feel confident with regex, just enter all the query parameters you are interested in, add “=” after each one of them, and separate them with a |.

Save this trigger and assign it to the Custom HTML tag.

 

Let’s Test

Save all changes, enable Preview and Debug mode. Now head over to the page you’re working on. There are two situations we need to test:

  1. Make sure that is at least one of the query parameters (that you want to transfer) in the Page URL. In my case, the page URL is www.loremappsum.com?utm_medium=referral&utm_source=promo &utm_campaign=blackfriday2017
  2. Click the link which contains the domain name you have defined in that custom script I’ve shared in this blog post. In my case, it’s www.appstore.com/loremappsum
  3. After I’m redirected, the Page URL (appstore.com/loremappsum) should also contain those 3 UTM parameters. The final result in the browser’s address bar should be www.appstore.com/loremappsum?utm_medium=referral&utm_source=promo &utm_campaign=blackfriday2017
    Appstore URL in browser address bar

Also, do not forget to test the opposite situation when there are no UTMs (or other parameters) in the address bar. In that case, nothing should be appended to appstore.com links.

Oh, there’s also a third case to test, check at least a couple of other external links (unrelated to appstore.com), they should never contain UTM parameters.

 

Transfer UTM Parameters: Final words

In this blog post, I’ve explained how to transfer UTM parameters (or any other URL parameters) from one page to another. This is really useful when you have an intermediate landing page that you’re attracting visitors to, and then they have to proceed to the final page which is stored in another domain.

This is a plan B if you cannot implement Cross-domain tracking for some reason.

By default, you’d lose all attribution data and Google Analytics will display your intermediate landing page as the main referral.

With the script I’ve shared, you’ll be able to reuse UTM parameters of the initial landing page and decorate certain links with them.

However, keep in mind that obviously, navigation between the intermediary page and the final landing will start a new session (and the same person will still be treated as two different people in your GA reports).

The situation I’ve described is not a very common issue, but it occurs from time to time. Actually, one of my readers has recently asked a question related to this very same topic.

Julius Fedorovicius
In Google Tag Manager Tips
115 COMMENTS
Thomas
  • Jun 15 2018
  • Reply

This was great information to have for a pizza website I'm working with. Thank you!

R K Kalaga
  • Aug 24 2018
  • Reply

Hi:

Thanks for publishing a wonderful article on UTM passing across URLs. I have been looking for a solution for the problem defined below:

- I provide a link with UTM parameters in emails we send. Whenever a user clicks, he lands on the landing page along with UTM parameters
- From here on, when the user clicks on any of the links within the landing page, he goes to the main website. We want the UTM parameters to be passed on to the main website URLs and from there on, to all the URLs within the website visited by the visitor, ultimately leading to acquiring the UTM values when a form is submitted. This will give us an accurate attribution.

I thought the solution you provided here will work for me. The UTM parameters are not being passed on to the links clicked. Can you please advise how to fix this?

Thanks

RK

    Julius Fedorovicius
    • Aug 24 2018
    • Reply

    Hey, what you need is cookies.
    1. Set cookies that contain UTM parameters https://www.analyticsmania.com/post/cookies-with-google-tag-manager/
    2. Insert values of those cookies with some simple JavaScript https://www.analyticsmania.com/post/enrich-form-submission-data-with-google-tag-manager/

      Jake
      • Oct 20 2020
      • Reply

      I also want to use this solution for attributing affiliate conversions in Google Ads. However, wouldn't I need to also have the Google Analytics code on the second domain (appstore.com)?

itay
  • Aug 24 2018
  • Reply

Assuming that I have an HTML page, And I want that for every user that enter my page, I want to send his first UTM SOURCE,Using a custom dimension, to the GOOGLE ANALYTICS.

explanation:

On the HTML page i need to use a code that enables me to capture incoming traffic's first visit UTM_SOURCE, and send it to GA via custom dimension. than, i need to use a cookie to store the first occurrence of "utm_source" from the URL.

How can this be done?
important notice: i need to use a custom dimension in my html code at my solution ,
and as i said, i need to store it in a cookie.
i understand that i should use the gtag.js

Thank you very much for the help

    Julius Fedorovicius
    • Aug 24 2018
    • Reply

    1. You don't need gtag.js if you use GTM. Ever.
    2. When a visitor lands on a page, create a URL parameter that reads utm_source. Here's the guide where you can learn it
    3. Store the value of that urm_source in a cookie. Here's a guide how to create and read cookies with GTM
    4. Send the value of the cookie as a custom dimension with GTM. Here's an example how it can be done.

      itay
      • Aug 24 2018
      • Reply

      hi julius, thank you very much for your quick and detailed answer!
      i wanted to know, in which of the steps (1 to 4) should i take care of the
      "capture incoming traffic’s first visit UTM_SOURCE"?
      thanks again!

        Julius Fedorovicius
        • Aug 24 2018
        • Reply

        1st guide - Read the value of utm_source that is currently in the URL
        2nd guide - how to save it in the cookie

Dig Altamiranda
  • Nov 16 2018
  • Reply

Hello,

Thank you for this great article! Do you know if this works for AMP containers as well?

    Julius Fedorovicius
    • Nov 16 2018
    • Reply

    Unfortunately, no. AMP GTM containers do not allow to add custom JavaScript (including this script).

Michiel
  • Jan 30 2019
  • Reply

Hi Julius,

Very useful. We've been testing this for quite a while and passing the UTM through works fine. However when I started analyzing the data in Google Analytics we found out that there was a massive increase of bouncerates.

We use this for marketing automation purposes. So when someone visits our website via for example a LinkedIn ad, we can exactly track what this visitor does on our website from the ad with UTM.

Somehow this solution affects bouncerates badly. And the main reason I can think of is that every time a page is loaded with UTM parameters, Google Analytics is starting a new session. So even when a visitors visits a second page, it automatically counted as a bounce. Do you agree? And do you think there is a way to fix that?

Hope you can help me out!

Michiel

    Julius
    • Feb 1 2019
    • Reply

    Yes, your observations are correct. If a visitor lands on your 1st website, does nothing (no events) and then clicks the link with UTM parameters that lead to the website #2, then a new session will start. This means that your previous session will be counted as a bounce.

    An idea for you: track links clicks. So if a visitor on a website #1 clicks a link to the website #2, track it as an event and this will keep your bounce rate lower.

Robert Rose
  • Feb 4 2019
  • Reply

Thanks for outlining this solution.
You most likely already addressed this question in a comment above, but I'm curious if this solution would work if you only have access to the final domain in the process?

For example, I'm working on a project where we will most likely have 10 digital media campaigns for 10 different products. Those campaigns will drive to a Product Page (productdomain1.com, productdomain2.com, etc.)

Then in order to purchase Product1 --> productdomain1-10.com will drive to -- > ecommercedomain.com where you can purchase any number of products 1-10.

If I only manage Google Tag Manager for ecommercedomain.com will I be able to apply this solution to determine the UTMs that began the campaign journey?

Thanks!
Rob

    Julius Fedorovicius
    • Feb 5 2019
    • Reply

    Hey, Robert. The answer is no. You won't be able to apply this method.

Mike Wong
  • Feb 15 2019
  • Reply

Hello Julius,

This is almost working for me. In both Preview Mode and when published, I can see the UTM parameters being appended to the URL of a button when I hover over the button. If I copy the link address, it copies everything as you would expect.

But when I click on the button, the new page on my site opens and the UTM parameters are not in the address bar.

Any suggestions? I've pasted the URL with the UTM parameters below.

Best,
Mike

ps - I purchased your beginner GTM class, but haven't gotten very far in it yet. Maybe I should do that first! :-)

    Julius Fedorovicius
    • Feb 15 2019
    • Reply

    Hey Mike,

    This topic is not covered in my Beginner course.

    From your link I see that you are probably working with the AMP website, right? This solution is not tested and probably will not work with AMP.

Stephanie Luk
  • Feb 19 2019
  • Reply

Hi Julius
Thanks, this article is helpful.
I just wanted to ask, this definitely works if all my tracking links have all the UTMs identified e.g. medium, source, campaign. However, some of my tracking links have content and term and even gclid. Is there a way where it just picks up whatever is available?

For e.g. if i have utm_medium=xx&utm_source=xxx&utm_campaign=xxx,gclid=xxx
it will pick up that.
but at the same time if my next tracking link comes in as utm_medium=xx&utm_source=xxx&utm_campaign=xxx,utm_term=xxx
It will still pick it up

Since at the moment, the instructions is all the parameters need to be "does not equal" to "undefined"
I want it so, it picks up any parameters when available, not when all parameters are available.

Hope it makes sense.
Cheers
Steph

    Julius Fedorovicius
    • Feb 21 2019
    • Reply

    Yes, you just need to update the "utms" JS variable in the script. Currently, there are 3 utms in that array, but you can add more. This script currently only fetches those query parameters that are in the "urm" array.

      Jake
      • Oct 20 2020
      • Reply

      I also want to use this solution for attributing affiliate conversions in Google Ads. However, wouldn't I need to also have the Google Analytics code on the second domain (appstore.com)?

Aron
  • May 5 2019
  • Reply

I'm totally new to Google Tag Manager
Can I ask, what kind of tag types are these for the UTM parameters?

page: https://www.screencast.com/t/oaI4ThJdNf

    Julius Fedorovicius
    • May 8 2019
    • Reply

    Hey, I'm not sure I understand the question. UTM tags are not the same as GTM tags. "UTM tag" is just a name and it is a part of the page link. In GTM, tag is a tracking script that does something.

    All in all, they are two different things. Very different.

Ronnie
  • Jun 20 2019
  • Reply

Thank you so much for sharing this unique code. It worked great, however, what if in addition I want the UTM parameters in the URL to stick across pages on the same domain as well (like a multi-page quote system)?

    Julius Fedorovicius
    • Jun 21 2019
    • Reply

    Why would you possibly need that? It's fully enough for UTMs to appear on the page just once per domain per session. GA takes care of the traffic source attribution.

      Rémi
      • Dec 10 2021
      • Reply

      Hi Julius,

      I'm in the same situation where I need those UTMs to be passed on from one page to the other, in the same domain. Basically, once people browse in Website 1, they lose UTM parameters. And when they finally click on a button in Website 1 that redirects them to Website 2, UTMs are lost. So I'm looking for a way to keep transfering UTMs in all URLs, whether on Website 1 or Website 2.

      Any chance you have a solution for that too? Thanks a lot,

      Rémi

Muhammad Ali Silat
  • Aug 22 2019
  • Reply

Hey Julius, this is really helpful. I have put main domain, we get traffic from different sources and we create landing pages as well. So, we need to see if visit is landed on landing pages, he/she came from homepage or directly from the source. With this implementation, I see UTM Parameters transferred from page to page and that's how we will see the source in GA for landing page. Correct me, if I am wrong.
Thanks

    Julius Fedorovicius
    • Aug 23 2019
    • Reply

    No, this solution should work only on landing pages. If you see UTMs on every page, this means that you have entered your own domain in the custom script. That's not how you should use the code.

Tom Young
  • Nov 6 2019
  • Reply

Hi Julius,

I was wondering if you could help please.

I've followed your steps but the UTM codes are not tracking onto the final website.

So this is the journey in three simple steps:
1) Facebook Ads and Google Ads containing relevant UTM codes
2) links through to a dedicated product landing page and the UTM codes to follow through
3) click a submit button on dedicated product landing page and it takes you to a different domain

Thanks,
Tom

    Julius Fedorovicius
    • Nov 6 2019
    • Reply

    This solution works with links, not forms (and I'm guessing you're working here with forms). In that case, you would need to contact the developer of the form and implement a similar solution in form's code.

Poulav
  • Jan 6 2020
  • Reply

Hey,

Don't you think this would lead to inrease of bounce rate and number of sessions?

Thanks

    Julius Fedorovicius
    • Jan 6 2020
    • Reply

    The bounce rate can be easily manipulated even in this case (e.g. send an event when the link is clicked). The number of sessions will be affected.

Franck
  • Mar 19 2020
  • Reply

Hi Julius, thanks a lot for this great tutorial.
I wonder if this method could be useful to transfer _GA variable (session ID) on an external domain (eg: paypal.com) in order to track and keep entire user journey across purchase process. Payment solutions website are really a challenge for Goggle analytics : most of them don't allow to add any tracker at all and generate urls dynamically..

    Julius
    • Mar 19 2020
    • Reply

    Sending session to sites like paypal.com won't help because those website must accept and store your session info somewhere. And they usually don't do that.

      Franck
      • Mar 19 2020
      • Reply

      Thanks Julius for your valuable advice.
      So then, there is no way to track journey through paywall solution..to know where successful sessions are really coming from.
      Either I keep Paypal (and others) among referrals sessions sources or
      I exclude Paywalls through the Referral Exclusion List, but this will inflate Direct access sessions.
      In any case sessions are broken, sessions numbers are artificially inflate and Source shares are incorrect: either a bigger % of "Referral" session or a bigger % of "Direct" access.
      Is there anything I could trick to mitigate this situation, at least?
      My sincere thank you

        Julius
        • Mar 19 2020
        • Reply

        If the traffic is (direct), google analytics will attribute the conversion/sale to the previous non-direct traffic source, e.g. Organic.

        Julius

Nicolas
  • Jun 7 2020
  • Reply

Hi Julius, awesome solution. Does it work for payment gateway? If its so, should I check the utms parameters when I come back to order-received page or on the current PV payment gate?

thanks in advanced

    Julius
    • Jun 7 2020
    • Reply

    It works for anything that is accessed via link click.

Cris
  • Jun 11 2020
  • Reply

Hello Julius,

Thank you for this tutorial. Just wondering if this can work on ecomm process, say you direct a customer on a collection page with UTM, and they navigate through the website, then finally convert. Can I pass those parameters across all pages until they reach checkout and convert?

TA

    Julius Fedorovicius
    • Jun 11 2020
    • Reply

    You don't need that if this is happening on the same domain. GA will automatically keep the traffic source intact.

Brooke
  • Jun 25 2020
  • Reply

Hi Julius,

This article is a great find. Thanks for simplifying.
Just have a question as to whether this is best practice for tracking links that might cross multiple domains.
Example:
We are paying for media on a publisher's website, that link will drive to our owned social post, we then want to track whether we had any leads to our owned website from the original publisher's link.

Publisher > Facebook post (owned) > Website (owned) = will we be able to see that the referral came from Facebook but source was the publisher?

    Julius Fedorovicius
    • Jun 25 2020
    • Reply

    Hi, that is impossible to track because you would need to have some tracking code added to Facebook's interface.

Laslo
  • Jun 30 2020
  • Reply

Hi Julius

Thanks for the post. I've implemented the code but I'm having some troubles...

My goal is to transfer UTM parameters throughout the site in the following setup:

The visitors enter my website via this link:

mywebsite.com/test?utm_source=newsletter&utm_medium=mail&utm_campaign=062020

They than go to:

mywebsite.com/form/

The parameters aren't transferred from /test to /form when I've implemented the code.

Am I missing something?

Thanks in advance!

    Julius Fedorovicius
    • Jun 30 2020
    • Reply

    The parameters are only transferred if both conditions are met:
    1. Link is decorated
    2. The link is clicked

    Regular navigation does not preserve the parameters. If one the page A, you see the parameters added to the link, then the redirect between the page A and page B is losing those parameters (and you should discuss the fix for that with you developers)

Alisha
  • Jul 13 2020
  • Reply

Hi Julius!
Great Post. Is there a way to transfer these UTM parameters from one url to other, in case of multiple redirections through tracker pages(when using third party trackers as well) between the source and the Landing Page?

    Julius
    • Jul 13 2020
    • Reply

    Hi, no. Javascript in the browser (client-side) cannot help here.

    If all the redirects were controlled by you, you could ask a developer/sysadmin to preserve those parameters somehow. But if the server-aide redirects happen and developer cannot help you, you are out of luck.

Alisha
  • Jul 13 2020
  • Reply

Ah ok! So I get this script needs to be part of each page that the UTM parameters needs to be transferred to, essentially like a passing the baton kind of situation.

Are there any other options?

    Julius
    • Jul 13 2020
    • Reply

    Options for what? To overcome those redirects you mentioned? There are no javascript solutions for that (meaning that GTM cannot help). Talk this with your developers, maybe they can offer something on the backend.

Stephen Stouffer
  • Jul 16 2020
  • Reply

First off - this is GREAT. I'm wondering how I address if one of the UTMs is missing? Right now, it will not move ANY over if they do not ALL Exist. I'm looking to pass over what I can vs an all or nothing situation.

Thanks!

    Julius Fedorovicius
    • Oct 2 2020
    • Reply

    I have just updated the code. Now it supports any number of parameters in the URL.

Joy
  • Oct 5 2020
  • Reply

Hi thank you for posting this!
What I am doing is embedding a form into a landing page and using the main landing page to have the UTMS. But when I tried this code it still didnt seem to capture the UTMs. Any ideas?

Thank you!!

    Julius
    • Oct 5 2020
    • Reply

    Hi, this solution is not built for iframes. Only links are supported.

Bytehawk
  • Oct 12 2020
  • Reply

I had to change one small thing to your script :

{ if (links[linkIndex].href.indexOf(domainsToDecorate[domainIndex]) > -1 && links[linkIndex].href.indexOf("#") === -1)

because it would decorate internal links in the page for example to activate the mobile menu

    Julius Fedorovicius
    • Oct 12 2020
    • Reply

    Good catch! I totally did not think about href with just #. I've updated the code.

    Thanks!

Akki
  • Oct 13 2020
  • Reply

How can we track with hash link i.e some link has example.com/#our-services

but these url are not tracking the same.

Jake
  • Oct 20 2020
  • Reply

I also want to use this solution for attributing affiliate conversions in Google Ads. However, wouldn't I need to also have the Google Analytics code on the second domain (appstore.com)?

David
  • Oct 23 2020
  • Reply

Thank you for the script Julius.

I have a few questions.
Does it work with subdomains?
Do I need to have that in the domain list at the top or just the root domain?

And I am linking to a checkout page where my links have variants.
store.mysite.com/product/product-name?variant_id=1234567

These links are not getting updated.

Thanks

Alex
  • Oct 24 2020
  • Reply

Hello Julius,

Thanks for this method, I tried with a URL where all UTM params were named test. Then I landed on my main domain www.example.com with the UTM it was getting stored in GA

When I clicked on the button it navigated to my subdomain blog.example.com along with the UTM parameters.

However, all the traffic is going to direct/none not the source or medium and the campaign is getting captured in GA. Because when I check the report I a not seeing any source /medium with name as test

What could be possibly wrong?? I am getting UTM parameters when I navigate but in GA it is not getting captured.

Any suggestion!!!

Christopher Becker
  • Nov 5 2020
  • Reply

Julius Fedorovicius,
I have implemented the most up to date version of the custom HTML. two problems have surfaced:
1. The URL generated is using encoding for all punctuation, how can I get around this?
2. The custom HTML is appending to more than just the two external links I coded, how can I limit this?

output of UTMs on external domain
%3Futm_campaign%3DFUN%26utm_medium%3DIS%26utm_source%3DThis

weirder yet is that the external link I didnt ask for to be UTM appended actually read
&utm_campaign=FUN&utm_medium=IS&utm_source=This.

Please help me fix the two problems, if possible.
thanks
chris

Erik Tiemann
  • Dec 1 2020
  • Reply

Hi!
I need to pass the utm tags on to all the pages on the same domain, can this solution work for that?
Because i have a form that collects that data (via hidden field), so we can know wich constumer came from wich channel, but i still get a lot of "blanks" or direct conversions.
I'll appreciate the help, thanks!!

    Stephen Stouffer
    • Dec 1 2020
    • Reply

    Yup! This will solve that problem for you. Just remember though, The form they fill out might not be the form / page they entered on. So you'll need to account for that in your reporting.

Hasan
  • Dec 21 2020
  • Reply

Hi Julius,

thanks for this code. We've been using it for a month. However after analyzing Google Analytics data, some of the sessions don't pass queries. We thought it's because GTM loads the tag slow. that's why we injected the code before tag via a wordpress plugin. It works but it duplicates every parameter in the query. We made sure we paused the GTM tag. We don't know why it happens and thought maybe you have a solution/idea for it.

Thanks.

AW
  • Dec 23 2020
  • Reply

Hi Julius,
Been using your code for about a month now passing utm_source, utm_medium, etc. All is well, except:
"Advanced Search on site".

One of our pages has a advanced search feature. When a user selects his search requirements and clicks on search, the advanced search appends its own queries related to our website product and url changes to domain.com/page/?dimension1=2&dimension2=4

So we loose all queries passed through your code (i.e. utm_source, utm_medium, etc..)

Any ideas how to rectify?

Thanks/ AW.

Heiman
  • Dec 29 2020
  • Reply

Hi Julius!

That's a great workaround. Here's one scenario I noticed where the script doesn't work:

User lands on a page with the UTM parameters > Clicks on an internal link on that page > on this second page clicks on a URL that is supposed to be decorated.

As UTMs don't get passed on internally in the URL that probably causes this. And I assume it wouldn't make any sense to implement it internally either?

Best regards,
Heiman

    Julius
    • Dec 29 2020
    • Reply

    Hi, The script was never meant to persist the data across the pages. You will have to use cookies to enhance the solution by yourself.

Amer Salgado Berzunza
  • Jan 7 2021
  • Reply

Hi Julius.

I found your article very useful and I would like to share the following snippet that allowed me to dynamically obtain all the query parameters.

function getParams() {
var params = [],
searchParams = new URLSearchParams(window.location.search.slice(1));

for(var pair of searchParams.entries()) {
params.push(pair[0]);
}

return params;
}

Best regards,
Amer

victor
  • Jan 16 2021
  • Reply

First of all, i will like to thanks you for this post, I followed the steps and finally i thought can work, but it only work in preview and debug mode. I don't know the reason why it only works in preview and debug mode but not working in actual.

anyway, i found a quick solution by a wordpress plugin (UTMs Carry Pages)
it will only carry UMT, if other reference, you might need self edit the plugin

    Julius
    • Jan 16 2021
    • Reply

    If something works only in tpreview mode, it means that you have to publish your changes

      George Todoris
      • Jan 9 2023
      • Reply

      Hi Julius,
      it sometimes works and sometimes not, both preview and live. the changes are published but in only works one time out of 3-4 refreshes

Mark
  • Jan 22 2021
  • Reply

Really good, well explained information. Thank you.

Ben
  • Feb 1 2021
  • Reply

Hi Julius,
Thanks a lot for these very helpful instructions!

I have one follow-up question as I have a special use case:
It generally works now on my page but I have outgoing links that are not clearly visible to the script because they are contained in a Woomcommerce button (like an add-to-cart button but for outgoing links). So the script wasn't able to detect them and add the parameters to the links in these buttons.
Do you have an idea how I could modify the script to also look into these buttons to change links?
Kind regards,
Ben

Adam
  • Mar 1 2021
  • Reply

I was debugging the page in question with google tag manager and I can see the UTMs being appended to the link in the browser but when I get to the new page the information gets lost. Unfortunately, the checkout page that i'm directed to can't have GTM. Only the direct integration with GA...

Can you help?

Thank you,
Adam

    Julius Fedorovicius
    • Mar 1 2021
    • Reply

    Sounds like that website is losing the UTMs so my guess would be for you to talk with a developer of that website and ask to persist those UTMs in the URL.

Dmitry Z
  • Jul 18 2021
  • Reply

Hi Julius, I finally found what seems to be a solution, I just need a little help to finalize it.

My scenario: Pre-Landing page with 1 button leading to the main website. I need the UTMs to be transferred to the main website. Your solution should be a perfect match.

I create the tag but it doesn't transfer the UTMs, do I need to set up Cross-Domain in Analytics? Do I need to set up cookies?

    Julius Fedorovicius
    • Jul 19 2021
    • Reply

    If this does not work, then maybe you are dealing NOT with links but with other HTML elements. Or maybe redirect is dropping the URL parameters. You do not need to configure cross domain tracking or cookies

Shefeeq Abubakr
  • Sep 21 2021
  • Reply

Hi Julius.
Can I pass the parameter from my landing page to thank-you page using this method?

Even though Both the landing page and thank-you page is from same domain, There is a intervention of pages.razorpay.com to complete a payment. Razorpay allows only to implement GAU by just pasting its GAU id. I couldn't see more control without diving into deeper. There are some API and development related documentation but that is not for me right now. Razorpay allows to track some standard events like Purchases, AddToCart, InitiateCheckout and also PageView event by default but only for Facebook. Currently Razorpay is not supporting GTM.

Thank-you page view is my conversion with some trigger condition:
1. Page URL Contains mylandingpage.com/signup
2. Page Referrer Contains pages.razorpay.com

I can see these conversions in GAU reports but not on the basis of campaign name. I can only see the pages.razorpay.com as source in GAU reports.

Here is my user journey if above explanation is not clear:
User lands on mylandingpage.com/signup > then user click on a button which leads to pages.razorpay.com/earlybirdoffer > when user completes payment then redirected to mylandingpage.com/thank-you.

What would you suggest to do in this case.?
Thank you for your awesome works.

David
  • Oct 7 2021
  • Reply

Hi Julius,

This is very useful, thank you.

I noticed that when I leave the orignal landing page, UTM parameters get duplicated (i.e."?utm_source=referrer&utm_campaign=tony&utm_source=referrer&utm_campaign=tony&utm_source=referrer&utm_campaign=tony")

Why does this happen?

    Julius Fedorovicius
    • Oct 8 2021
    • Reply

    Hard to tell, maybe something is misconfigured or maybe there is some edge case you're dealing with

      David
      • Oct 8 2021
      • Reply

      I found the problem. In the domain section of the script, I added different pages from the same website (not realizing that if it's the same domain, there's no need to add all the URLs there).

      It now works perfectly.

Marcus Farias
  • Oct 12 2021
  • Reply

Hi Julius, how are you? Thanks for sharing this code, it was very helpful.

In my case, we direct the users to a page where they need to click on a CTA that opens a lightbox and then select on this lightbox the products that they are looking for, summarising users have click in 2 elements in order to get to the final URL.

Do you have any tips to tweak the code in order to get this code to work on this condition?

    Julius Fedorovicius
    • Oct 13 2021
    • Reply

    This would require involving developers and asking them to build a similar solution tailored to your situation

Paul Wampler
  • Nov 3 2021
  • Reply

Hi Julius,
Thank you for this code. It was just what I was needing. I implemented the code on https://www.cloud5.com and it's working if there are URL parameters -- utm_medium, utm_source, etc. -- but if there are no URL parameters, it's adding a '?' at the end of all links on the page.

I think I see how I can fix this in your code, but wondered if you had heard of this before and if you have a solution.

My fix would be to change the decorateUrl function to check if there are any URL params before adding a '?' or '#' to the URL:

function decorateUrl(urlToDecorate) {
var collectedQueryParams = [];
for (var queryIndex = 0; queryIndex 0) {
urlToDecorate = (urlToDecorate.indexOf('?') === -1) ? urlToDecorate + '?' : urlToDecorate + '&';
}
urlToDecorate = (urlToDecorate.indexOf('?') === -1) ? urlToDecorate + '?' : urlToDecorate + '&';
return urlToDecorate + collectedQueryParams.join('&');
}

    Julius Fedorovicius
    • Nov 5 2021
    • Reply

    Hi, that is because you implemented the trigger incorrectly. My code is not thinking of the missing URL parameters because the trigger is doing that. I fire the Custom HTML tag only if UTMs are in the URL.

Victoria Dodeva
  • Nov 22 2021
  • Reply

Hey Julius, that's a great post I often refer to. I have an issue implementing this on one website where it doesn't work (unlike many other websites we've implemented it on and it works like a charm)
Do you have any pointers about troubleshooting - website technology or any other conflict? Thank you!

    Julius Fedorovicius
    • Nov 24 2021
    • Reply

    Difficult to provide any solutions without seeing the actual situation and doing an audit

Milan Meurs
  • Nov 26 2021
  • Reply

Hi Julius,

Works like a charm for me!
The only thing I can't figure out is how to return my parameters without "utm_" in front of it.
So when the landing URL is incoming.com?utm_source=test
I would like to create the link outgoing.com?source=test
Would you be able to tell me how I can do this?

Kind regards,

Milan

Sudheer
  • Dec 9 2021
  • Reply

Hi,

I need one answer from you if any one is aware of this please let me know. How can we pass the single custom query parameters in the url like www.domain.com/?site_refer=test&gclid=test like this.

    Julius Fedorovicius
    • Dec 10 2021
    • Reply

    The same way you do with UTM parameters. Instead of a UTM parameter (that I show in this blog post), include another parameter.

Alain
  • Jan 16 2022
  • Reply

Hello Julius,

This is very helpful and very well detailed Thank you,
Only one question : does this work with subdomains ?

Thanks

    Julius Fedorovicius
    • Jan 26 2022
    • Reply

    GA handles UTMs between subdomains by default

John
  • Mar 8 2022
  • Reply

Hi Julius, nice work!
If we already have links with variables the script didn't append / decorate with UTMs.

Example of an incoming url:
website.com/landingpage?utm_campaign=test

in the landing page we have a button with this link:
anotherwebsite.com/landingpage?id=123&brand=1234

So the script didn't append this existing link to this one:
anotherwebsite.com/landingpage?id=123&brand=1234&utm_campaign=test

Any workaround this?
Thank you!

Kolton Mero
  • Mar 17 2022
  • Reply

Hi Julius,

This is a great article but I seem to be running into an issue.

Trying to get UTM's to track over when sending users to this page - https://www.azgolfassociation.com/under-30/?utm_source=test&utm_medium=test and clicking on the CTA 'Learn More' or 'Sign Up' which takes them to this page - https://www.azgolf.org/join-the-arizona-golf-association/join/?cid=7770

Implemented the code exactly as outlined and changed the domain to azgolf.org but when testing out it doesn't seem to work.

Is this due to all the other stuff at the end of the URL? Or did I edit the code incorrectly? Would be awesome to get your feedback. Thank you!

<script>
(function() {
var domainsToDecorate = [
'azgolf.org', //add or remove domains (without https or trailing slash)
],
queryParams = [
'utm_medium', //add or remove query parameters you want to transfer
'utm_source',
'utm_campaign'
]
// do not edit anything below this line
var links = document.querySelectorAll('a');

// check if links contain domain from the domainsToDecorate array and then decorates
for (var linkIndex = 0; linkIndex < links.length; linkIndex++) {
for (var domainIndex = 0; domainIndex < domainsToDecorate.length; domainIndex++) {
if (links[linkIndex].href.indexOf(domainsToDecorate[domainIndex]) > -1 && links[linkIndex].href.indexOf("#") === -1) {
links[linkIndex].href = decorateUrl(links[linkIndex].href);
}
}
}
// decorates the URL with query params
function decorateUrl(urlToDecorate) {
urlToDecorate = (urlToDecorate.indexOf('?') === -1) ? urlToDecorate + '?' : urlToDecorate + '&';
var collectedQueryParams = [];
for (var queryIndex = 0; queryIndex < queryParams.length; queryIndex++) {
if (getQueryParam(queryParams[queryIndex])) {
collectedQueryParams.push(queryParams[queryIndex] + '=' + getQueryParam(queryParams[queryIndex]))
}
}
return urlToDecorate + collectedQueryParams.join('&');
}

// borrowed from https://stackoverflow.com/questions/831030/
// a function that retrieves the value of a query parameter
function getQueryParam(name) {
if (name = (new RegExp('[?&]' + encodeURIComponent(name) + '=([^&]*)')).exec(window.location.search))
return decodeURIComponent(name[1]);
}

})();
</script>

Bruno Santucci
  • Apr 5 2022
  • Reply

Hey there!

Is it possible to insert this code on a Wordpress page?

Great content, by the way! Will definitely buy your course in the future.

Thanks!

    Julius Fedorovicius
    • Apr 13 2022
    • Reply

    Simple copy paste will probably not work because you need to wait for this code to be fired when the website DOM is loaded. And that requires customization. So use GTM.

Ryan
  • May 27 2022
  • Reply

Hi Julius,

Would it be possible to use version 1 & version 2 for the same website? My website has a need to send utm data to a new domain but it also has a need to track utm data across pages (which do involve #urls).

I would like to use version 2 to track products purchased on the site (through shopify) and version 1 to track products that require an application process (form download).

Thanks for your work

Nicolás
  • May 28 2022
  • Reply

Julius, first THANKS for the article. It helped a lot.

Second: I have a new use case that I believe something similar would help.

Problem: I got many article in my blog linking to mi site (example.com/blog/article >> example.com).

I would like to add massively UTM parameters to all this links so I know a certain lead came from the blog.

This UTM could be fixed for all links or maybe add the blog/article url

Do you you imagine something similar could be accomplished?

Thanks for your help

    Julius Fedorovicius
    • Jun 3 2022
    • Reply

    Everything you have belong to the *same domain*. You don't need to persist UTMs in the links. GA will properly track UTMs without this.

Neha
  • May 30 2022
  • Reply

In the given script if I add FromSource and then I modify the trigger to include it as well utm_medium=|utm_source=|utm_campaign=|utm_content=|utm_term=|FromSource
Will it transfer this custom URL parameter. So far I tried and it didn't work.

queryParams = [
'utm_medium',
'utm_source',
'utm_campaign',
'utm_content',
'utm_term',
'FromSource'
]

Alex
  • Jul 30 2022
  • Reply

Hello Julius,
1st of, this is a great content and development of you! Many Thanks!!!
2nd I'm trying to add also Tracking URL Parameters ID from Affiliate Platforms to forward those within the URL (landing page > pre-sales page > hop offer page), but unfortunately it is not working. Even within own domain transfer (landing page > pre-sales page) the corresponding tracking ID's are not forwarded in the URL. It seems that the script is not providing such a forward.

Are you able to ajdust the script to enable not only UTM Parameters?

queryParams = [
'utm_id', //add or remove query parameters you want to transfer
'utm_medium',
'utm_source',
'utm_campaign',
'utm_term',
'utm_content',
'utm_source_platformis', //add or remove NEW query parameters
'utm_creative_format',
'utm_marketing_tactic',
'tid', //add or remove Affiliate Traffic ID query parameters
'ds24tr',
'cam'
]

Best regards, Alex

    Julius Fedorovicius
    • Aug 1 2022
    • Reply

    The script already supports any URL parameter

Jonathan
  • Aug 25 2022
  • Reply

Hey Julius,
One issue we have had is that the DOM Ready actually doesn't fire at all. To counter this, I set the trigger to view on page views (with the same filters), it works but it is causing broken links throughout the site. Ex: user comes to site.com?utm_source=source and when they visit the next page, it is now site.com?utm_source=source?utm_source=source.

Do you know what could be causing DOM Ready to not fire/ any potential workarounds for it?

Rotem
  • Sep 12 2022
  • Reply

Hi Julius,
I implemented the tag and it seems to work only when I move forward to a different domain.
If I click on a link in the landing page which is directing to a page in the same domain, I do not see the UTM parameters in the URL.

Also, if I go to another page in the 2nd domain, it doesn;t forward the UTMs.
Is there a way to solve it?

    Julius Fedorovicius
    • Sep 22 2022
    • Reply

    Include both domains in the Custom HTML tag

      Rotem
      • Oct 2 2022
      • Reply

      Hi,
      I included both domains in the HTML tag.
      The problem is still on the same domain.
      1) Landing page: Domain1.com/?utm_source=test&utm_medium=display&utm_campaign=test1&utm_content=testfromhome
      2) Click on CTA: Domain2.com/?utm_source=test&utm_medium=display&utm_campaign=test1&utm_content=testfromhome
      3) Click on navigation Domain2.com/page (no UTMs)

Aurélien
  • Sep 13 2022
  • Reply

Works beautifully! Thank you for sharing and explaining!

Povilas
  • Oct 1 2022
  • Reply

Thanks, Julius! Veikia puikiai!

Sean
  • Oct 6 2022
  • Reply

Julius,

I recognize this post is a little yesterday, but I want to thank you for putting together this tutorial. It was extremely educational and easy to implement.

Much obliged,
Sean

Nate Schwarz
  • Oct 20 2022
  • Reply

Hi Julius,

I'm working on setting up tracking from Facebook Ads and the user path is Facebook Ad With UTM Link > Consumer Site > Third Party Online Ordering Site so I think this will work. The only question I have is when I specify a domain to decorate, will any link containing that domain being "decorated" or do I have specify every single link?

For example, the Consumer Site has both general links (onlineorderingsite.com) and specific links (onlineordersite.com/location1). Will both have the UTM parameters added since they both go to the same domain?

    Julius Fedorovicius
    • Oct 26 2022
    • Reply

    Every link of that website will be decorated

Colleen Klein
  • Nov 7 2022
  • Reply

Hi Julius, is this a viable solution for GA4? We have a client that sends an email campaign out that directs clients to site A (one GA4 property), but then they make the purchase on site B (separate GA4 property). They want the email campaign to be recognized, but currently, in GA4, the purchase shows the session campaign as (referral) and the session source/medium as (web address for site A)/referral. We implemented the above (we do have cross domain tracking enabled but I understand that seems to only work if they are all under the same measurement ID) but now session campaign and session source/medium are coming in as (not set). Thanks for the help!

Sean
  • Nov 16 2022
  • Reply

Hi Julius - this is fantastic. This is solving part of my problem but I have a question for you. Right now I have the persist campaign tag set up in GTM to store my UTM variables in a 1st party cookie so this information is not lost when a user goes from page to page.

Am I able to create a tag/trigger that can pull from that 1st party cookie variable and append the UTMs to my other site's URL? Basically, can I decorate my link with UTMs stored in my 1st party cookie variable? Thank you!

Yusuf
  • Dec 5 2022
  • Reply

Hi Julius, thanks for that :) It works but I've the issue that I get the same parameters twice in the destination URL. Looks like: websiteb.com&?utm_source=example&utm_source=example&utm_campaign=same%20example&utm_campaign=same%20example&utm_source=adwords&utm_source=adwords ... and so on. How can I fix this? Every parameter is appearing twice.

Thanks in advance!

Dejan
  • Dec 11 2022
  • Reply

Should I expect the same results, if I add exactly the same script to my Unbounce script manager?

I have searched all over the internet, you are one of the few who really described this topic in detail, thank you.

Leave a comment Cancel reply

Your email address will not be published. Required fields are marked *

 

Hi, I'm Julius Fedorovicius and I'm here to help you learn Google Tag Manager and Google Analytics. Join thousands of other digital marketers and digital analysts in this exciting journey. Read more
Analytics Mania
  • Google Tag Manager Courses
  • Google Tag Manager Recipes
  • Google Tag Manager Resources
  • Google Tag Manager Community
  • Login to courses
Follow Analytics Mania
  • Subscribe to newsletter
Recent Posts
  • Cannot See the Google Tag Manager Option in Google Ads Conversion?
  • Google Ads Conversion Tracking with Google Tag Manager
  • Google Tag Manager Tutorial + Video & Free E-Book for Beginners
Analytics Mania - Google Tag Manager and Google Analytics Blog | Privacy Policy
Manage Cookie Settings