Link Untracker

Remove tracking elements from links

< Feedback on Link Untracker

Question/comment

§
Posted: 2018-01-23
Edited: 2018-01-31

[SOLVED] Doesn't work

"purl.delete(b);" deletes only parameters with key 'b' but not parameters that starts with 'b'.

I wrote a simple test:

var ln = '?example=value&utm_campaign=email_digest';
var purl = new URLSearchParams(ln);
console.log('before1: ' + purl.toString());
for (let b of badp) { purl.delete(b); }
console.log('after1:  ' + purl.toString());

purl = new URLSearchParams(ln);
console.log('before2: ' + purl.toString());
for(var key of purl.keys()) { for (let b of badp) { if (key.startsWith(b)) { purl.delete(key); break; } } }
console.log('after2:  ' + purl.toString());

For me it produces this output in console:
before1: example=value&utm_campaign=email_digest
after1: example=value&utm_campaign=email_digest
before2: example=value&utm_campaign=email_digest
after2: example=value

After change deletion to second version script works fine.

I tested in Chrome/64.0.3282.97.

IzzySoftAuthor
§
Posted: 2018-01-23

Thanks for reporting, Danil! Strangely, it works for me as-is – and stops working if I apply your change. Might be a Chrome thing (dealing differently with it than Firefox/Waterfox).

As replacing my implementation by yours would break it on FF, we'd need a "switch" on UA (run your replacement for Chrome, my original for all else):

if (navigator.userAgent.indexOf("Chrome") !== -1){
  for(var key of purl.keys()) { for (let b of badp) { if (key.startsWith(b)) { purl.delete(key); break; } } }
} else {
  for (let b of badp) { purl.delete(b); }
}

Could you try if that works for you? I don't use Chrome, so I cannot check for myself.

§
Posted: 2018-01-23
Edited: 2018-01-23

Hi! Thanks for quick response.
Your code works for me: it correctly determines that I use Chrome-like browser and links are clear.
I don't understand why it works for you though. Documentation for URLSearchParams states that delete() removes just the item with this name, not with similar names.
I installed Firefox 58.0 and modified test.

var ln = '?utm_campaign=email_digest&utm_source=email_habrahabr&utm_medium=email_week_20180123&utm_content=link2post';
var purl = new URLSearchParams(ln);
purl.delete('utm_');
console.log('after1: ' + purl.toString());
console.log('--');
purl = new URLSearchParams(ln);
var tmp = purl.keys();
console.log(tmp.next());
console.log(tmp.next());
console.log('--');
tmp = purl.keys();
console.log(tmp.next());
console.log('delete: ' + purl.delete('utm_campaign'));
console.log(tmp.next());

First line is the same for me: it contains all the parameters in both FF and Chrome.
Second part of the test is different. The problem is: in Chrome "delete()" doesn't move iterator and in FF it does, so in FF my patch skips half of the parameters. I guess it can be bypassed by dividing search and removing of parameters.

Also I tested in Greasemonkey, Tampermonkey and Violentmonkey and while second and third works as expected, Greasemonkey gives me an exception that says that object returned by ".keys()" is not iterable on line with "for()" although I can iterate through it with "next()".

What exact browser and add-on do you use?
And what output produces following code for you?

var ln = '?utm_campaign=email_digest&utm_source=email_habrahabr&utm_medium=email_week_20180123&utm_content=link2post';
var purl = new URLSearchParams(ln);
for (let b of badp) { purl.delete(b); }
console.log('after1:  ' + purl.toString());
purl = new URLSearchParams(ln);
var keyToDelete = [];
for(var key of purl.keys()) { for (let b of badp) { if (key.startsWith(b)) { keyToDelete.push(key); break; } } }
for(var key of keyToDelete) { purl.delete(key); }
console.log('after2:  ' + purl.toString());
IzzySoftAuthor
§
Posted: 2018-01-28
Edited: 2018-01-28

Uh… Sorry for the delay, I got no notification that a comment had been made …

I'm using Firefox 55 on Linux (and Waterfox 56 on Windows at the office – I'm on my way to kick Firefox after being burned by Mozilla for the third time now; having used it since back when it was named Phoenix and had a 0.7 version number).

Now let's check the output of your code (doing that in the FF developer console here): I get an error at line 3 that badp is not defined ;) After copying that definition from my script, line 3 gives "undefined" – so the initial string is left untouched (as line 4 confirms).

Line 5 then gives a totally empty object. Fixing that up by replacing it with the first two lines, line 7 gives a "4", line 8 "undefined", and the last line gives "after2: undefined". The console itself shows:

after1:  utm_campaign=email_digest&utm_source=email_habrahabr&utm_medium=email_week_20180123&utm_content=link2post 
after2: 

I guess that is what you expected – and you see me totally confused as now I don't understand myself why it works for me in two browsers (and as the script was "upvoted" twice, it seems to work for at least 2 others as well). Something GreaseMonkey specific, maybe?

