My Twitter ad blocking experiment, DOM manipulation in someone else's React app

Twitter as a platform is pretty neat. Twitter as a company sucks.

A while back they started blasting ads into my timeline, which is something I’m really not here for. I would gladly pay a fee not to have that because I love the platform, but y’know. Corporate bullshit etc. 🙄

So I’ve been taking it out on the advertisers audacious enough to target me, by blocking them. Apple? Blocked. Amazon? Blocked. Intel? You betcha you’re gonna git blocked.

a list of accounts I've blocked, overlaid by a big ol' no entry sign

Despite my best efforts it got to the point where I was getting way too many ads to keep up with, so I decided to write a script to do it automatically.

TL/DR: I just want to install the ad blocker extension

There’s an extension you can install to auto-block Twitter advertisers (providing you’re using the mobile site). You can get this for:

Automating actions in someone else’s react site 🤔

I mainly use the mobile Twitter site becuse it’s way faster than desktop, but it’s one of those sites that use React to munge class names. So instead of seeing nice <div class="tweet"> HTML, you get something more akin to <div class="rn-1oszu61 rn-1efd50x rn-14skgim rn-rull8r []…]">

This makes it insanely difficult to automate the process of finding an ad and blocking it. I’m not sure what ad blockers are doing, but this requires some pretty specific DOM selection to get working.

viewing the source of a React DOM is an exercise in pain

There’s two approaches you could take:

  1. Loop through all the <div> elements on the page until you find one with the text you’re looking for. Eg. “promoted”.
  2. Use weirdly specific selectors that get the job done, almost by chance.

Despite making fun on Twitter I chose the latter, because Twitter uses inline SVG elements, which means we can find promoted tweets by querying for the presence of certain SVG paths. It’s completely absurd and I think React is criminally negligent for making this a standard practice.

Here’s the two main selectors I’m using to find interface elements on Twitter mobile:

// The "promoted icon"
const adSelector =
'path[d="M20.75 2H3.25A2.25 2.25 0 0 0 1 4.25v15.5A2.25 2.25 0 0 0 3.25 22h17.5A2.25 2.25 0 0 0 23 19.75V4.25A2.25 2.25 0 0 0 20.75 2zM17.5 13.504a.875.875 0 1 1-1.75-.001V9.967l-7.547 7.546a.875.875 0 0 1-1.238-1.238l7.547-7.547h-3.54a.876.876 0 0 1 .001-1.751h5.65c.483 0 .875.39.875.874v5.65z"]';

// The dropdown chevron
const dropdownSelector =
'path[d="M20.207 7.043a1 1 0 0 0-1.414 0L12 13.836 5.207 7.043a1 1 0 0 0-1.414 1.414l7.5 7.5a.996.996 0 0 0 1.414 0l7.5-7.5a1 1 0 0 0 0-1.414z"]';

The remainder of the extension is fairly straightforward. Find stuff, click stuff, you know the deal. If you’re interested in having a play with it yourself, you can check it out and give it some stars on Github.