Skip to main content

Browser Extension — Managed Deployment

This page covers deploying the Behavry browser extension centrally, to a managed fleet, via Intune or Group Policy. To install it on a single machine by hand, see Browser Extension.

Applies to extension v0.1.13.


Start here if you manage Edge

You cannot upload the extension to Edge, and that is expected — it is not a step you have missed.

Edge's admin console has no extension-upload path, and the .zip published on downloads.behavry.ai is a sideload-only format that no Chromium browser can install by policy. Uploading works in the Google Admin console because it accepts a signed .crx; Edge has no equivalent.

Force-install from the Chrome Web Store instead. Edge installs Chrome Web Store extensions natively. You do not need an Edge Add-ons listing, and you do not need the zip.

Deployment is two steps, in order:

  1. Install — force-install by extension ID
  2. Configure — push serverUrl and extensionToken by policy
Step 2 is not optional

Without a pushed configuration the extension falls back to http://localhost:8000 and silently forwards nothing. It will still appear healthy in edge://extensions, and it will produce zero data. Most failed deployments are a completed step 1 with a skipped step 2.


1. Install

Extension ID: phpahmfilmdnlfgfkjkhpdjgbliipoac

Intune (Settings Catalog)

Go to Devices → Configuration → Create policy → Windows 10 and later → Settings catalog, then add Microsoft Edge → Extensions → Configure extension management settings. Paste this as a single line:

{"phpahmfilmdnlfgfkjkhpdjgbliipoac":{"installation_mode":"force_installed","update_url":"https://clients2.google.com/service/update2/crx"}}
The Google URL is correct

clients2.google.com is what tells Edge to pull from the Chrome Web Store. A policy-driven force-install does not require your users to opt in to "extensions from other stores."

Group Policy

Computer Configuration → Administrative Templates → Microsoft Edge → Extensions → Configure extension management settings, with the same JSON payload.

Registry

HKLM\SOFTWARE\Policies\Microsoft\Edge
ExtensionSettings REG_SZ {"phpahmfilmdnlfgfkjkhpdjgbliipoac":{"installation_mode":"force_installed","update_url":"https://clients2.google.com/service/update2/crx"}}

Chrome

Identical JSON. The registry path is HKLM\SOFTWARE\Policies\Google\Chrome.

Deploying to Macs?

macOS has no registry, and both steps arrive in a single configuration profile. Skip ahead to macOS under Configure — that profile force-installs and configures, so you do not need anything from this section.


2. Configure

The extension reads its configuration from chrome.storage.managed, under its own policy namespace.

First, generate a token: in the Behavry dashboard go to Settings → Extension Tokens. Pushing it by policy means no end user ever has to paste one.

Windows

HKLM\SOFTWARE\Policies\Microsoft\Edge\3rdparty\extensions\phpahmfilmdnlfgfkjkhpdjgbliipoac\policy
serverUrl REG_SZ https://behavry.yourcompany.com
extensionToken REG_SZ <token from the dashboard>

Via Intune, use an OMA-URI or ingested-ADMX policy targeting the same path.

Supported keys

KeyRequiredPurpose
serverUrlYesBase URL of your Behavry server. Defaults to http://localhost:8000 when unset, which forwards nothing.
extensionTokenYesAPI authentication token. Without it the popup reports "No token — events will not be forwarded."
userIdentifierOptionalThe work email to attribute this install's activity to. Assigned per user. Overrides both what the person entered and the account the browser reports, and makes the field read-only in the popup. Leave unset to let people enter and maintain their own.
allowedEmailDomainsOptionalArray, e.g. ["yourcompany.com"]. Only binds an identity when the signed-in account's domain matches, so personal accounts on a managed browser are not attributed.

Any value pushed by policy outranks both the value the person entered and the account the browser reports.

macOS

Chromium on macOS honours a value only when it comes from a managed source. A configuration profile qualifies. defaults write does not — it appears to succeed and has no effect.

