Skip to content

Commit

Permalink
Add Pendo integration (#643)
Browse files Browse the repository at this point in the history
* Add Pendo integration

* update package

* lockfile

* update script scr

* fix pendo eu region thingy

* update assets

* update script in manifest

* add preview images

* add var

* typo

* typo
  • Loading branch information
vibhanshub authored Dec 10, 2024
1 parent 0c7d088 commit 011fd92
Show file tree
Hide file tree
Showing 9 changed files with 232 additions and 0 deletions.
Binary file modified bun.lockb
Binary file not shown.
Binary file added integrations/pendo/assets/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added integrations/pendo/assets/preview-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added integrations/pendo/assets/preview-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
37 changes: 37 additions & 0 deletions integrations/pendo/gitbook-manifest.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: pendo
title: Pendo
icon: ./assets/icon.png
previewImages:
- ./assets/preview-1.png
- ./assets/preview-2.png
description: Plug your GitBook site to your Pendo Analytics instance.
externalLinks:
- label: Documentation
url: https://www.gitbook.com/integrations/pendo
visibility: private
script: ./src/index.tsx
# The following scope(s) are available only to GitBook Staff
# See https://developer.gitbook.com/integrations/configurations#scopes
scopes:
- site:script:inject
organization: gitbook
contentSecurityPolicy:
script-src: https://cdn.eu.pendo.io https://cdn.pendo.io
summary: |
# Overview
This integration allows to add Pendo Analytics on your published GitBook site.
# How it works
The integration injects the Pendo Analytics script on your page, using the configured API Key,
so that you can get analytics information from your GitBook site directly inside of Pendo.
# Configure
Install the integration on the GitBook site of your choice.
Locate the Pendo API Key you want to use from Pendo and paste it in the GitBook integration's configuration screen
categories:
- analytics
configurations:
site:
componentId: config
target: site
19 changes: 19 additions & 0 deletions integrations/pendo/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "@gitbook/integration-pendo",
"version": "0.0.1",
"private": true,
"dependencies": {
"@gitbook/api": "*",
"@gitbook/runtime": "*"
},
"devDependencies": {
"@gitbook/cli": "workspace:*",
"@gitbook/tsconfig": "workspace:*"
},
"scripts": {
"typecheck": "tsc --noEmit",
"publish-integrations-staging": "gitbook publish .",
"check": "gitbook check",
"publish-integrations": "gitbook publish ."
}
}
148 changes: 148 additions & 0 deletions integrations/pendo/src/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import {
createIntegration,
FetchPublishScriptEventCallback,
RuntimeContext,
RuntimeEnvironment,
createComponent,
} from '@gitbook/runtime';
import { IntegrationInstallationConfiguration } from '@gitbook/api';

import script from './script.raw.js';

type PendoRuntimeContext = RuntimeContext<
RuntimeEnvironment<{}, PendoSiteInstallationConfiguration>
>;
type PendoRuntimeEnvironment = RuntimeEnvironment<{}, PendoSiteInstallationConfiguration>;

type PendoSiteInstallationConfiguration = {
api_key?: string;
is_eu_region?: boolean;
};

type PendoState = PendoSiteInstallationConfiguration;

type PendoProps = {
installation: {
configuration?: IntegrationInstallationConfiguration;
};
siteInstallation?: {
configuration?: PendoSiteInstallationConfiguration;
};
};
export type PendoAction = { action: 'save.config' };

const configBlock = createComponent<PendoProps, PendoState, PendoAction, PendoRuntimeContext>({
componentId: 'config',
initialState: (props) => {
const siteInstallation = props.siteInstallation;
return {
api_key: siteInstallation?.configuration?.api_key || '',
is_eu_region: siteInstallation?.configuration?.is_eu_region || false,
};
},
action: async (element, action, context) => {
switch (action.action) {
case 'save.config':
const { api, environment } = context;
const siteInstallation = assertSiteInstallation(environment);

const configurationBody = {
...siteInstallation.configuration,
api_key: element.state.api_key,
is_eu_region: element.state.is_eu_region,
};

await api.integrations.updateIntegrationSiteInstallation(
siteInstallation.integration,
siteInstallation.installation,
siteInstallation.site,
{
configuration: {
...configurationBody,
},
},
);

return { type: 'complete' };
}
},
render: async (element, context) => {
return (
<configuration>
<box>
<markdown content="### Pendo Analytics" />
<vstack>
<input
label="Pendo API Key"
hint={<text>The Pendo API Key.</text>}
element={<textinput state="api_key" placeholder="API Key" />}
/>
</vstack>
<divider size="medium" />

<markdown content="### Region of your Pendo App" />
<input
label="Is your app in the EU Region"
hint="Toggle on if your app is in EU Region"
element={<switch state="is_eu_region" />}
/>

<input
label=""
hint=""
element={
<button
style="primary"
disabled={false}
label="Save"
tooltip="Save configuration"
onPress={{
action: 'save.config',
}}
/>
}
/>
</box>
</configuration>
);
},
});

function assertSiteInstallation(environment: PendoRuntimeEnvironment) {
const siteInstallation = environment.siteInstallation;
if (!siteInstallation) {
throw new Error('No site installation found');
}

return siteInstallation;
}

export const handleFetchEvent: FetchPublishScriptEventCallback = async (
event,
{ environment }: PendoRuntimeContext,
) => {
const apiKey = environment.siteInstallation?.configuration?.api_key;
const isEURegion = environment.siteInstallation?.configuration?.is_eu_region;
if (!apiKey) {
throw new Error(
`The API key is missing from the configuration (ID: ${
'spaceId' in event ? event.spaceId : event.siteId
}).`,
);
}
const region = isEURegion ? 'EU' : 'US';
return new Response(
(script as string).replace('<TO_REPLACE>', apiKey).replace('<REGION>', region),
{
headers: {
'Content-Type': 'application/javascript',
'Cache-Control': 'max-age=604800',
},
},
);
};

export default createIntegration<PendoRuntimeContext>({
fetch_published_script: handleFetchEvent,
components: [configBlock],
});
25 changes: 25 additions & 0 deletions integrations/pendo/src/script.raw.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
(function (apiKey) {
(function (p, e, n, d, o) {
var v, w, x, y, z;
o = p[d] = p[d] || {};
o._q = o._q || [];
v = ['initialize', 'identify', 'updateOptions', 'pageLoad', 'track'];
for (w = 0, x = v.length; w < x; ++w)
(function (m) {
o[m] =
o[m] ||
function () {
o._q[m === v[0] ? 'unshift' : 'push'](
[m].concat([].slice.call(arguments, 0)),
);
};
})(v[w]);
y = e.createElement(n);
y.async = !0;
var cdn;
cdn = '<REGION>' === 'EU' ? 'https://cdn.eu.pendo.io' : 'https://cdn.pendo.io';
y.src = `${cdn}/agent/static/` + apiKey + '/pendo.js';
z = e.getElementsByTagName(n)[0];
z.parentNode.insertBefore(y, z);
})(window, document, 'script', 'pendo');
})('<TO_REPLACE>');
3 changes: 3 additions & 0 deletions integrations/pendo/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "@gitbook/tsconfig/integration.json"
}

0 comments on commit 011fd92

Please sign in to comment.