Link to home
Start Free TrialLog in
Avatar of Heather Ritchey
Heather RitcheyFlag for United States of America

asked on

Remove url query string if parameter is empty (undefined)

This looks for a query string in the initial visit to the site if the person came from an ad (ppc) and makes sure that it stays for the rest of the site visit. How do I keep the query part from showing if they didn't come from an ad (visited the site directly)?


<script type="text/javascript">
function getAllUrlParams(url) {

  // get query string from url (optional) or window
  var queryString = url ? url.split('?')[1] : window.location.search.slice(1);

  // we'll store the parameters here
  var obj = {};

  // if query string exists
  if (queryString) {

    // stuff after # is not part of query string, so get rid of it
    queryString = queryString.split('#')[0];

    // split our query string into its component parts
    var arr = queryString.split('&');

    for (var i = 0; i < arr.length; i++) {
      // separate the keys and the values
      var a = arr[i].split('=');

      // set parameter name and value (use 'true' if empty)
      var paramName = a[0];
      var paramValue = typeof (a[1]) === 'undefined' ? true : a[1];

      // (optional) keep case consistent
      paramName = paramName.toLowerCase();
      if (typeof paramValue === 'string') paramValue = paramValue.toLowerCase();

      // if the paramName ends with square brackets, e.g. colors[] or colors[2]
      if (paramName.match(/\[(\d+)?\]$/)) {

        // create key if it doesn't exist
        var key = paramName.replace(/\[(\d+)?\]/, '');
        if (!obj[key]) obj[key] = [];

        // if it's an indexed array e.g. colors[2]
        if (paramName.match(/\[\d+\]$/)) {
          // get the index value and add the entry at the appropriate position
          var index = /\[(\d+)\]/.exec(paramName)[1];
          obj[key][index] = paramValue;
        } else {
          // otherwise add the value to the end of the array
          obj[key].push(paramValue);
        }
      } else {
        // we're dealing with a string
        if (!obj[paramName]) {
          // if it doesn't exist, create property
          obj[paramName] = paramValue;
        } else if (obj[paramName] && typeof obj[paramName] === 'string'){
          // if property does exist and it's a string, convert it to an array
          obj[paramName] = [obj[paramName]];
          obj[paramName].push(paramValue);
        } else {
          // otherwise add the property
          obj[paramName].push(paramValue);
        }
      }
    }
  }

  return obj;
}

 (function() {
 var utmInheritingDomain = "homecomfortalliance.com", // REPLACE THIS DOMAIN (DO NOT INCLUDE HTTPS)
 utmRegExp = /(\&|\?)utm_[A-Za-z]+=[A-Za-z0-9]+/gi,
 links = document.getElementsByTagName("a"),
 utms = [
 "utm_medium=" + getAllUrlParams().utm_medium, // IN GTM, CREATE A URL VARIABLE utm_medium
 "utm_source=" + getAllUrlParams().utm_source, // IN GTM, CREATE A URL VARIABLE utm_source
 "utm_campaign=" + getAllUrlParams().utm_campaign // IN GTM, CREATE A URL VARIABLE utm_campaign
 ];
 
 for (var index = 0; index < links.length; index += 1) {
 var tempLink = links[index].href,
 tempParts;

 if (tempLink.indexOf(utmInheritingDomain) > 0) { // The script is looking for all links with the utmInheritingDomain
 tempLink = tempLink.replace(utmRegExp, "");

 tempParts = tempLink.split("#");

 if (tempParts[0].indexOf("?") < 0 ) {
 tempParts[0] += "?" + utms.join("&"); // The script adds UTM parameters to all links with the domain you've defined
 } else {
 tempParts[0] += "&" + utms.join("&");
 }

 tempLink = tempParts.join("#");
 }

 links[index].href = tempLink;
 }
 }());
</script>

Open in new window

Ex: https://homecomfortalliance.com/commercial-electrical-services/?utm_medium=undefined&utm_source=undefined&utm_campaign=undefined

Those are undefined - I don't want the ?query showing on the end.

This has all parameters, so I want it to stay throughout clicking around the site:

https://homecomfortalliance.com/?utm_source=ppc&utm_medium=displayad&utm_campaign=springsale

ASKER CERTIFIED SOLUTION
Avatar of Noah
Noah
Flag of Singapore image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Heather Ritchey

ASKER

@Noah 

That definitely worked! I'm getting a ? when there aren't any parameters (no query string). Can you tell where that is coming from?

If there are no existing query parameters in the URL, the code adds a ? before appending the UTM parameters.

Here is an updated code that avoids this.