The profile below covers both steps: it force-installs the extension and pushes its configuration. Save it as behavry-identity.mobileconfig and replace the three placeholder values:

PlaceholderReplace with
REPLACE_WITH_SERVER_URLBase URL of your Behavry server
REPLACE_WITH_EXTENSION_TOKENToken from Settings → Extension Tokens
REPLACE_WITH_USER_EMAILThe person's work email — or delete the userIdentifier key to let them enter their own

It carries two payloads per browser — delete both payloads for a browser you do not use; they are harmless but add noise to the profiles list.

Why two payloads per browser

The force-install (ExtensionInstallForcelist) is a browser policy, so it goes in the com.google.Chrome / com.microsoft.Edge payload. The extension's own configuration lives in a separate preference domain per extension — a payload whose PayloadType is the browser's bundle ID with .extensions.<extension-id> appended, with the keys at its top level.

Configuration keys nested as 3rdpartyextensions<id> inside the browser payload are not read on macOS. That form is the Windows registry and Linux JSON layout; Chromium's macOS loader builds <bundle-id>.extensions.<extension-id> and reads each key as a raw top-level value from that domain instead. A profile using the nested form installs cleanly, reports no error, and delivers nothing.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PayloadContent</key>
<array>
<!-- Microsoft Edge — force-install (browser policy) -->
<dict>
<key>PayloadType</key>
<string>com.microsoft.Edge</string>
<key>PayloadUUID</key>
<string>264AE748-6263-4165-BF3E-6EAB13B7D767</string>
<key>PayloadIdentifier</key>
<string>ai.behavry.extension.edge</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>PayloadDisplayName</key>
<string>Behavry extension — install (Edge)</string>
<key>PayloadEnabled</key>
<true/>
<key>ExtensionInstallForcelist</key>
<array>
<string>phpahmfilmdnlfgfkjkhpdjgbliipoac;https://clients2.google.com/service/update2/crx</string>
</array>
</dict>
<!-- Microsoft Edge — extension configuration (per-extension domain) -->
<dict>
<key>PayloadType</key>
<string>com.microsoft.Edge.extensions.phpahmfilmdnlfgfkjkhpdjgbliipoac</string>
<key>PayloadUUID</key>
<string>A130E482-A53A-4FF2-8A9D-48FAB69AA914</string>
<key>PayloadIdentifier</key>
<string>ai.behavry.extension.edge.config</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>PayloadDisplayName</key>
<string>Behavry extension — config (Edge)</string>
<key>PayloadEnabled</key>
<true/>
<key>serverUrl</key>
<string>REPLACE_WITH_SERVER_URL</string>
<key>extensionToken</key>
<string>REPLACE_WITH_EXTENSION_TOKEN</string>
<key>userIdentifier</key>
<string>REPLACE_WITH_USER_EMAIL</string>
</dict>
<!-- Google Chrome — force-install (browser policy) -->
<dict>
<key>PayloadType</key>
<string>com.google.Chrome</string>
<key>PayloadUUID</key>
<string>47C052AD-7B40-4803-9AEB-A1E7DD2E55E7</string>
<key>PayloadIdentifier</key>
<string>ai.behavry.extension.chrome</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>PayloadDisplayName</key>
<string>Behavry extension — install (Chrome)</string>
<key>PayloadEnabled</key>
<true/>
<key>ExtensionInstallForcelist</key>
<array>
<string>phpahmfilmdnlfgfkjkhpdjgbliipoac;https://clients2.google.com/service/update2/crx</string>
</array>
</dict>
<!-- Google Chrome — extension configuration (per-extension domain) -->
<dict>
<key>PayloadType</key>
<string>com.google.Chrome.extensions.phpahmfilmdnlfgfkjkhpdjgbliipoac</string>
<key>PayloadUUID</key>
<string>95EB66ED-E923-42A8-9DC3-65E0F7F0C4B5</string>
<key>PayloadIdentifier</key>
<string>ai.behavry.extension.chrome.config</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>PayloadDisplayName</key>
<string>Behavry extension — config (Chrome)</string>
<key>PayloadEnabled</key>
<true/>
<key>serverUrl</key>
<string>REPLACE_WITH_SERVER_URL</string>
<key>extensionToken</key>
<string>REPLACE_WITH_EXTENSION_TOKEN</string>
<key>userIdentifier</key>
<string>REPLACE_WITH_USER_EMAIL</string>
</dict>
</array>
<key>PayloadDisplayName</key>
<string>Behavry — browser extension</string>
<key>PayloadIdentifier</key>
<string>ai.behavry.extension</string>
<key>PayloadType</key>
<string>Configuration</string>
<key>PayloadUUID</key>
<string>F74B8626-9DC1-48E9-A005-79F034632CA5</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>PayloadScope</key>
<string>System</string>
<key>PayloadOrganization</key>
<string>Behavry</string>
<key>PayloadDescription</key>
<string>Installs the Behavry browser extension and sets the server, token, and work identity it reports under.</string>
</dict>
</plist>
userIdentifier makes this a per-user profile

