From bee0361523213f37bed39639c3ba43124b261fcf Mon Sep 17 00:00:00 2001 From: Ryan Martin Date: Wed, 11 Sep 2024 22:13:10 +0700 Subject: [PATCH 1/5] feat: setup posthog --- .env.example | 2 ++ package.json | 1 + pnpm-lock.yaml | 27 +++++++++++++++++++++ src/components/sheets/edit-entity-group.tsx | 12 +++++++++ src/components/sheets/new-entity-group.tsx | 9 ++++++- src/components/sidebar/messages.tsx | 6 +++++ src/components/sidebar/persona.tsx | 6 +++++ src/components/sidebar/queries.tsx | 13 ++++++++-- src/main.tsx | 22 +++++++++++------ 9 files changed, 88 insertions(+), 10 deletions(-) create mode 100644 .env.example diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..c130e40 --- /dev/null +++ b/.env.example @@ -0,0 +1,2 @@ +VITE_SENTRY_DSN= +VITE_POSTHOG_KEY= diff --git a/package.json b/package.json index 710ef94..b510b94 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "class-variance-authority": "^0.7.0", "clsx": "^2.1.0", "lucide-react": "^0.334.0", + "posthog-js": "^1.161.3", "react": "^18.2.0", "react-dom": "^18.2.0", "react-hook-form": "^7.51.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a081534..ea1712a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -62,6 +62,9 @@ importers: lucide-react: specifier: ^0.334.0 version: 0.334.0(react@18.2.0) + posthog-js: + specifier: ^1.161.3 + version: 1.161.3 react: specifier: ^18.2.0 version: 18.2.0 @@ -1781,6 +1784,9 @@ packages: fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + fflate@0.4.8: + resolution: {integrity: sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==} + file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -2365,6 +2371,12 @@ packages: resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} engines: {node: ^10 || ^12 || >=14} + posthog-js@1.161.3: + resolution: {integrity: sha512-TQ77jtLemkUJUyJAPrwGay6tLqcAmXEM1IJgXOx5Tr4UohiTx8JTznzrCuh/SdwPIrbcSM1r2YPwb72XwTC3wg==} + + preact@10.23.2: + resolution: {integrity: sha512-kKYfePf9rzKnxOAKDpsWhg/ysrHPqT+yQ7UW4JjdnqjFIeNUnNcEJvhuA8fDenxAGWzUqtd51DfVg7xp/8T9NA==} + prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -2774,6 +2786,9 @@ packages: terser: optional: true + web-vitals@4.2.3: + resolution: {integrity: sha512-/CFAm1mNxSmOj6i0Co+iGFJ58OS4NRGVP+AWS/l509uIK5a1bSoIVaHz/ZumpHTfHSZBpgrJ+wjfpAOrTHok5Q==} + webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} @@ -4695,6 +4710,8 @@ snapshots: dependencies: reusify: 1.0.4 + fflate@0.4.8: {} + file-entry-cache@6.0.1: dependencies: flat-cache: 3.2.0 @@ -5245,6 +5262,14 @@ snapshots: picocolors: 1.0.0 source-map-js: 1.2.0 + posthog-js@1.161.3: + dependencies: + fflate: 0.4.8 + preact: 10.23.2 + web-vitals: 4.2.3 + + preact@10.23.2: {} + prelude-ls@1.2.1: {} prettier-linter-helpers@1.0.0: @@ -5709,6 +5734,8 @@ snapshots: '@types/node': 20.12.4 fsevents: 2.3.3 + web-vitals@4.2.3: {} + webidl-conversions@3.0.1: {} webpack-sources@3.2.3: {} diff --git a/src/components/sheets/edit-entity-group.tsx b/src/components/sheets/edit-entity-group.tsx index c4f6a55..c5f5c5f 100644 --- a/src/components/sheets/edit-entity-group.tsx +++ b/src/components/sheets/edit-entity-group.tsx @@ -1,6 +1,7 @@ import { zodResolver } from '@hookform/resolvers/zod' import { useQuery } from '@tanstack/react-query' import { ChevronsUpDown, Edit, X } from 'lucide-react' +import { usePostHog } from 'posthog-js/react' import { useState } from 'react' import { useForm } from 'react-hook-form' import { z } from 'zod' @@ -73,6 +74,7 @@ export function EditEntityGroupSheet({ entityGroup }: EditEntityGroupProps) { defaultValues: entityGroup, }) const [open, setOpen] = useState(false) + const posthog = usePostHog() const originalName = entityGroup.name const components = data?.components ?? [] @@ -95,6 +97,13 @@ export function EditEntityGroupSheet({ entityGroup }: EditEntityGroupProps) { toast({ title: 'Successfully updated entity group', }) + const fieldsUpdated = Object.keys(entityGroup).filter((k) => { + const key = k as 'name' | 'components' + return entityGroup[key] !== values[key] + }) + posthog.capture('Entity Group Edited', { + fieldsUpdated: fieldsUpdated, + }) } const handleDelete = () => { const newEntityGroups = entityGroups.filter((eg) => eg.name !== originalName) @@ -103,6 +112,9 @@ export function EditEntityGroupSheet({ entityGroup }: EditEntityGroupProps) { toast({ title: 'Successfully deleted entity group', }) + posthog.capture('Entity Group Deleted', { + componentsCount: entityGroup.components.length, + }) } return ( diff --git a/src/components/sheets/new-entity-group.tsx b/src/components/sheets/new-entity-group.tsx index 32b1e81..2e34792 100644 --- a/src/components/sheets/new-entity-group.tsx +++ b/src/components/sheets/new-entity-group.tsx @@ -1,6 +1,7 @@ import { zodResolver } from '@hookform/resolvers/zod' import { useQuery } from '@tanstack/react-query' import { ChevronsUpDown, X } from 'lucide-react' +import { usePostHog } from 'posthog-js/react' import { useState } from 'react' import { useForm } from 'react-hook-form' import { z } from 'zod' @@ -59,6 +60,7 @@ export function NewEntityGroupSheet() { }, }) const [open, setOpen] = useState(false) + const posthog = usePostHog() const components = data?.components ?? [] const options = components.map((c) => ({ label: c.name, value: c.name })) ?? [] @@ -84,12 +86,17 @@ export function NewEntityGroupSheet() { toast({ title: 'Successfully created entity group', }) + posthog.capture('Entity Group Created', { + componentsCount: values.components.length, + }) } return ( - +
diff --git a/src/components/sidebar/messages.tsx b/src/components/sidebar/messages.tsx index 30723a8..c0bb284 100644 --- a/src/components/sidebar/messages.tsx +++ b/src/components/sidebar/messages.tsx @@ -1,6 +1,7 @@ import { zodResolver } from '@hookform/resolvers/zod' import { useQueryClient } from '@tanstack/react-query' import { BookDashed, MessageSquareCode, Loader } from 'lucide-react' +import { usePostHog } from 'posthog-js/react' import { useForm } from 'react-hook-form' import { @@ -83,6 +84,7 @@ function Message({ message, namespace }: MessageProp) { defaultValues: defaultValues(message), }) const { toast } = useToast() + const posthog = usePostHog() const handleSubmit = async (values: ComponentProperty) => { const { persona: personaTag, ...fields } = values @@ -112,8 +114,12 @@ function Message({ message, namespace }: MessageProp) { return p.personaTag === personaTag ? { ...p, nonce: p.nonce + 1 } : p }), ) + posthog.capture('Message Submitted') } catch (error) { errorToast(toast, error, 'Failed to send message') + posthog.capture('Failed to Submit Message', { + error: error, + }) } } diff --git a/src/components/sidebar/persona.tsx b/src/components/sidebar/persona.tsx index afcdd41..559f728 100644 --- a/src/components/sidebar/persona.tsx +++ b/src/components/sidebar/persona.tsx @@ -1,6 +1,7 @@ import { zodResolver } from '@hookform/resolvers/zod' import { useQueryClient } from '@tanstack/react-query' import { Loader } from 'lucide-react' +import { usePostHog } from 'posthog-js/react' import { useForm } from 'react-hook-form' import { z } from 'zod' @@ -49,6 +50,7 @@ export function CreatePersona({ namespace }: CreatePersonaProps) { }, }) const { toast } = useToast() + const posthog = usePostHog() const handleSubmit = async ({ personaTag }: z.infer) => { const { privateKey, address, sign } = createPersonaAccount(personaTag) @@ -93,8 +95,12 @@ export function CreatePersona({ namespace }: CreatePersonaProps) { // only set the personas if there is no error const newPersona = { personaTag, privateKey, address, nonce: nonce + 1 } setPersonas([...personas, newPersona]) + posthog.capture('Persona Created') } catch (error) { errorToast(toast, error, 'Error creating persona') + posthog.capture('Failed to Create Persona', { + error: error, + }) } } diff --git a/src/components/sidebar/queries.tsx b/src/components/sidebar/queries.tsx index bf5d260..7e178dd 100644 --- a/src/components/sidebar/queries.tsx +++ b/src/components/sidebar/queries.tsx @@ -1,6 +1,7 @@ import { zodResolver } from '@hookform/resolvers/zod' import { useQueryClient } from '@tanstack/react-query' import { BookDashed, Loader, SearchCode } from 'lucide-react' +import { usePostHog } from 'posthog-js/react' import { useForm } from 'react-hook-form' import { @@ -82,6 +83,7 @@ function Query({ query }: QueryProp) { defaultValues: defaultValues(query), }) const { toast } = useToast() + const posthog = usePostHog() const handleSubmit = (values: ComponentProperty) => { queryClient @@ -93,8 +95,15 @@ function Query({ query }: QueryProp) { body: values, }), ) - .then(() => true) - .catch((error) => errorToast(toast, error, 'Error sending query')) + .then(() => { + posthog.capture('Query Submitted') + }) + .catch((error) => { + errorToast(toast, error, 'Error sending query') + posthog.capture('Failed to Submit Query', { + error: error as string, + }) + }) } return ( diff --git a/src/main.tsx b/src/main.tsx index 1d04eca..87ef18d 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,6 +1,7 @@ import * as Sentry from '@sentry/react' import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { RouterProvider, createRouter } from '@tanstack/react-router' +import { PostHogProvider } from 'posthog-js/react' import { StrictMode } from 'react' import ReactDOM from 'react-dom/client' @@ -52,18 +53,25 @@ Sentry.init({ profilesSampleRate: 1.0, }) +const postHogConfig = { + apiKey: import.meta.env.VITE_POSTHOG_KEY as string, + options: {}, +} + const rootElement = document.getElementById('root')! if (!rootElement.innerHTML) { const root = ReactDOM.createRoot(rootElement) root.render( - - - - - - - + + + + + + + + + , ) } From 5b7c0de7893be098d0a4cb6fcf647e06ed51689e Mon Sep 17 00:00:00 2001 From: Ryan Martin Date: Wed, 18 Sep 2024 15:19:00 +0700 Subject: [PATCH 2/5] feat: use web analytics instead of product analytics --- src/components/sheets/edit-entity-group.tsx | 12 ------------ src/components/sheets/new-entity-group.tsx | 9 +-------- src/components/sidebar/messages.tsx | 6 ------ src/components/sidebar/persona.tsx | 6 ------ src/components/sidebar/queries.tsx | 13 ++----------- src/main.tsx | 5 ++++- src/routes/__root.tsx | 4 ++++ 7 files changed, 11 insertions(+), 44 deletions(-) diff --git a/src/components/sheets/edit-entity-group.tsx b/src/components/sheets/edit-entity-group.tsx index c5f5c5f..c4f6a55 100644 --- a/src/components/sheets/edit-entity-group.tsx +++ b/src/components/sheets/edit-entity-group.tsx @@ -1,7 +1,6 @@ import { zodResolver } from '@hookform/resolvers/zod' import { useQuery } from '@tanstack/react-query' import { ChevronsUpDown, Edit, X } from 'lucide-react' -import { usePostHog } from 'posthog-js/react' import { useState } from 'react' import { useForm } from 'react-hook-form' import { z } from 'zod' @@ -74,7 +73,6 @@ export function EditEntityGroupSheet({ entityGroup }: EditEntityGroupProps) { defaultValues: entityGroup, }) const [open, setOpen] = useState(false) - const posthog = usePostHog() const originalName = entityGroup.name const components = data?.components ?? [] @@ -97,13 +95,6 @@ export function EditEntityGroupSheet({ entityGroup }: EditEntityGroupProps) { toast({ title: 'Successfully updated entity group', }) - const fieldsUpdated = Object.keys(entityGroup).filter((k) => { - const key = k as 'name' | 'components' - return entityGroup[key] !== values[key] - }) - posthog.capture('Entity Group Edited', { - fieldsUpdated: fieldsUpdated, - }) } const handleDelete = () => { const newEntityGroups = entityGroups.filter((eg) => eg.name !== originalName) @@ -112,9 +103,6 @@ export function EditEntityGroupSheet({ entityGroup }: EditEntityGroupProps) { toast({ title: 'Successfully deleted entity group', }) - posthog.capture('Entity Group Deleted', { - componentsCount: entityGroup.components.length, - }) } return ( diff --git a/src/components/sheets/new-entity-group.tsx b/src/components/sheets/new-entity-group.tsx index 2e34792..32b1e81 100644 --- a/src/components/sheets/new-entity-group.tsx +++ b/src/components/sheets/new-entity-group.tsx @@ -1,7 +1,6 @@ import { zodResolver } from '@hookform/resolvers/zod' import { useQuery } from '@tanstack/react-query' import { ChevronsUpDown, X } from 'lucide-react' -import { usePostHog } from 'posthog-js/react' import { useState } from 'react' import { useForm } from 'react-hook-form' import { z } from 'zod' @@ -60,7 +59,6 @@ export function NewEntityGroupSheet() { }, }) const [open, setOpen] = useState(false) - const posthog = usePostHog() const components = data?.components ?? [] const options = components.map((c) => ({ label: c.name, value: c.name })) ?? [] @@ -86,17 +84,12 @@ export function NewEntityGroupSheet() { toast({ title: 'Successfully created entity group', }) - posthog.capture('Entity Group Created', { - componentsCount: values.components.length, - }) } return ( - + diff --git a/src/components/sidebar/messages.tsx b/src/components/sidebar/messages.tsx index c0bb284..30723a8 100644 --- a/src/components/sidebar/messages.tsx +++ b/src/components/sidebar/messages.tsx @@ -1,7 +1,6 @@ import { zodResolver } from '@hookform/resolvers/zod' import { useQueryClient } from '@tanstack/react-query' import { BookDashed, MessageSquareCode, Loader } from 'lucide-react' -import { usePostHog } from 'posthog-js/react' import { useForm } from 'react-hook-form' import { @@ -84,7 +83,6 @@ function Message({ message, namespace }: MessageProp) { defaultValues: defaultValues(message), }) const { toast } = useToast() - const posthog = usePostHog() const handleSubmit = async (values: ComponentProperty) => { const { persona: personaTag, ...fields } = values @@ -114,12 +112,8 @@ function Message({ message, namespace }: MessageProp) { return p.personaTag === personaTag ? { ...p, nonce: p.nonce + 1 } : p }), ) - posthog.capture('Message Submitted') } catch (error) { errorToast(toast, error, 'Failed to send message') - posthog.capture('Failed to Submit Message', { - error: error, - }) } } diff --git a/src/components/sidebar/persona.tsx b/src/components/sidebar/persona.tsx index 559f728..afcdd41 100644 --- a/src/components/sidebar/persona.tsx +++ b/src/components/sidebar/persona.tsx @@ -1,7 +1,6 @@ import { zodResolver } from '@hookform/resolvers/zod' import { useQueryClient } from '@tanstack/react-query' import { Loader } from 'lucide-react' -import { usePostHog } from 'posthog-js/react' import { useForm } from 'react-hook-form' import { z } from 'zod' @@ -50,7 +49,6 @@ export function CreatePersona({ namespace }: CreatePersonaProps) { }, }) const { toast } = useToast() - const posthog = usePostHog() const handleSubmit = async ({ personaTag }: z.infer) => { const { privateKey, address, sign } = createPersonaAccount(personaTag) @@ -95,12 +93,8 @@ export function CreatePersona({ namespace }: CreatePersonaProps) { // only set the personas if there is no error const newPersona = { personaTag, privateKey, address, nonce: nonce + 1 } setPersonas([...personas, newPersona]) - posthog.capture('Persona Created') } catch (error) { errorToast(toast, error, 'Error creating persona') - posthog.capture('Failed to Create Persona', { - error: error, - }) } } diff --git a/src/components/sidebar/queries.tsx b/src/components/sidebar/queries.tsx index 7e178dd..bf5d260 100644 --- a/src/components/sidebar/queries.tsx +++ b/src/components/sidebar/queries.tsx @@ -1,7 +1,6 @@ import { zodResolver } from '@hookform/resolvers/zod' import { useQueryClient } from '@tanstack/react-query' import { BookDashed, Loader, SearchCode } from 'lucide-react' -import { usePostHog } from 'posthog-js/react' import { useForm } from 'react-hook-form' import { @@ -83,7 +82,6 @@ function Query({ query }: QueryProp) { defaultValues: defaultValues(query), }) const { toast } = useToast() - const posthog = usePostHog() const handleSubmit = (values: ComponentProperty) => { queryClient @@ -95,15 +93,8 @@ function Query({ query }: QueryProp) { body: values, }), ) - .then(() => { - posthog.capture('Query Submitted') - }) - .catch((error) => { - errorToast(toast, error, 'Error sending query') - posthog.capture('Failed to Submit Query', { - error: error as string, - }) - }) + .then(() => true) + .catch((error) => errorToast(toast, error, 'Error sending query')) } return ( diff --git a/src/main.tsx b/src/main.tsx index 87ef18d..2750b52 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -55,7 +55,10 @@ Sentry.init({ const postHogConfig = { apiKey: import.meta.env.VITE_POSTHOG_KEY as string, - options: {}, + options: { + person_profiles: 'identified_only', + capture_pageview: false, + }, } const rootElement = document.getElementById('root')! diff --git a/src/routes/__root.tsx b/src/routes/__root.tsx index 67fe6c1..b121e27 100644 --- a/src/routes/__root.tsx +++ b/src/routes/__root.tsx @@ -1,6 +1,7 @@ import * as Sentry from '@sentry/react' import { useQueryClient } from '@tanstack/react-query' import { createRootRoute, Outlet } from '@tanstack/react-router' +import posthog from 'posthog-js' import { useEffect } from 'react' import { BottomBar } from '@/components/bottom-bar' @@ -22,6 +23,9 @@ import { cn, errorToast } from '@/lib/utils' export const Route = createRootRoute({ component: Root, + beforeLoad: (route) => { + posthog.capture('$pageview', { path: route.location.pathname }) + }, }) interface CardinalEvent { From 0f87a345f31c75c36b42c70038e7b220255f7faa Mon Sep 17 00:00:00 2001 From: Ryan Martin Date: Wed, 18 Sep 2024 15:29:15 +0700 Subject: [PATCH 3/5] fix: type error --- src/main.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main.tsx b/src/main.tsx index 2750b52..c529546 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,6 +1,7 @@ import * as Sentry from '@sentry/react' import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { RouterProvider, createRouter } from '@tanstack/react-router' +import { PostHogConfig } from 'posthog-js' import { PostHogProvider } from 'posthog-js/react' import { StrictMode } from 'react' import ReactDOM from 'react-dom/client' @@ -58,7 +59,7 @@ const postHogConfig = { options: { person_profiles: 'identified_only', capture_pageview: false, - }, + } as PostHogConfig, } const rootElement = document.getElementById('root')! From 73ae8f453e15699e3384afc8b8da453dcd249526 Mon Sep 17 00:00:00 2001 From: Ryan Martin Date: Wed, 18 Sep 2024 16:47:37 +0700 Subject: [PATCH 4/5] ci: add build secrets --- .github/workflows/build.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index a41e989..0c7704a 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -36,6 +36,9 @@ jobs: run: pnpm install - name: Build run: pnpm build + env: + VITE_SENTRY_DSN: $${{ secrets.SENTRY_DSN }} + VITE_POSTHOG_KEY: ${{ secrets.POSTHOG_KEY }} - name: Archive Release uses: thedoctor0/zip-release@0.7.6 with: From 2cdcbd877d2dbc4776623394d8a98c4dc4f8b370 Mon Sep 17 00:00:00 2001 From: Ryan Martin Date: Wed, 25 Sep 2024 23:29:47 +0700 Subject: [PATCH 5/5] fix: typo --- .github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 0c7704a..f32a121 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -37,7 +37,7 @@ jobs: - name: Build run: pnpm build env: - VITE_SENTRY_DSN: $${{ secrets.SENTRY_DSN }} + VITE_SENTRY_DSN: ${{ secrets.SENTRY_DSN }} VITE_POSTHOG_KEY: ${{ secrets.POSTHOG_KEY }} - name: Archive Release uses: thedoctor0/zip-release@0.7.6