Intro

Recently I needed to modify all the links in my blog to add a query string parameter. As you can imagine, this is a lot of work, and developers are very lazy people. We prefer to spend a few hours tweaking a script that will do whatever we need instead of manually doing it (even if it takes less time).

Fortunately, the blog engine I use allows to inject javascript on each page easily, so let's get to it.

var querystring = '?WT.mc_id=DOP-MVP-5003880';
$('a').each(function() {
    var href = $(this).attr('href');
    if (href) {
      $(this).attr('href', href + querystring);
    }
});

Requires JQuery

Not so fast

I coded that script in 5 minutes, and though I was done with it. God, I was wrong. I wanted to go so fast I overlooked many test cases and broke some pages on the first deploy.

Fortunately, I have a dev environment where I always test first, before going live in prod with a change.

This script only works for straightforward scenarios. What if the link already contains a query? Well, the script will append a second ? which obviously will cause issues.

<a href="https://www.google.ca/search?q=test">link with query string</a>

Will result in https://www.google.ca/search?q=test?WT.mc_id=DOP-MVP-5003880, definitely not what we want.

There are many ways to validate if there's already a query string present in a URL. However, they often require a lot of javascript and string manipulation through regex to achieve the desired outcome. Moreover, you'll find soon enough that these scripts don't correctly support URL fragments # most of the time.

Keep it simple

Fortunately, there's a way to keep it simple and avoid writing 100 lines of javascript just to rewrite some URLs. We'll use the built-in URL object and let it do the heavy lifting for us.

$('a').each(function() {
    var href = $(this).attr('href');
    if (href) {
        var url = new URL(href);
        url.searchParams.set("WT.mc_id", "DOP-MVP-5003880");
        $(this).attr('href', url.href);
    }
});

Test cases

<a href="http://google.ca">absoluteLink</a>
<a href="https://www.google.ca/search?q=test">link with query string</a>
<a href="http://google.ca#something">link with fragment</a>

Results

https://www.google.ca/?WT.mc_id=DOP-MVP-5003880
https://www.google.ca/search?q=test&WT.mc_id=DOP-MVP-5003880
https://www.google.ca/?WT.mc_id=DOP-MVP-5003880#something

Notice that the URL fragment moved AFTER the query string, which is essential if you don't want to make the browser crash.

Final version

There's some other nice to have that we should add to make it a bit better. First, the URL object doesn't like relative URLs so let's make sure we have a try/catch to avoid polluting the console with errors we don't care about.

It could also be interesting only to rewrite specific links.
Eg. In my case, I only want to rewrite links than point outside of my blog and filter out everything that is part of my domain *.miguelbernard.com.

$('a').each(function() {
    var href = $(this).attr('href');
    if (href) {
        try {
            var url = new URL(href);
            var regex = /.*miguelbernard.com/;
            if(!url.hostname.match(regex))
            {
                url.searchParams.set("WT.mc_id", "DOP-MVP-5003880");
                $(this).attr('href', url.href);
            }
        }
        catch{}
    }
});

Final word

Here you go, a simple and elegant solution to a simple problem. It's hard to believe that you won't find this trick before a few pages if you search on google/bing. Help others find this trick by sharing this article.