From 0993825286780f07287b7f18239d69fa4444e7d4 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Tue, 21 Sep 2021 11:47:14 +0100 Subject: [PATCH] analytics clients --- .github/workflows/release-develop.yml | 1 + .github/workflows/release.yml | 1 + packages/auth/src/objectStore/index.js | 1 + packages/builder/src/analytics.js | 139 ----------------- .../builder/src/analytics/IntercomClient.js | 66 ++++++++ .../builder/src/analytics/PosthogClient.js | 144 ++++++++++++++++++ .../builder/src/analytics/SentryClient.js | 39 +++++ packages/builder/src/analytics/constants.js | 49 ++++++ packages/builder/src/analytics/index.js | 76 +++++++++ packages/builder/src/builderStore/index.js | 4 +- .../src/components/deploy/DeployModal.svelte | 6 +- .../components/start/CreateAppModal.svelte | 6 +- .../src/pages/builder/auth/login.svelte | 13 +- .../pages/builder/portal/apps/index.svelte | 6 +- .../builder/portal/manage/auth/index.svelte | 2 + .../builder/portal/manage/email/index.svelte | 2 + .../users/_components/AddUserModal.svelte | 2 + .../portal/settings/organisation.svelte | 2 +- packages/builder/vite.config.js | 3 + 19 files changed, 412 insertions(+), 150 deletions(-) delete mode 100644 packages/builder/src/analytics.js create mode 100644 packages/builder/src/analytics/IntercomClient.js create mode 100644 packages/builder/src/analytics/PosthogClient.js create mode 100644 packages/builder/src/analytics/SentryClient.js create mode 100644 packages/builder/src/analytics/constants.js create mode 100644 packages/builder/src/analytics/index.js diff --git a/.github/workflows/release-develop.yml b/.github/workflows/release-develop.yml index ce41fcc3e6..cf0d6f848c 100644 --- a/.github/workflows/release-develop.yml +++ b/.github/workflows/release-develop.yml @@ -7,6 +7,7 @@ on: env: POSTHOG_TOKEN: ${{ secrets.POSTHOG_TOKEN }} + INTERCOM_TOKEN: ${{ secrets.INTERCOM_TOKEN }} POSTHOG_URL: ${{ secrets.POSTHOG_URL }} SENTRY_DSN: ${{ secrets.SENTRY_DSN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index aaee3923ef..00e7f9a795 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,6 +7,7 @@ on: env: POSTHOG_TOKEN: ${{ secrets.POSTHOG_TOKEN }} + INTERCOM_TOKEN: ${{ secrets.INTERCOM_TOKEN }} POSTHOG_URL: ${{ secrets.POSTHOG_URL }} SENTRY_DSN: ${{ secrets.SENTRY_DSN }} diff --git a/packages/auth/src/objectStore/index.js b/packages/auth/src/objectStore/index.js index 81bdd06b62..0f1307c39d 100644 --- a/packages/auth/src/objectStore/index.js +++ b/packages/auth/src/objectStore/index.js @@ -73,6 +73,7 @@ exports.ObjectStore = bucket => { AWS.config.update({ accessKeyId: env.MINIO_ACCESS_KEY, secretAccessKey: env.MINIO_SECRET_KEY, + region: env.AWS_REGION }) const config = { s3ForcePathStyle: true, diff --git a/packages/builder/src/analytics.js b/packages/builder/src/analytics.js deleted file mode 100644 index 5b130a8e6b..0000000000 --- a/packages/builder/src/analytics.js +++ /dev/null @@ -1,139 +0,0 @@ -import * as Sentry from "@sentry/browser" -import posthog from "posthog-js" -import api from "builderStore/api" - -let analyticsEnabled -const posthogConfigured = process.env.POSTHOG_TOKEN && process.env.POSTHOG_URL -const sentryConfigured = process.env.SENTRY_DSN - -const FEEDBACK_SUBMITTED_KEY = "budibase:feedback_submitted" -const APP_FIRST_STARTED_KEY = "budibase:first_run" -const feedbackHours = 12 - -async function activate() { - if (analyticsEnabled === undefined) { - // only the server knows the true NODE_ENV - // this was an issue as NODE_ENV = 'cypress' on the server, - // but 'production' on the client - const response = await api.get("/api/analytics") - analyticsEnabled = (await response.json()).enabled === true - } - if (!analyticsEnabled) return - if (sentryConfigured) Sentry.init({ dsn: process.env.SENTRY_DSN }) - if (posthogConfigured) { - posthog.init(process.env.POSTHOG_TOKEN, { - autocapture: false, - capture_pageview: false, - api_host: process.env.POSTHOG_URL, - }) - posthog.set_config({ persistence: "cookie" }) - } -} - -function identify(id) { - if (!analyticsEnabled || !id) return - if (posthogConfigured) posthog.identify(id) - if (sentryConfigured) - Sentry.configureScope(scope => { - scope.setUser({ id: id }) - }) -} - -async function identifyByApiKey(apiKey) { - if (!analyticsEnabled) return true - try { - const response = await fetch( - `https://03gaine137.execute-api.eu-west-1.amazonaws.com/prod/account/id?api_key=${apiKey.trim()}` - ) - if (response.status === 200) { - const id = await response.json() - - await api.put("/api/keys/userId", { value: id }) - identify(id) - return true - } - - return false - } catch (error) { - console.log(error) - } -} - -function captureException(err) { - if (!analyticsEnabled) return - Sentry.captureException(err) - captureEvent("Error", { error: err.message ? err.message : err }) -} - -function captureEvent(eventName, props = {}) { - if (!analyticsEnabled || !process.env.POSTHOG_TOKEN) return - props.sourceApp = "builder" - posthog.capture(eventName, props) -} - -if (!localStorage.getItem(APP_FIRST_STARTED_KEY)) { - localStorage.setItem(APP_FIRST_STARTED_KEY, Date.now()) -} - -const isFeedbackTimeElapsed = sinceDateStr => { - const sinceDate = parseFloat(sinceDateStr) - const feedbackMilliseconds = feedbackHours * 60 * 60 * 1000 - return Date.now() > sinceDate + feedbackMilliseconds -} - -function submitFeedback(values) { - if (!analyticsEnabled || !process.env.POSTHOG_TOKEN) return - localStorage.setItem(FEEDBACK_SUBMITTED_KEY, Date.now()) - - const prefixedValues = Object.entries(values).reduce((obj, [key, value]) => { - obj[`feedback_${key}`] = value - return obj - }, {}) - - posthog.capture("Feedback Submitted", prefixedValues) -} - -function requestFeedbackOnDeploy() { - if (!analyticsEnabled || !process.env.POSTHOG_TOKEN) return false - const lastSubmittedStr = localStorage.getItem(FEEDBACK_SUBMITTED_KEY) - if (!lastSubmittedStr) return true - return isFeedbackTimeElapsed(lastSubmittedStr) -} - -function highlightFeedbackIcon() { - if (!analyticsEnabled || !process.env.POSTHOG_TOKEN) return false - const lastSubmittedStr = localStorage.getItem(FEEDBACK_SUBMITTED_KEY) - if (lastSubmittedStr) return isFeedbackTimeElapsed(lastSubmittedStr) - const firstRunStr = localStorage.getItem(APP_FIRST_STARTED_KEY) - if (!firstRunStr) return false - return isFeedbackTimeElapsed(firstRunStr) -} - -// Opt In/Out -const ifAnalyticsEnabled = func => () => { - if (analyticsEnabled && process.env.POSTHOG_TOKEN) { - return func() - } -} -const disabled = () => posthog.has_opted_out_capturing() -const optIn = () => posthog.opt_in_capturing() -const optOut = () => posthog.opt_out_capturing() - -export default { - activate, - identify, - identifyByApiKey, - captureException, - captureEvent, - requestFeedbackOnDeploy, - submitFeedback, - highlightFeedbackIcon, - disabled: () => { - if (analyticsEnabled == null) { - return true - } - return ifAnalyticsEnabled(disabled) - }, - optIn: ifAnalyticsEnabled(optIn), - optOut: ifAnalyticsEnabled(optOut), -} diff --git a/packages/builder/src/analytics/IntercomClient.js b/packages/builder/src/analytics/IntercomClient.js new file mode 100644 index 0000000000..2cabeb97df --- /dev/null +++ b/packages/builder/src/analytics/IntercomClient.js @@ -0,0 +1,66 @@ +export default class IntercomClient { + constructor(token) { + this.token = token + } + + init() { + if (!this.token) return + + const token = this.token + + var w = window + var ic = w.Intercom + if (typeof ic === "function") { + ic("reattach_activator") + ic("update", w.intercomSettings) + } else { + var d = document + var i = function () { + i.c(arguments) + } + i.q = [] + i.c = function (args) { + i.q.push(args) + } + w.Intercom = i + var l = function () { + var s = d.createElement("script") + s.type = "text/javascript" + s.async = true + s.src = "https://widget.intercom.io/widget/" + token + var x = d.getElementsByTagName("script")[0] + x.parentNode.insertBefore(s, x) + } + if (document.readyState === "complete") { + l() + } else if (w.attachEvent) { + w.attachEvent("onload", l) + } else { + w.addEventListener("load", l, false) + } + + this.initialised = true + } + } + + show(user = {}) { + if (!this.initialised) return + + return window.Intercom("boot", { + app_id: this.token, + ...user + }) + } + + update() { + if (!this.initialised) return + + return window.Intercom("update") + } + + captureEvent(event, props = {}) { + if (!this.initialised) return + + window.Intercom("trackEvent", event, props); + } +} diff --git a/packages/builder/src/analytics/PosthogClient.js b/packages/builder/src/analytics/PosthogClient.js new file mode 100644 index 0000000000..9a98520c91 --- /dev/null +++ b/packages/builder/src/analytics/PosthogClient.js @@ -0,0 +1,144 @@ +import posthog from "posthog-js" +import { Events } from "./constants" + +// let analyticsEnabled +// const posthogConfigured = process.env.POSTHOG_TOKEN && process.env.POSTHOG_URL + +// const FEEDBACK_SUBMITTED_KEY = "budibase:feedback_submitted" +// const APP_FIRST_STARTED_KEY = "budibase:first_run" +// const feedbackHours = 12 + +export default class PosthogClient { + constructor(token, url) { + this.token = token + this.url = url + } + + init() { + if (!this.token || !this.url) return + + posthog.init(this.token, { + autocapture: false, + capture_pageview: false, + api_host: this.url, + }) + posthog.set_config({ persistence: "cookie" }) + + this.initialised = true + } + + disabled() { + return posthog.has_opted_out_capturing() + } + + optIn() { + return posthog.opt_in_capturing() + } + + optOut() { + return posthog.opt_out_capturing() + } + + identify(id) { + if (!this.initialised) return + + posthog.identify(id) + } + + updateUser(meta) { + if (!this.initialised) return + + posthog.people.set(meta) + } + + captureException(err) { + if (!this.initialised) return + + this.captureEvent("Error", { error: err.message ? err.message : err }) + } + + captureEvent(eventName, props) { + if (!this.initialised) return + + props.sourceApp = "builder" + posthog.capture(eventName, props) + } + + npsFeedback(values) { + if (!this.initialised) return + + localStorage.setItem(Events.NPS.SUBMITTED, Date.now()) + + const prefixedFeedback = {} + for (let key in values) { + prefixedFeedback[`feedback_${key}`] = values[key] + } + + posthog.capture(Events.NPS.SUBMITTED, prefixedFeedback) + } +} + +// function captureEvent(eventName, props = {}) { +// if (!analyticsEnabled || !process.env.POSTHOG_TOKEN) return +// props.sourceApp = "builder" +// posthog.capture(eventName, props) +// } + +// if (!localStorage.getItem(APP_FIRST_STARTED_KEY)) { +// localStorage.setItem(APP_FIRST_STARTED_KEY, Date.now()) +// } + +// function submitFeedback(values) { +// if (!analyticsEnabled || !process.env.POSTHOG_TOKEN) return +// localStorage.setItem(FEEDBACK_SUBMITTED_KEY, Date.now()) + +// const prefixedValues = Object.entries(values).reduce((obj, [key, value]) => { +// obj[`feedback_${key}`] = value +// return obj +// }, {}) + +// posthog.capture("Feedback Submitted", prefixedValues) +// } + +// function requestFeedbackOnDeploy() { +// if (!analyticsEnabled || !process.env.POSTHOG_TOKEN) return false +// const lastSubmittedStr = localStorage.getItem(FEEDBACK_SUBMITTED_KEY) +// if (!lastSubmittedStr) return true +// return isFeedbackTimeElapsed(lastSubmittedStr) +// } + +// function highlightFeedbackIcon() { +// if (!analyticsEnabled || !process.env.POSTHOG_TOKEN) return false +// const lastSubmittedStr = localStorage.getItem(FEEDBACK_SUBMITTED_KEY) +// if (lastSubmittedStr) return isFeedbackTimeElapsed(lastSubmittedStr) +// const firstRunStr = localStorage.getItem(APP_FIRST_STARTED_KEY) +// if (!firstRunStr) return false +// return isFeedbackTimeElapsed(firstRunStr) +// } + +// Opt In/Out +// const ifAnalyticsEnabled = func => () => { +// if (analyticsEnabled && process.env.POSTHOG_TOKEN) { +// return func() +// } +// } +// const disabled = () => posthog.has_opted_out_capturing() +// const optIn = () => posthog.opt_in_capturing() +// const optOut = () => posthog.opt_out_capturing() + +// export default { +// init, +// identify, +// captureException, +// captureEvent, +// submitFeedback, +// highlightFeedbackIcon, +// disabled: () => { +// if (analyticsEnabled == null) { +// return true +// } +// return ifAnalyticsEnabled(disabled) +// }, +// optIn: ifAnalyticsEnabled(optIn), +// optOut: ifAnalyticsEnabled(optOut), +// } diff --git a/packages/builder/src/analytics/SentryClient.js b/packages/builder/src/analytics/SentryClient.js new file mode 100644 index 0000000000..11377d254f --- /dev/null +++ b/packages/builder/src/analytics/SentryClient.js @@ -0,0 +1,39 @@ +import * as Sentry from "@sentry/browser" + +export default class SentryClient { + constructor(dsn) { + this.dsn = dsn + } + + init() { + if (this.dsn) { + Sentry.init({ dsn: this.dsn }) + + this.initalised = true + } + } + + captureException(err) { + if (!this.initalised) return + + Sentry.captureException(err) + } + + identify(id) { + Sentry.configureScope(scope => { + scope.setUser({ id }) + }) + } +} + +// export function init() { +// if (process.env.SENTRY_DSN) { +// Sentry.init({ dsn: process.env.SENTRY_DSN }) +// } +// } + +// export function captureException(err) { +// // if (!analyticsEnabled) return +// Sentry.captureException(err) +// // captureEvent("Error", { error: err.message ? err.message : err }) +// } diff --git a/packages/builder/src/analytics/constants.js b/packages/builder/src/analytics/constants.js new file mode 100644 index 0000000000..1102ad3ce4 --- /dev/null +++ b/packages/builder/src/analytics/constants.js @@ -0,0 +1,49 @@ +export const Events = { + BUILDER: { + STARTED: "Builder Started" + }, + COMPONENT: { + CREATED: "Added Component" + }, + DATASOURCE: { + CREATED: "Datasource Created", + UPDATED: "Datasource Updated", + }, + TABLE: { + CREATED: "Table Created", + }, + VIEW: { + CREATED: "View Created", + ADDED_FILTER: "Added View Filter", + ADDED_CALCULATE: "Added View Calculate" + }, + SCREEN: { + CREATED: "Screen Created" + }, + AUTOMATION: { + CREATED: "Added Component", + SAVED: "Automation Saved", + BLOCK_ADDED: "Added Automation Block", + }, + NPS: { + SUBMITTED: "budibase:feedback_submitted" + }, + APP: { + CREATED: "budibase:app_created", + PUBLISHED: "budibase:app_published", + UNPUBLISHED: "budibase:app_unpublished" + }, + ANALYTICS: { + OPT_IN: "budibase:analytics_opt_in", + OPT_OUT: "budibase:analytics_opt_out" + }, + USER: { + INVITE: "budibase:portal_user_invite" + }, + SMTP: { + SAVED: "budibase:smtp_saved" + }, + SSO: { + SAVED: "budibase:sso_saved" + } +} diff --git a/packages/builder/src/analytics/index.js b/packages/builder/src/analytics/index.js new file mode 100644 index 0000000000..9fd8f82668 --- /dev/null +++ b/packages/builder/src/analytics/index.js @@ -0,0 +1,76 @@ +import api from "builderStore/api" +import PosthogClient from "./PosthogClient" +import IntercomClient from "./IntercomClient" +import SentryClient from "./SentryClient" +import { Events } from "./constants" + +// const posthog = new PosthogClient( +// process.env.POSTHOG_TOKEN, +// process.env.POSTHOG_URL +// ) +const posthog = new PosthogClient( + "phc_yGOn4i7jWKaCTapdGR6lfA4AvmuEQ2ijn5zAVSFYPlS", + "https://app.posthog.com" +) +// const sentry = new SentryClient(process.env.SENTRY_DSN) +const sentry = new SentryClient("https://a34ae347621946bf8acded18e5b7d4b8@o420233.ingest.sentry.io/5338131") +// const intercom = new IntercomClient(process.env.INTERCOM_TOKEN) +const intercom = new IntercomClient("qz2sxfuv") + + +class AnalyticsHub { + constructor() { + this.clients = [posthog, sentry, intercom] + } + + async activate() { + const analyticsStatus = await api.get("/api/analytics") + const json = await analyticsStatus.json() + + if (json.enabled) { + this.clients.forEach(client => client.init()) + } + + this.enabled = json.enabled + } + + optIn() { + this.captureEvent(Events.ANALYTICS.OPT_IN) + this.clients.forEach(client => client.optIn()) + } + + optOut() { + this.captureEvent(Events.ANALYTICS.OPT_OUT) + this.clients.forEach(client => client.optOut()) + } + + identify(id, metadata) { + posthog.identify(id) + if (metadata) { + posthog.updateUser(metadata) + } + sentry.identify(id) + } + + captureException(err) { + sentry.captureException(err) + } + + captureEvent(eventName, props = {}) { + posthog.captureEvent(eventName, props) + intercom.captureEvent(eventName, props) + } + + showChat(user) { + intercom.show(user) + } + + submitFeedback(values) { + posthog.npsFeedback(values) + } +} + +const analytics = new AnalyticsHub() + +export { Events } +export default analytics \ No newline at end of file diff --git a/packages/builder/src/builderStore/index.js b/packages/builder/src/builderStore/index.js index 6fecda84c0..fb888b6fc9 100644 --- a/packages/builder/src/builderStore/index.js +++ b/packages/builder/src/builderStore/index.js @@ -3,7 +3,7 @@ import { getAutomationStore } from "./store/automation" import { getHostingStore } from "./store/hosting" import { getThemeStore } from "./store/theme" import { derived, writable } from "svelte/store" -import analytics from "analytics" +import analytics, { Events } from "analytics" import { FrontendTypes, LAYOUT_NAMES } from "../constants" import { findComponent } from "./storeUtils" @@ -58,7 +58,7 @@ export const selectedAccessRole = writable("BASIC") export const initialise = async () => { try { await analytics.activate() - analytics.captureEvent("Builder Started") + analytics.captureEvent(Events.BUILDER.STARTED) } catch (err) { console.log(err) } diff --git a/packages/builder/src/components/deploy/DeployModal.svelte b/packages/builder/src/components/deploy/DeployModal.svelte index 4daa16c7c4..5500aff866 100644 --- a/packages/builder/src/components/deploy/DeployModal.svelte +++ b/packages/builder/src/components/deploy/DeployModal.svelte @@ -2,7 +2,8 @@ import { onMount, onDestroy } from "svelte" import { Button, Modal, notifications, ModalContent } from "@budibase/bbui" import api from "builderStore/api" - import analytics from "analytics" + import analytics, { Events } from "analytics" + import { store } from "builderStore" const DeploymentStatus = { SUCCESS: "SUCCESS", @@ -23,6 +24,9 @@ if (response.status !== 200) { throw new Error(`status ${response.status}`) } else { + analytics.captureEvent(Events.APP.PUBLISHED, { + appId: $store.appId + }) notifications.success(`Application published successfully`) } } catch (err) { diff --git a/packages/builder/src/components/start/CreateAppModal.svelte b/packages/builder/src/components/start/CreateAppModal.svelte index 4310d3322e..9ce9d746d7 100644 --- a/packages/builder/src/components/start/CreateAppModal.svelte +++ b/packages/builder/src/components/start/CreateAppModal.svelte @@ -12,7 +12,7 @@ import { admin } from "stores/portal" import { string, mixed, object } from "yup" import api, { get, post } from "builderStore/api" - import analytics from "analytics" + import analytics, { Events } from "analytics" import { onMount } from "svelte" import { capitalise } from "helpers" import { goto } from "@roxi/routify" @@ -98,9 +98,9 @@ throw new Error(appJson.message) } - analytics.captureEvent("App Created", { + analytics.captureEvent(Events.APP.CREATED, { name: $values.name, - appId: appJson._id, + appId: appJson.instance._id, template, }) diff --git a/packages/builder/src/pages/builder/auth/login.svelte b/packages/builder/src/pages/builder/auth/login.svelte index 783e5a4903..568a0550a3 100644 --- a/packages/builder/src/pages/builder/auth/login.svelte +++ b/packages/builder/src/pages/builder/auth/login.svelte @@ -15,6 +15,7 @@ import OIDCButton from "./_components/OIDCButton.svelte" import Logo from "assets/bb-emblem.svg" import { onMount } from "svelte" + import analytics from "analytics" let username = "" let password = "" @@ -25,10 +26,20 @@ async function login() { try { - await auth.login({ + const { user } = await auth.login({ username, password, }) + + analytics.identify(user._id, user) + analytics.showChat({ + email: user.email, + created_at: Date.now(), + name: user.name, + user_id: user._id, + tenant: user.tenantId + }) + if ($auth?.user?.forceResetPassword) { $goto("./reset") } else { diff --git a/packages/builder/src/pages/builder/portal/apps/index.svelte b/packages/builder/src/pages/builder/portal/apps/index.svelte index a18ec6a8bd..319a00f471 100644 --- a/packages/builder/src/pages/builder/portal/apps/index.svelte +++ b/packages/builder/src/pages/builder/portal/apps/index.svelte @@ -69,9 +69,9 @@ const checkKeys = async () => { const response = await api.get(`/api/keys/`) const keys = await response.json() - if (keys.userId) { - analytics.identify(keys.userId) - } + // if (keys.userId) { + // analytics.identify(keys.userId) + // } } const initiateAppCreation = () => { diff --git a/packages/builder/src/pages/builder/portal/manage/auth/index.svelte b/packages/builder/src/pages/builder/portal/manage/auth/index.svelte index 48d9da18f9..c2445e14ae 100644 --- a/packages/builder/src/pages/builder/portal/manage/auth/index.svelte +++ b/packages/builder/src/pages/builder/portal/manage/auth/index.svelte @@ -23,6 +23,7 @@ import api from "builderStore/api" import { organisation, auth, admin } from "stores/portal" import { uuid } from "builderStore/uuid" + import analytics, { Events } from "analytics" $: tenantId = $auth.tenantId $: multiTenancyEnabled = $admin.multiTenancy @@ -209,6 +210,7 @@ providers[res.type]._id = res._id }) notifications.success(`Settings saved.`) + analytics.captureEvent(Events.SSO.SAVED) }) .catch(err => { notifications.error(`Failed to update auth settings. ${err}`) diff --git a/packages/builder/src/pages/builder/portal/manage/email/index.svelte b/packages/builder/src/pages/builder/portal/manage/email/index.svelte index 76d98ed545..5a78623b81 100644 --- a/packages/builder/src/pages/builder/portal/manage/email/index.svelte +++ b/packages/builder/src/pages/builder/portal/manage/email/index.svelte @@ -16,6 +16,7 @@ import { email } from "stores/portal" import api from "builderStore/api" import { cloneDeep } from "lodash/fp" + import analytics, { Events } from "analytics" const ConfigTypes = { SMTP: "smtp", @@ -69,6 +70,7 @@ smtpConfig._rev = json._rev smtpConfig._id = json._id notifications.success(`Settings saved.`) + analytics.captureEvent(Events.SMTP.SAVED) } } diff --git a/packages/builder/src/pages/builder/portal/manage/users/_components/AddUserModal.svelte b/packages/builder/src/pages/builder/portal/manage/users/_components/AddUserModal.svelte index 9504f73b68..be5d6db746 100644 --- a/packages/builder/src/pages/builder/portal/manage/users/_components/AddUserModal.svelte +++ b/packages/builder/src/pages/builder/portal/manage/users/_components/AddUserModal.svelte @@ -10,6 +10,7 @@ } from "@budibase/bbui" import { createValidationStore, emailValidator } from "helpers/validation" import { users } from "stores/portal" + import analytics, { Events } from "analytics" export let disabled @@ -25,6 +26,7 @@ notifications.error(res.message) } else { notifications.success(res.message) + analytics.captureEvent(Events.USER.INVITE) } } diff --git a/packages/builder/src/pages/builder/portal/settings/organisation.svelte b/packages/builder/src/pages/builder/portal/settings/organisation.svelte index be8b60e6e7..3d149e6e60 100644 --- a/packages/builder/src/pages/builder/portal/settings/organisation.svelte +++ b/packages/builder/src/pages/builder/portal/settings/organisation.svelte @@ -25,7 +25,7 @@ } const values = writable({ - analytics: !analytics.disabled(), + analytics: analytics.enabled, company: $organisation.company, platformUrl: $organisation.platformUrl, logo: $organisation.logoUrl diff --git a/packages/builder/vite.config.js b/packages/builder/vite.config.js index d8b8dbba1d..12b45e7cf8 100644 --- a/packages/builder/vite.config.js +++ b/packages/builder/vite.config.js @@ -22,6 +22,9 @@ export default ({ mode }) => { isProduction ? "production" : "development" ), "process.env.POSTHOG_TOKEN": JSON.stringify(process.env.POSTHOG_TOKEN), + "process.env.INTERCOM_TOKEN": JSON.stringify( + process.env.INTERCOM_TOKEN + ), "process.env.POSTHOG_URL": JSON.stringify(process.env.POSTHOG_URL), "process.env.SENTRY_DSN": JSON.stringify(process.env.SENTRY_DSN), }),