diff --git a/integrations/mouseflow/.eslintrc.json b/integrations/mouseflow/.eslintrc.json
new file mode 100644
index 000000000..99e7792b9
--- /dev/null
+++ b/integrations/mouseflow/.eslintrc.json
@@ -0,0 +1,3 @@
+{
+ "extends": ["@gitbook/eslint-config/integration"]
+}
\ No newline at end of file
diff --git a/integrations/mouseflow/CHANGELOG.md b/integrations/mouseflow/CHANGELOG.md
new file mode 100644
index 000000000..2e693aaf4
--- /dev/null
+++ b/integrations/mouseflow/CHANGELOG.md
@@ -0,0 +1 @@
+# @gitbook/integration-mouseflow
diff --git a/integrations/mouseflow/assets/icon.png b/integrations/mouseflow/assets/icon.png
new file mode 100644
index 000000000..efe64e4d0
Binary files /dev/null and b/integrations/mouseflow/assets/icon.png differ
diff --git a/integrations/mouseflow/assets/mouseflow-preview.png b/integrations/mouseflow/assets/mouseflow-preview.png
new file mode 100644
index 000000000..ce2c6f121
Binary files /dev/null and b/integrations/mouseflow/assets/mouseflow-preview.png differ
diff --git a/integrations/mouseflow/gitbook-manifest.yaml b/integrations/mouseflow/gitbook-manifest.yaml
new file mode 100644
index 000000000..9531a60b0
--- /dev/null
+++ b/integrations/mouseflow/gitbook-manifest.yaml
@@ -0,0 +1,41 @@
+name: mouseflow
+title: mouseflow
+icon: ./assets/icon.png
+previewImages:
+ - ./assets/mouseflow-preview.png
+description: Plug your GitBook site to your Mouseflow installation.
+externalLinks:
+ - label: Documentation
+ url: https://www.gitbook.com/integrations/mouseflow
+visibility: public
+script: ./src/index.ts
+# The following scope(s) are available only to GitBook Staff
+# See https://developer.gitbook.com/integrations/configurations#scopes
+scopes:
+ - space:script:inject
+organization: d8f63b60-89ae-11e7-8574-5927d48c4877
+contentSecurityPolicy:
+ script-src: cdn.mouseflow.com;
+summary: |
+ # Overview
+ This integration allows to add the Mouseflow tracker on your published GitBook site.
+
+ # How it works
+ The integration injects the Mouseflow script on your page, using the configured Website ID,
+ so that you can get analytics information from your GitBook site.
+
+ # Configure
+ Install the integration on the GitBook space of your choice.
+ Locate the Website ID you want to use from the settings page.
+
+categories:
+ - analytics
+configurations:
+ space:
+ properties:
+ website_id:
+ type: string
+ title: Mouseflow Website ID
+ description: Available in Mouseflow website settings page
+ required:
+ - website_id
diff --git a/integrations/mouseflow/package.json b/integrations/mouseflow/package.json
new file mode 100644
index 000000000..252a535ed
--- /dev/null
+++ b/integrations/mouseflow/package.json
@@ -0,0 +1,18 @@
+{
+ "name": "@gitbook/integration-mouseflow",
+ "version": "0.0.1",
+ "private": true,
+ "dependencies": {
+ "@gitbook/api": "*",
+ "@gitbook/runtime": "*"
+ },
+ "devDependencies": {
+ "@gitbook/cli": "*"
+ },
+ "scripts": {
+ "lint": "eslint ./src/**/*.ts",
+ "typecheck": "tsc --noEmit",
+ "publish-integrations-staging": "gitbook publish .",
+ "publish-integrations": "gitbook publish ."
+ }
+}
diff --git a/integrations/mouseflow/src/index.ts b/integrations/mouseflow/src/index.ts
new file mode 100644
index 000000000..0499e7d6d
--- /dev/null
+++ b/integrations/mouseflow/src/index.ts
@@ -0,0 +1,40 @@
+import {
+ createIntegration,
+ FetchPublishScriptEventCallback,
+ RuntimeContext,
+ RuntimeEnvironment,
+} from '@gitbook/runtime';
+
+import script from './script.raw.js';
+
+type MouseflowRuntimeContext = RuntimeContext<
+ RuntimeEnvironment<
+ {},
+ {
+ website_id?: string;
+ }
+ >
+>;
+
+export const handleFetchEvent: FetchPublishScriptEventCallback = async (
+ event,
+ { environment }: MouseflowRuntimeContext
+) => {
+ const websiteId = environment.spaceInstallation.configuration.website_id;
+ if (!websiteId) {
+ throw new Error(
+ `The Mouseflow Website ID is missing from the configuration. (ID: ${event.spaceId}).`
+ );
+ }
+
+ return new Response(script.replace('', websiteId), {
+ headers: {
+ 'Content-Type': 'application/javascript',
+ 'Cache-Control': 'max-age=604800',
+ },
+ });
+};
+
+export default createIntegration({
+ fetch_published_script: handleFetchEvent,
+});
diff --git a/integrations/mouseflow/src/script.raw.js b/integrations/mouseflow/src/script.raw.js
new file mode 100644
index 000000000..1655b98be
--- /dev/null
+++ b/integrations/mouseflow/src/script.raw.js
@@ -0,0 +1,10 @@
+const websiteId = '';
+
+window._mfq = window._mfq || [];
+(function() {
+ var mf = document.createElement("script");
+ mf.type = "text/javascript";
+ mf.defer = true;
+ mf.src = "//cdn.mouseflow.com/projects/" + websiteId + ".js";
+ document.getElementsByTagName("head")[0].appendChild(mf);
+})();
diff --git a/integrations/mouseflow/tsconfig.json b/integrations/mouseflow/tsconfig.json
new file mode 100644
index 000000000..f839d1833
--- /dev/null
+++ b/integrations/mouseflow/tsconfig.json
@@ -0,0 +1,3 @@
+{
+ "extends": "@gitbook/tsconfig/integration.json"
+}
\ No newline at end of file