Cecy Correa

Lessons Learned From Creating My First Chrome Extension

Mar 29, 2018 | Reading time: 9 mins

I honestly had not given much thought to Chrome extensions and how they are made. I just assumed magical fairies created them, to be honest.

We have been creating some Chrome extensions for our user base at work, and this got me to really research how Chrome extensions are created. Surprisingly, they are a delight to make, and all it takes is HTML, CSS, and basic Javascript.

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 Help You Quit Social” over a Saturday (or Caturday, really).

My Chrome Extension, let me show you it

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:

Example browser action popup

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 of the manifest you will be using, not the version of your app (this is the very first thing that I tripped on, to be honest). 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

The “background” section is where we start to get into the good stuff! Under “scripts” in the “background” object, you can determine what background scripts will run. For a complex extention, you may need to split things up into various background scripts. If you will need several background scripts, you can simply add them to the manifest under “background.scripts” as an array. Please note that this array does not know about order! If you need your scripts to 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 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 run, but most will; especially if you expect interactions between different elements. For example, if you want the extension popup window to talk to the page the user is on, you will need a popup script that talks to a content script. A pop-up cannot talk directly to the content script (or viceversa). To accomplish this interaction, 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 script.

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.

Please note that if you plan on publishing your extension to the Chrome store, there are some requirements about the type of image your icon can be. The Chrome store prefers fairly flat icons that are easy to compress. Simplicity is key here. I used FlatIcon.com to find an icon for my extension. They offer both free and paid options.

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 your extension icon. If you can’t think of anything, you don’t need one. It’s okay!

If you do, you can set the icon for your extension the browser_action section of the manifest, along with any text to 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).

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 a browser_action, 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.

Here’s 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 “Private Search Engine”. We will create a background script that will look for requests to “yahoo.com”, “bing.com” or “google.com”, and will redirect to “duckduckgo.com”.

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

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

Let’s look at the permissions step by step. We’re using a background script, so we need to request the “background” permission. We’re also using the webRequest API to modify our requests “in-flight”. Lastly, we’re requesting “webRequestBlocking” to ensure the request is run synchronously (this is important so the redirect happens at the correct time). Next, we’re requesting permissions to modify requests on certain URLs, in this case “yahoo.com”,“bing.com”, and “google.com”.

That’s all we need for the 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 arguments, but they are used to further target functionality. Here, we’re specifying we’re only looking for requests to “yahoo”, “bing”, and “google” (plus their variations); and in the options array, we’re specifying “blocking” (as explained earlier).

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

You may be wondering why you need to specify URLs and blocking in both the manifest.json file 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 button.
  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.
  5. You will also need to upload some more images for your extension, such as the banner image that will appear in the Chrome store listing for your extension.
  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.

<< Back to Posts