Search code examples
javascriptgoogle-chromegoogle-chrome-extensionwebrequest

Chrome Extension: when being directed to a new page, replace assorted URL parameters with a different value before the URL request gets sent off


When I click I a link (or am getting redirected by a site), I want to replace the values of assorted tracking parameters in the requested URL with a different, universal value. For this example, let's use my username, so a link that directs to

www.abc.com/?utm_source=originalsource&utm_campaign=originalcampaign&cid=originalcid&gclid=originalgclid

would become www.abc.com/?utm_source=WTTDOTM&utm_campaign=WTTDOTMcampaign&cid=WTTDOTM&gclid=WTTDOTM

It’s important that these parameters get edited before the request is sent off, as the idea is to avoid the UTM/cid/gclid/etc tracking and leave a mark in the traffic data of whoever is looking at those tracking parameters. I know I have to use webRequest, and the logic seems pretty simple, but I don’t know how to find-and-replace in the URL on the fly with js. This answer looks like its the closest to what I’m asking, but I don’t know how it would work with just modifying smaller slices of a URL as I'm pretty inexperienced with javascript and most of my coding knowledge is just slapping stuff together until it works.

To start with a simple sub-problem my question is: how can I use the webRequest API to replace utm_campaign=*** in a URL with utm_campaign=WTTDOTM before the page is requested?

----EDIT:-----

@wOxxOm thank you for your helpful answer! I think I have the general structure down now, but I am still struggling with the formatting of regex rules, which I'm pretty unfamiliar with. The way I understand it, the rule ^(.*?utm_source=)(.+?(?=\\&)|$)(.*) (and its "medium" variant) will capture all values before 'utm_source=' into group 1 and all values (or none in the case of it being the last parameter) after '&' into group 3 and then I should be able to make the regexSubstition group1+WTTDOTM+group3, right? When I currently try to upload the unpacked extension below, I get hit with an error that says "rules.json: Rule with id 1 specifies an incorrect value for the "regexFilter" key." I think I am just formatting it wrong, but I do not know what I need to fix. Can you help? Here are my rules.json and manifest.json files.

rules.json

[
{
    "id": 1,
    "priority": 1,
    "action": {
      "type": "redirect",
      "redirect": {
        "regexSubstitution": "\\1WTTDOTM\\3"
      }
    },
    "condition": {
      "regexFilter": "^(.*?utm_source=)(.+?(?=\\&)|$)(.*)",
      "resourceTypes": [
        "main_frame"
      ]
    }
  },
{
    "id": 2,
    "priority": 2,
    "action": {
      "type": "redirect",
      "redirect": {
        "regexSubstitution": "\\1WTTDOTM\\3"
      }
    },
    "condition": {
      "regexFilter": "^(.*?utm_medium=)(.+?(?=\\&)|$)(.*)",
      "resourceTypes": [
        "main_frame"
      ]
    }
  }
]

manifest.json

{
    "manifest_version": 2,
    "name": "WTTDOTM is a UTM",
    "version": "1.3",
    "permissions": [
    "declarativeNetRequest",
    "declarativeNetRequestFeedback",
    "<all_urls>"
],
    "description": "Replaces all UTM values with 'WTTDOTM'",
     "declarative_net_request" : {
    "rule_resources" : [{
      "id": "1",
      "enabled": true,
      "path": "rules.json"
    },
    {
      "id": "2",
      "enabled": true,
      "path": "rules.json"
    }],
    "icons": {
          "128": "icon128.png" }
 }
}

Solution

  • It's probably not impossible to do this with regular expressions but it's going to be frustrating. The text that you're trying to capture could contain almost anything, so building a regex that captures what's after each query parameter and only what's after each query parameter is going to be difficult. Instead I would suggest using Chrome's built in URLSearchParams API.

    Combined with Javascript's URL object, what you're trying to do would probably look like this:

    const replaceTrackerParams = (urlString, replacementString) => {
      const url = new URL(urlString);
      const params = new URLSearchParams(url.search);
    
      // If campagin parameters exist, replace them
      params.has('utm_source') && params.set('utm_source', replacementString)
      params.has('utm_campaign') && params.set('utm_campaign', replacementString)
    
      // Return modified URL
      return url.hostname + '?' + params.toString() 
    }
    

    Replace shorthand syntax with more complicated logic as needed.

    Another answer suggested using declarativeNetRequest because it is the newer, more efficient API. This is true, but I don't think it supports callback functions yet.