A profile carrying userIdentifier holds one person's email, so an MDM must generate it per assignment rather than shipping one file to the whole fleet. If you would rather deploy a single profile everywhere, delete the userIdentifier key — people then enter and maintain their own identity in the popup. serverUrl and extensionToken are fleet-wide and safe to ship identically.

To scope identity binding to your own domain, add allowedEmailDomains alongside the other keys in the .extensions.<id> config payload — note that it is an array, not a string:

<key>allowedEmailDomains</key>
<array>
<string>yourcompany.com</string>
</array>

Installing by hand (for testing): double-click the file, then approve it in System Settings → General → Device Management. macOS requires that approval for manually installed profiles, and the profiles CLI does not bypass it. A profile delivered by MDM installs without the prompt.

Restart the browser afterwards — policy is read at startup.


The extension has two IDs

A policy aimed at the wrong ID fails silently

No error, no log entry — the extension simply never receives the policy.

Install sourceExtension ID
Chrome Web Store (used throughout this page)phpahmfilmdnlfgfkjkhpdjgbliipoac
Sideload zip from downloads.behavry.aihbcmolffehhcjabapjoglcjgpbckhmbp

The sideload build pins its ID via a key field in its manifest. Store builds have that key stripped, so the store assigns its own ID.

If you test-installed the zip by hand earlier, that machine is running the other ID. Confirm the ID on edge://extensions for the install you are targeting before concluding that policy is broken.


3. Verify

Check the policy arrived. Open edge://policy and select Reload policies. ExtensionSettings should be listed, and the extension's own policies appear under its ID. If they are absent, the browser never received them — wrong ID, policy not delivered, or the browser wasn't restarted.

Check the extension can see them. Open edge://extensionsBehavryservice worker, and run:

chrome.storage.managed.get(null, v => console.log('MANAGED →', v))

Expect {serverUrl: "https://…", extensionToken: "…"}. An empty {} means policy is not reaching the extension — recheck the ID.

Check it end to end. Open chatgpt.com, submit a prompt, then look for a browser_event entry under Live Activity in the dashboard. To exercise DLP, paste a test card number (4111 1111 1111 1111) into the prompt box; the event should arrive with dlp_findings populated.


Notes

  • Updates are handled by the store automatically. There is no update infrastructure to host.
  • Version parity: the Chrome Web Store serves the same build as the sideload zip, so deploying from the store costs you no functionality.
  • InPrivate / Incognito: Chromium disables extensions there by default. Enable it per extension if your coverage requirements call for it.
  • Firefox and Safari builds exist but are distributed separately, and neither supports chrome.storage.managed — the policy configuration on this page is Chromium-only.