Lessons Learned From Creating My First Chrome Extension

29 March 2018

People make Chrome extensions? And other people use them?

YES!

I had not given much thought to Chrome extensions. I do use some, but only a few. I had never given much thought to how to create one. I just assumed magical fairies created them, to be honest.

Recently for my day job, we have been creating some Chrome extensions in the productivity category for our user base, and this got me to really research how Chrome extensions are created… and I realized they were actually quite easy to make! The hard part is coming up with an idea.

Of course, some extensions vary wildly in complexity, especially if they involve calls to outside APIs or databases, but a basic self-contained app can be knocked out in a weekend.

For example, I created “Cats Not Facebook” over a Saturday.

Let’s get started creating a simple Chrome extension.

Skills needed

Anatomy of a Chrome extension

A Chrome extension is made up of the following parts:

In sum, you will definitely need a manifest.json file, but the rest are dependent on the functionality of your extension. Let’s look at these components in depth.

Manifest file

The manifest.json file has several components of note. Let’s look at a sample one.

{
	"manifest_version": 2,
	"name": "The name of your app",
	"description": "The description of your app",
	"version": "0.1",
	"background": {
		"scripts": ["background.js"],
		"persistent" : true
	},
	"icons": {
		"19": "images/icon-16.png",
		"48": "images/icon-48.png",
		"128": "images/icon-128.png"
	},
	"browser_action": {
		"default_title": "title that appears when users mouse over the extension icon",
		"default_icon": "images/icon-48.png"
	},
	"options_page": "options.html",
	"permissions": [
		"background",
		"tabs"
	]
}

You can find a full example of a manifest.json file here.

Manifest metadata

“manifest_version” refers to the version you will be using, not the version of your app. Currently, the most recent version is version “2”. This may change as Google makes updates to the way they handle extensions.

The name and description part are pretty self-explanatory. The “version” is the version of your extenstion, which will be shown on the Chrome extension store. The recommended way to handle the extension versioning is SEMVER.

Background tasks

“background” is where we start to get into the good stuff! Under “scripts” in the “background” object, you can determine what background scripts run. You can have more than one, if you need to split things up, just add it to the “scripts” array. This array does not know about order. If you need them run in a certain order, you can create an empty “background.html” page, and add them to the head of the html in the order you want them loaded.

If you want the background task to run more than once, and continue running until the user closes the browser, you’ll want to set your background scripts to “persistent: true” in your manifest file. You can learn more about background scripts here.

Not all apps require a background script to be running, but most will need it, especially if you expect to have more complex interactions between elements. For example, if you want the extension popup window to talk to the page the user is on, you would need the popup to talk to the content script(s). A pop-up cannot talk directly to the content script (or viceversa). To do this, you would need to have the popup send a message to the background script, and then have the background script send a message to the content to do something.

For these reasons, you will most likely need one (if not more) background scripts for your extension. This is likely where most of the complexity will come from.

Icons

The “icons” portion is pretty self-explanatory. Icons can live anywhere, even at the root of your extension if you want. I personally set them inside an “images” folder for organization purposes. Chrome requires you to have several sizes for your icons: 16x16, 48x48, and 128x128.

Browser action

The browser action refers to the icon that appears on the user’s browser on the upper right-hand corner. Not all extensions show an icon there, because not all extensions need something to happen when a user clicks on this icon. Think about whether you will need something to happen when user clicks on theyour extension icon on the browser. If you can’t think of anything, you don’t need one. It’s okay!

If you do, you can set the icon the extension will show in this section, along with the title that will be displayed when a user hovers over the icon. This can be the title of your extension, or even some helpful information to the user about the status of the extension (i.e. you are logged in / logged out sort of thing).

You can also set more of these options from your background script(s). You can learn more about browser actions here.

Again, if you don’t think you’ll need this, you can omit this from your manifest file.

Options

This section determines whether you need a special options page for your extension. If your extension would require a user to sign in to a service, this may be a good place to put some of those interactions.

For my app, I used this page to include an FAQ about the extension itself. If you don’t think you’ll need an options page, you don’t have to include this in your manifest file.

Permissions

This section is super important and you will absolutely need it for your extension. The permissions section determines which permissions your extension needs from the user. If you are going to use a background script, you would ask for the “background” permission.

You can find a list of all of the permissions you can request access to. The most common are “tabs”, “activeTab”, and “background”.

Let’s build something!

Let’s build a simple chrome extension together. We’ll call it “Better Search Engine”. We will create a background script that will look for requests to “yahoo” or “bing”, and will redirect to “google”.

First, let’s add this to our manifest file:

	"permissions": [
		"background",
		"webRequest",
		"webRequestBlocking",
		"*://*.yahoo.com/",
		"*://*.bing.com/"
	]

We’re using a background script, so we need to request the “background” permission. We’re also using the webRequest API, and we’ll be using web request blocking to redirect URLs, so we need to also request “webRequestBlocking”. Next, we’re requesting permissions to modify requests on certain URLs, in this case “yahoo.com” and “bing.com”.

That’s all we need for manifest.

Now for the background script, we’ll add a simple listener to monitor web requests. webRequest.onBeforeRequest uses the following convention:

chrome.webRequest.onBeforeRequest.addListener(callback, urls, options)

The callback is just an anonymous function that returns some data. The “urls” and “options” are optional, but they are used to further target functionality. Here, we’re specifying we’re only looking for requests to “yahoo” and “bing” (and their variations), and in the options array, we’re specifying “blocking”, meaning this is meant to block the request.

chrome.webRequest.onBeforeRequest.addListener(
    (details) => {
        return {redirectUrl: "https://google.com"}
    },
    {urls: ["*://www.yahoo.com/*", "*://yahoo.com/*", "*://www.bing.com/*", "*://bing.com/*"]},
    ["blocking"]
)

You may be wondering why you need to specify URLs both in manifest.json and in the background script. The difference is simple: 1) In manifest.json, we’re asking permission to modify certain URLs, and 2) In background.js we’re simply adding which URLs our script should match.

Let’s test our extension

To test our extension:

  1. Go to chrome://extensions
  2. On the upper right-hand corner, make sure “Developer mode” is turned on
  3. You should now see an option that says “Load unpacked”, click on this
  4. Navigate to the directory where your extension code lives and select the root directory of your extension

Your extension should now be loaded in developer mode. If you click on “background page”, you’ll be able to read any output of your extension that you’re logging out, or look for any errors.

Deploying your extension

Deploying your extension to the Chrome store is easy!

  1. Go to the Chrome developer dashboard
  2. Click on “Add New Item”
  3. Zip up the contents of your extension (make sure you zip the contents from the root directory, and not the root directory itself)
  4. You will see a screen where you can fill out more details about your extension. Fill them out.
  5. You will also need to upload some more images / icons for your extension. You may notice that the compression of the images is really bad, and makes some images look like crap. Chrome recommends using very flat imagery for icons.
  6. Lastly, you will need to pay a one-time $5 developer fee.

Your extension can take up to an hour to fully publish and propagate, so be patient!

That’s it! You have now deployed a Chrome extension to the app store.