If you control both the extension and the website, two approaches leap to mind: web accessible resources or site-extension messaging.
In this answer I'll be using abcdefghijklmnopqrstuvwxyzabcdef
as a placeholder for your extension's ID.
Web accessible resources
Perhaps the simplest way to check if the user has your extension installed is to use XMLHttpRequest or fetch() to try to load a file from the extension. By default, extensions do not expose their resources to websites, but extension authors can selectively expose resources using the "web_accessible_resources"
key in the manifest. The following example is for a Manifest V3 extension.
manifest.json
{
"name": "",
"version": "",
"manifest_version": 3,
"web_accessible_resources": [
{
"matches": ["https://example.com/*"],
"resources": [
"1x1.png", // Expose a single file
"web-accessible-resources/*" // Or a directory tree
]
}
]
}
Then, add the following snippet to your site to check if the extension is installed.
Website JavaScript
const extensionId = "abcdefghijklmnopqrstuvwxyzabcdef";
async function checkExtensionInstalled() {
try {
await fetch(`chrome-extension://${extensionId}/1x1.png`);
return true;
} catch (e) {
if (e instanceof TypeError && e.message == 'Failed to fetch') {
return false;
} else {
throw e;
}
}
}
// Then in your site's buisness logic, do something like this
checkExtensionInstalled.then(installed => {
if (installed) {
console.log("The extension IS installed.");
} else {
console.log("The extension is NOT installed.")
}
});
Messaging
The extension platform allows a website and an extension to communicate directly with each other, but both sides must know about each other in order for this to work.
The following example is adapted from Chrome's official docs.
First, add an "externally_connectable" declaration to your extension's manifest.
manifest.json
"externally_connectable": {
"matches": ["https://*.example.com/*"]
}
Next, update your site's JS to send the extension a message.
Website JavaScript
// The ID of the extension we want to talk to.
const extensionId = "abcdefghijklmnopqrstuvwxyzabcdef";
const messageBody = "Ping";
if (chrome?.runtime?.sendMessage) {
chrome.runtime.sendMessage(extensionId, messageBody, function(response) {
console.log("The extension IS installed.", response);
});
} else {
console.log("The extension is NOT installed.")
}
Finally, in the extension's background context, add a listener for this message.
background.js
function handleExternalMessage(message, _sender, sendResponse) {
if (message === "Ping") {
sendResponse("Pong");
};
}
chrome.runtime.onMessageExternal.addListener(handleExternalMessage);