A little while ago, I developed and published my first chrome extension. Now that it's gone through a few iterations, we want to start pushing it more from the main web application, so we need to detect whether or not users already have it installed. Here's how.

Use case

Crash is a pitching platform for winning jobs. The web app allows users to create custom video pitches and send them straight to the hiring manager, yielding a very high (50-80%) conversion rate in terms of interviews won.

The chrome extension allows users to start creating pitches from anywhere on the web, so that whenever they find a job opening on some job board, they're only one click away from a new pitch for that job.

Now, whenever our users are on their dashboard in the web app, we want to remind them that they can download the extension, if they haven't already.

High level conceptual overview

It's important to understand that you cannot detect the presence of a browser extension in a user's browser directly – most likely for privacy reasons. However, you can set up your own extension to be detected by websites (domains) of your choosing.

The way this works, conceptually, is relatively straightforward. The web application sends a message to the extension to see if it's installed (requesting the version number, for example) and if the extension sends the expected response, you know that it is.

Setting up the extension

To set this up, first you have to make sure you have a background script in your extension.

Your background script is the only script in your chrome extension that runs when the extension is not opened. And seeing that the extension is most likely not opened while you're checking if it's installed, you need to communicate with the background script (and not with the content script or popup script).

If you have to add a background script for this particular use case, add the following to your manifest.json file:


  "background": {
    "scripts": ["background.js"],
    "persistent": false
  },

Now, messaging between web pages and the extension works very similarly to messaging between content scripts and popup scripts, namely via the chrome.runtime messaging API.

The difference is that web pages don't have access to that messaging API by default. You need to explicitly give them that permission, by adding the following to manifest.json:


  "externally_connectable": {
    "matches": ["*://localhost/*"]
  },
  

Obviously, you want to add your own domain under matches (in our case: crash.co) if you're running the app in production, but localhost works for testing purposes.

Now in background.js, add the following line to receive messages from the allowed domain:


chrome.runtime.onMessageExternal.addListener();

Note the onMessageExternal instead of the regular onMessage, here.

My implementation in background.js looks like this:



chrome.runtime.onMessageExternal.addListener(gotMessageExternal);

function gotMessageExternal(message, sender, sendResponse) {
  if (message.txt === 'req version') {
    const manifest = chrome.runtime.getManifest();
    sendResponse({
      type: 'success',
      version: manifest.version,
    });
  }
}

Setting up the web app

Now that the extension is set up to receive and send messages, you can start sending messages from your web app to detect whether the extension is installed.

To do this, you need your extension's ID. If you don't know the ID, you can go to chrome://extensions in your browser and find it there, or just take the ID directly from the URL of your extension in the Chrome Web Store.

When you have the ID, you can just start sending messages right from the script on the page where that information is relevant.

An implementation could look like this:


const EXTENSION_ID = 'bphcnpchmidlijnafkkjaddhadmildfh';

chrome.runtime.sendMessage(
  EXTENSION_ID,
  { txt: 'req version' },
  response => {
     if (!response) {
       //display popup: download the extension
       return
     }
     console.log('Extension version: ', response.version);
  }
);
    

And that's all there is to it!

Hopefully, my learning out loud here has been useful to you. Have a great day, and happy coding!