javascriptgoogle-tag-managerutm

What is the bug in my Persistent UTM Code?


I am using the following code to persist utms across my website. However i notice that its adding a question mark to links even without the UTM parameters. Can someone help me figure out what in this code needs to change. It should only be trying to add UTM parameters to the links if there is one present in the URL.

 <script>
(function() {
  var domainsToDecorate = [
          'example.com'
      ],
      queryParams = [
          'utm_medium', //add or remove query parameters you want to transfer
          'utm_source',
          'utm_campaign',
          'utm_content',
          'utm_term'
      ]
  // 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('&');
  }


  // 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>

Solution

  • In decorateUrl you are adding the ? if there is not one

    urlToDecorate = (urlToDecorate.indexOf('?') === -1) ? urlToDecorate + '?' : urlToDecorate + '&';
    

    I would suggest you may only want to do this if collectedQueryParams contains any elements

     function decorateUrl(urlToDecorate) {
          var collectedQueryParams = [];
          for (var queryIndex = 0; queryIndex < queryParams.length; queryIndex++) {
              if (getQueryParam(queryParams[queryIndex])) {
                  collectedQueryParams.push(queryParams[queryIndex] + '=' + getQueryParam(queryParams[queryIndex]))
              }
          }
    
          if(collectedQueryParams.length == 0){
            return urlToDecorate;
          }
    
          //only add the ? if we have params AND if there isn't already one
          urlToDecorate = (urlToDecorate.indexOf('?') === -1) ? urlToDecorate + '?' : urlToDecorate + '&';
          return urlToDecorate + collectedQueryParams.join('&');
      }