<script type="text/javascript">
  // Function to parse query parameters from the URL
  function getAllUrlParams(url) {
    // Get query string from URL (optional) or window
    var queryString = url ? url.split('?')[1] : window.location.search.slice(1);

    // Store the parameters here
    var obj = {};

    // If query string exists
    if (queryString) {
      // Remove anything after '#' as it is not part of the query string
      queryString = queryString.split('#')[0];

      // Split the query string into its component parts
      var arr = queryString.split('&');

      for (var i = 0; i < arr.length; i++) {
        // Separate the keys and values
        var a = arr[i].split('=');

        // Set parameter name and value (use 'true' if empty)
        var paramName = a[0];
        var paramValue = typeof a[1] === 'undefined' ? true : a[1];

        // Keep the case consistent (optional)
        paramName = paramName.toLowerCase();
        if (typeof paramValue === 'string') paramValue = paramValue.toLowerCase();

        // If the paramName ends with square brackets, e.g., colors[] or colors[2]
        if (paramName.match(/\[(\d+)?\]$/)) {
          // Create key if it doesn't exist
          var key = paramName.replace(/\[(\d+)?\]/, '');
          if (!obj[key]) obj[key] = [];

          // If it's an indexed array, e.g., colors[2]
          if (paramName.match(/\[\d+\]$/)) {
            // Get the index value and add the entry at the appropriate position
            var index = /\[(\d+)\]/.exec(paramName)[1];
            obj[key][index] = paramValue;
          } else {
            // Otherwise, add the value to the end of the array
            obj[key].push(paramValue);
          }
        } else {
          // We're dealing with a string
          if (!obj[paramName]) {
            // If it doesn't exist, create the property
            obj[paramName] = paramValue;
          } else if (obj[paramName] && typeof obj[paramName] === 'string') {
            // If the property exists and it's a string, convert it to an array
            obj[paramName] = [obj[paramName]];
            obj[paramName].push(paramValue);
          } else {
            // Otherwise, add the property
            obj[paramName].push(paramValue);
          }
        }
      }
    }
    return obj;
  }

  // Immediately-invoked function expression (IIFE)
  (function () {
    // Replace this domain (do not include 'https://')
    var utmInheritingDomain = 'homecomfortalliance.com';

    // Regular expression to match UTM parameters in the URL
    var utmRegExp = /(\&|\?)utm_[A-Za-z]+=[A-Za-z0-9]+/gi;

    // Get all anchor elements on the page
    var links = document.getElementsByTagName('a');

    // Get the UTM parameters from the current URL
    var utmParams = getAllUrlParams();
    var utms = [];
    if (utmParams.utm_medium && utmParams.utm_source && utmParams.utm_campaign) {
      utms = [
        'utm_medium=' + utmParams.utm_medium,
        'utm_source=' + utmParams.utm_source,
        'utm_campaign=' + utmParams.utm_campaign
      ];
    }

    // Iterate through each anchor element
    for (var index = 0; index < links.length; index++) {
      var link = links[index];
      var href = link.getAttribute('href');

      // Check if the href attribute exists and contains the target domain
      if (href && href.indexOf(utmInheritingDomain) > -1) {
        if (utmRegExp.test(href)) {
          // Remove existing UTM parameters from the href
          href = href.replace(utmRegExp, '');
        }

        // Append UTM parameters to the href
        if (utms.length > 0) {
          // Check if there are existing query parameters in the href
          if (href.indexOf('?') > -1) {
            // Append UTM parameters with '&' only if there are existing query parameters
            href += '&' + utms.join('&');
          } else {
            // Append UTM parameters directly without '?'
            href += utms.join('&');
          }

          // Update the href attribute with the modified URL
          link.setAttribute('href', href);
        }
      }
    }
  })();
</script>

Open in new window

That removed the ? also with the query once you click another page link (same site), but I can't tell where it's doing that.

Here is a much shorter script. It works when run. If another page or part of the site adds the parameters again, you will need to address that in another manner

https://jsfiddle.net/mplungjan/0a17uxey/

const keys = ["utm_medium", "utm_source", "utm_campaign"];
const removeSearchIfEmpty = uri => {
  const url = new URL(uri);
  let urlComplete = keys.every(key => {
    const parm = url.searchParams.get(key)?.trim();
    return parm.length > 0 && parm !== "undefined"
  })
  console.log(urlComplete);
  return urlComplete ? uri : url.toString().split("?")[0];
};

// tests
const urls = ["https://homecomfortalliance.com/commercial-electrical-services/?utm_medium=undefined&utm_source=undefined&utm_campaign=undefined",
  "https://homecomfortalliance.com/?utm_source=ppc&utm_medium=displayad&utm_campaign=springsale"];

urls.forEach(url => console.log(removeSearchIfEmpty(url)))

Open in new window