From 6f5c22c31dab14d19f508d4a58c71155ed6a75fa Mon Sep 17 00:00:00 2001 From: Bryant Gillespie Date: Fri, 9 Aug 2024 14:55:54 -0400 Subject: [PATCH] Add Posthog to Site (#160) * ph module * capture hubspot forms * global middleware for feature flags * fix types / change interval * small type fix * button capture for posthog * add types for pagebuilder * add experiment types * Add posthog to page * add posthog * fix url for posthog module * fix typage * fix url again * update module yet again * temp fixes * fix ui host behavior * new form logic * uncomment gtm * remove logs --- .env.example | 2 + components/Base/DirectusVideo.vue | 2 +- components/Base/HsForm.vue | 29 +++- components/Block/Button.vue | 2 + components/PageBuilder.vue | 4 +- middleware/experiments.global.ts | 21 +++ modules/posthog/index.ts | 108 ++++++++++++++ .../runtime/components/PostHogFeatureFlag.vue | 20 +++ .../composables/usePostHogFeatureFlag.ts | 23 +++ .../posthog/runtime/directives/v-capture.ts | 88 ++++++++++++ modules/posthog/runtime/plugins/directives.ts | 6 + .../posthog/runtime/plugins/posthog.client.ts | 65 +++++++++ .../posthog/runtime/plugins/posthog.server.ts | 44 ++++++ modules/posthog/runtime/types/directives.d.ts | 40 ++++++ modules/posthog/runtime/types/index.d.ts | 7 + nuxt.config.ts | 19 ++- package.json | 4 +- pages/[...permalink].vue | 66 ++++++--- plugins/directus.ts | 4 +- plugins/tv.ts | 4 +- pnpm-lock.yaml | 135 +++++++++++++++--- server/routes/rss.xml.ts | 4 +- types/schema/blocks/block-button.ts | 1 + types/schema/meta/experiment.ts | 26 ++++ types/schema/meta/index.ts | 1 + types/schema/routes/page.ts | 3 + 26 files changed, 676 insertions(+), 52 deletions(-) create mode 100644 middleware/experiments.global.ts create mode 100644 modules/posthog/index.ts create mode 100644 modules/posthog/runtime/components/PostHogFeatureFlag.vue create mode 100644 modules/posthog/runtime/composables/usePostHogFeatureFlag.ts create mode 100644 modules/posthog/runtime/directives/v-capture.ts create mode 100644 modules/posthog/runtime/plugins/directives.ts create mode 100644 modules/posthog/runtime/plugins/posthog.client.ts create mode 100644 modules/posthog/runtime/plugins/posthog.server.ts create mode 100644 modules/posthog/runtime/types/directives.d.ts create mode 100644 modules/posthog/runtime/types/index.d.ts create mode 100644 types/schema/meta/experiment.ts diff --git a/.env.example b/.env.example index 9bd52bb5..e3f27832 100644 --- a/.env.example +++ b/.env.example @@ -2,3 +2,5 @@ DIRECTUS_URL="https://your-instance.directus.app" DIRECTUS_TV_URL="https://your-instance.directus.app" GOOGLE_TAG_MANAGER_ID="GTM-PTLT3GH" NUXT_PUBLIC_SITE_URL=https://directus.io +POSTHOG_API_KEY="phc_project_api_key" +POSTHOG_API_HOST="https://us.i.posthog.com" diff --git a/components/Base/DirectusVideo.vue b/components/Base/DirectusVideo.vue index 5822a9ba..59f14763 100644 --- a/components/Base/DirectusVideo.vue +++ b/components/Base/DirectusVideo.vue @@ -19,7 +19,7 @@ export interface DirectusVideoProps { const props = defineProps(); const src = computed(() => { - const url = new URL(`/assets/${props.uuid}`, directusUrl); + const url = new URL(`/assets/${props.uuid}`, directusUrl as string); return url.toString(); }); diff --git a/components/Base/HsForm.vue b/components/Base/HsForm.vue index 6528ea88..eea6991e 100644 --- a/components/Base/HsForm.vue +++ b/components/Base/HsForm.vue @@ -15,7 +15,7 @@ const props = withDefaults(defineProps(), { const { formId } = toRefs(props); -const { $directus, $readSingleton } = useNuxtApp(); +const { $directus, $readSingleton, $posthog } = useNuxtApp(); declare global { var hbspt: any; @@ -25,12 +25,27 @@ const { data: globals } = useAsyncData('sales-reps', () => $directus.request($readSingleton('globals', { fields: ['reps'] })), ); +function formSubmitCallback(form: any, data: any) { + // Track form submission in PH + $posthog?.capture('marketing.site.forms.hubspot.submit', { + form_id: formId.value, + form_data: data, + }); + + // Redirect to meeting link on form submission + if (props.routeToMeetingLinkOnSuccess) { + routeToMeetingLinkCallback(form, data); + } +} + function routeToMeetingLinkCallback(form: any, data: any) { + const fallbackLink = 'https://directus.io/thanks'; + const reason = data.submissionValues.lets_chat_reason ?? null; const country = data.submissionValues.country_region__picklist_ ?? null; const state = data.submissionValues.state_region__picklist_ ?? null; + const redirectReasons = ["I'd like a guided demo of Directus", 'I am interested in Directus Enterprise']; const reps = unref(globals)?.reps ?? []; - const fallbackLink = 'https://directus.io/thanks'; function getSalesRepLink(country: string, state = null) { for (const rep of reps) { @@ -44,8 +59,12 @@ function routeToMeetingLinkCallback(form: any, data: any) { return fallbackLink; } - const link = getSalesRepLink(country, state); - window.location.href = link; + if (reason && redirectReasons.includes(reason)) { + const link = getSalesRepLink(country, state); + window.location.href = link; + } else { + window.location.href = fallbackLink; + } } const renderHsForm = () => { @@ -54,7 +73,7 @@ const renderHsForm = () => { portalId: '20534155', formId: unref(formId), target: `#${unref(generatedId)}`, - onFormSubmitted: props.routeToMeetingLinkOnSuccess ? routeToMeetingLinkCallback : undefined, + onFormSubmitted: formSubmitCallback, }); }; diff --git a/components/Block/Button.vue b/components/Block/Button.vue index d80106eb..e789a3dd 100644 --- a/components/Block/Button.vue +++ b/components/Block/Button.vue @@ -17,6 +17,7 @@ const { data: block } = await useAsyncData(props.uuid, () => 'icon', 'size', { page: ['permalink'], resource: ['slug', { type: ['slug'] }] }, + 'ph_event', ], }), ), @@ -44,6 +45,7 @@ const href = computed(() => {