Your browser extension

From time to time I face a need to automatically run a script on a webpage with certain URL.

While there are certain web extensions that allow you to do that (e.g. Tampermonkey), this solution doesn’t always work: you might be restricted in some extensions usage at your work for security reasons or you’d like to edit those user scripts by your code editor of choice.

There’s another solution you can try to overcome these issues: write your own browser extension! I’ve tried this approach to run custom scripts on websites and I never looked back.

Before I start: this solution works with Google Chrome browser. The provided extension will also work in Firefox, but you’ll need to pack it before you can use it.

What does that mean?

So, what I mean is that you have a simple browser extension that contains all the custom behaviours you’d like to use and the mechanism running them.

You can bind behaviours you want to implement by registering them for certain hostnames.

I’ve created a template for such an extension and shared it in my Github account. Feel free to fork it and implement your own custom scripts extension. The extension is compatible with Google Chrome browser.

How do I use the extension?

There are a few ways you can use the extension in. The simplest one is to use the extension in an unpacked form.

Advantages:

Disadvantages:

An alternative to this can be to register as an extensions developer in Chrome Web Store. Note that Google collects a one-time fee when you’re signing up (I believe it’s $5), you can read more about that in official docs.

Either option will hit the goal, but for personal usage I would recommend you to stick with the unpacked extension format.

How do I install unpacked extension?

After you clone the example of my repo, you can load the extension in a browser.

To install the extension:

That’s it! After you change something in the extension files, the changes should be applied automatically, but if it doesn’t happen, you should go again to “Extensions” page and hit the “Reload” button for the extension.

How do I sync my extension between my computers?

I see a few ways to sync the extension between different computers.

First way would be to use Git in order to keep your extension versions. In that case you’ll have to manually pull the repo on your other machines (or, maybe, schedule a cron job to do that).

The other option would be to place the extension files in a cloud storage, e.g. Dropbox, and it’ll make the extension up-to-date automatically.

While I prefer to use git for the sake of such a sync, I also see the benefits of the other approach; so it’s up to you how to use it.

Use cases

Maybe you know that I’m prefer to use keyboard when possible. Because of that, I tend to use an excellent Vimium extension for Google Chrome, allowing to navigate web with keyboard.

But sometimes the elements aren’t accessible via keyboard by design. Developers implement buttons using <div> elements, come up with custom dropdown lists implementations and so on.

So sometimes, in order to make an element clickable, I add a “tabindex” attribute to the elements I need to interact with on a certain website.

In my extension example you’ll find a helper “enableKeyboardFor”, which does exactly that. You feed a CSS selector to this helper and it does the rest of work, allowing me to navigate the website using Vimium extension.

Another helper I use is “blurActiveElement”. It removes focus from the focused element on the page. As I’m using Vimium, sometimes I want to open a page and start scrolling it, but instead of that my key press causes typing in a search box or something like that. In these situations I’m calling “blurActiveElement” in order to navigate the page.

The last typical case would be custom styling. Sometimes you need to hide some parts of a website, change font of colors in order to make it readable. You can use “injectStyles” helper for that. And as Chrome supports template literals now, injecting multiline CSS is a breeze:

runOn(/google.com/, () => {
  injectStyles(`
    body {
      background: red;
    }
  `);
});

I also provided a mechanism for pathname filtering:

runOn(/google.com/, /^\/flights/, () => {
  // do something
});

If you want to implement more granular filtering for pages (e.g. based on GET-parameters or page hash) you can either implement such filtering inside of the appropriate “runOn” callback, or write your own handler doing the filtering for you.