When I go to e.g. https://www.appbrain.com/app/com.widgapp.quicktile and hover my mouse over the "Google Play" button, I see none of the tracking parameters when using my variant of the script – but all of them when using yours.

PS: It looks like purl.keys() does not work properly in GreaseMonkey (note I still use the last pre-WebExt version as the WE version is too crippled for me). I've put

console.log('checking keys');
console.log(purl.toString());
for(let key of purl.keys()) { console.log(key); }

before the for (let b of badp) { purl.delete(b); } line in my script, and all I get on that AppBrain page is:

checking keys
id=com.widgapp.quicktile&referrer=utm_source%3Dappbrain%26utm_medium%3Dappbrain_web%26utm_campaign%3Dappbrain_web

No keys. In the FF console itself the keys are listed fine. That seems to match your finding of

Greasemonkey gives me an exception that says that object returned by ".keys()" is not iterable on line with "for()" although I can iterate through it with "next()".

So maybe we rather need a switch checking for GreaseMonkey instead of Chrome? Is there any (something like "functionexists('GMxxx')")?

PPS: Ouch. Just figured why it works for me on that test URL: the referrer parameter "contains" the UTM stuff there: id=com.widgapp.quicktile&referrer=utm_source%3Dappbrain%26utm_medium%3Dappbrain_web%26utm_campaign%3Dappbrain_web. Yuck. Any alternative to purl.keys() that might work in GreaseMonkey? purl.entries() doesn't seem to work either.

IzzySoftAuthor
§
Posted: 2018-01-28

OK, got it! Can you please verify? Replace for (let b of badp) { purl.delete(b); } in my script by

for(var pair of purl) {
  for(let b of badp) {
    if (pair[0].startsWith(b)) { purl.delete(pair[0]); break; }
  }
}

This works for me in FF with GreaseMonkey. Please let me know if it works in your candidates as well.

I'll test on Waterfox tomorrow if I find time. If it works there as well, I'll update the script here – as the current version doesn't work as expected anyway, so this change is an improvement already :wink:

Thanks for making me aware of that!

§
Posted: 2018-01-31
Edited: 2018-01-31

Sorry, I got busy too, and just read your answer. I saw script update but wasn't able to check it immediately and remembered about it just today.
I'm glad you figured out why we had different results. It's quite a tricky link with symbols-escaping.
Your solution in update 6 seems to work except for:

The problem is: in Chrome "delete()" doesn't move iterator and in FF it does, so in FF my patch skips half of the parameters.

FireFox still skips half of the parameters when removing elements while iterating :(
I guess I can post link here to ease checking: >test me<.
For me in Chrome current version of script fully removes parameters from this link but FF leaves 2 params untouched.
I can suggest to divide search and removing into different loops (but maybe there is better solutions). Like in my last example in previous post:

var keysToDelete = [];
for(var pair of purl) {
  for(let b of badp) {
    if (pair[0].startsWith(b)) {
      keysToDelete.push(pair[0]);
      break;
    }
  }
}
for(var key of keysToDelete) {
  purl.delete(key);
}
IzzySoftAuthor
§
Posted: 2018-01-31

Thanks for your feedback, Danil – and glad it (basically) works as expected now. Leaves room for improvements though, I fully agree:

but FF leaves 2 params untouched.

Confirmed.

removing into different loops

I will try that as soon as time permits. Maybe before that I try finding out why FF skips some parameters; that might help finding a different/more efficient/whatever approach. Afraid if it's Firefox not moving the iterator, that double-loop might have the same problem. I'll play with it a bit and see what I can find out.

PS: Funnily, this time I got a notification for your comment …

§
Posted: 2018-01-31
Edited: 2018-01-31

It's not a double loop, it is two completely different loops.
Let's say we have params a1, a2, a3.
In Chrome if we iterate over it and in first iteration remove element a1 then we have 2 another iterations with a2 and a3.
If FF if we do the same then after removing a1 we will receive a3 in second iteration and that's all. I guess, Chrome creates a copy of an array or maybe iterator in Chrome is not just an index or removing just marks element as removed - main thing is that in Chrome we can modify array while iterating and in FF we can't.
If we do not remove elements then Chrome and FF behave the same so I modified first loop to just reading elements and checking and remembering it.
In second loop I do not iterate over modified array (I iterate over my own array) so the issue does not affect this loop too.

IzzySoftAuthor
§
Posted: 2018-01-31

It's not a double loop

I didn't mean that literally :wink:

As your approach seems to work fine with Firefox (well, I just tried it with Waterfox), I'll put that in now and make it version 7. Thanks again for your help, very much appreciated!

§
Posted: 2018-01-31

I'm glad to help! :)

Also, while testing, I found out that your script doesn't work with dynamic sites and modified it to work.
I will merge it with newer versions in few days (I used v4).
I hope you don't mind if I open new discussion about it.

IzzySoftAuthor
§
Posted: 2018-01-31

I hope you don't mind if I open new discussion about it.

Certainly not! Go ahead :wink:

Post reply

Sign in to post a reply.