Fix event capture
Some checks are pending
Runs E2E API Tests / build (20.x) (push) Waiting to run
Runs E2E API Tests / build (22.x) (push) Waiting to run
Lint & build / lint_and_build (20.x) (push) Waiting to run
Lint & build / lint_and_build (22.x) (push) Waiting to run
TOC Generator / TOC Generator (push) Waiting to run

This commit is contained in:
Konstantin Wohlwend 2024-08-14 12:49:35 -07:00
parent 0acabfe9c3
commit b99efd675b
10 changed files with 120 additions and 15 deletions

View File

@ -4,7 +4,8 @@
// List of extensions which should be recommended for users of this workspace.
"recommendations": [
"dbaeumer.vscode-eslint"
"dbaeumer.vscode-eslint",
"streetsidesoftware.code-spell-checker"
],
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
"unwantedRecommendations": [

View File

@ -28,6 +28,8 @@
"nicify",
"oidc",
"openapi",
"pageleave",
"pageview",
"posthog",
"Proxied",
"qrcode",

View File

@ -39,7 +39,7 @@
"openid-client": "^5.6.4",
"oslo": "^1.2.1",
"pg": "^8.11.3",
"posthog-js": "^1.149.1",
"posthog-node": "^4.1.0",
"react": "^18.2",
"server-only": "^0.0.1",
"sharp": "^0.32.6",

View File

@ -0,0 +1,16 @@
import { getEnvVariable } from '@stackframe/stack-shared/dist/utils/env';
import { PostHog } from 'posthog-node';
export default async function withPostHog<T>(callback: (posthog: PostHog) => Promise<T>) {
const postHogKey = getEnvVariable("NEXT_PUBLIC_POSTHOG_KEY", "phc_vIUFi0HzHo7oV26OsaZbUASqxvs8qOmap1UBYAutU4k");
const posthogClient = new PostHog(postHogKey, {
host: "https://eu.i.posthog.com",
flushAt: 1,
flushInterval: 0
});
try {
await callback(posthogClient);
} finally {
await posthogClient.shutdown();
}
}

View File

@ -4,7 +4,8 @@ import * as yup from "yup";
import { UnionToIntersection } from "@stackframe/stack-shared/dist/utils/types";
import { StackAssertionError } from "@stackframe/stack-shared/dist/utils/errors";
import { prismaClient } from "@/prisma-client";
import posthog from "posthog-js";
import withPostHog from "@/analytics";
import { generateUuid } from "@stackframe/stack-shared/dist/utils/uuids";
type EventType = {
id: string,
@ -137,13 +138,21 @@ export async function logEvent<T extends EventType[]>(
});
// log event in PostHog
for (const eventType of allEventTypes) {
const postHogEventName = `stack_${eventType.id.replace(/^\$/, "system_").replace(/-/g, "_")}`;
posthog.capture(postHogEventName, {
data,
isWide,
eventStartedAt: timeRange.start,
eventEndedAt: timeRange.end,
});
}
await withPostHog(async posthog => {
const distinctId = typeof data === "object" && data && "userId" in data ? (data.userId as string) : `backend-anon-${generateUuid()}`;
for (const eventType of allEventTypes) {
const postHogEventName = `stack_${eventType.id.replace(/^\$/, "system_").replace(/-/g, "_")}`;
posthog.capture({
event: postHogEventName,
distinctId,
timestamp: timeRange.end,
properties: {
data,
is_wide: isWide,
event_started_at: timeRange.start,
event_ended_at: timeRange.end,
},
});
}
});
}

View File

@ -80,6 +80,10 @@ const nextConfig = {
source: "/consume/:path*",
destination: "https://eu.i.posthog.com/:path*",
},
{
source: "/consume/decide",
destination: "https://eu.i.posthog.com/decide",
},
];
},
skipTrailingSlashRedirect: true,

View File

@ -17,6 +17,7 @@ import '../polyfills';
import { ClientPolyfill } from './client-polyfill';
import './globals.css';
import { CSPostHogProvider, UserIdentity } from './providers';
import dynamic from 'next/dynamic';
export const metadata: Metadata = {
metadataBase: new URL(process.env.NEXT_PUBLIC_STACK_URL_DEPRECATED || ''),
@ -41,6 +42,10 @@ type TagConfigJson = {
innerHTML?: string,
};
const PageView = dynamic(() => import('./pageview'), {
ssr: false,
});
export default function RootLayout({
children,
}: {
@ -73,6 +78,7 @@ export default function RootLayout({
suppressHydrationWarning
>
<Analytics />
<PageView />
<ThemeProvider>
<StackProvider app={stackServerApp}>
<StackTheme>

View File

@ -0,0 +1,27 @@
'use client';
import { usePathname, useSearchParams } from "next/navigation";
import { useEffect } from "react";
import { usePostHog } from 'posthog-js/react';
export default function PostHogPageView(): null {
const pathname = usePathname();
const searchParams = useSearchParams();
const posthog = usePostHog();
useEffect(() => {
if (pathname) {
let url = window.origin + pathname;
if (searchParams.toString()) {
url = url + `?${searchParams.toString()}`;
}
posthog.capture(
'$pageview',
{
'$current_url': url,
}
);
}
}, [pathname, searchParams, posthog]);
return null;
}

View File

@ -10,6 +10,8 @@ if (typeof window !== 'undefined') {
posthog.init(postHogKey, {
api_host: "/consume",
ui_host: "https://eu.i.posthog.com",
capture_pageview: false,
capture_pageleave: true,
});
}
}

View File

@ -125,9 +125,9 @@ importers:
pg:
specifier: ^8.11.3
version: 8.12.0
posthog-js:
specifier: ^1.149.1
version: 1.149.2
posthog-node:
specifier: ^4.1.0
version: 4.1.0
react:
specifier: ^18.2
version: 18.3.1
@ -4108,6 +4108,9 @@ packages:
resolution: {integrity: sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==}
engines: {node: '>=4'}
axios@1.7.4:
resolution: {integrity: sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==}
axobject-query@3.2.1:
resolution: {integrity: sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==}
@ -5216,6 +5219,15 @@ packages:
flatted@3.3.1:
resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==}
follow-redirects@1.15.6:
resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==}
engines: {node: '>=4.0'}
peerDependencies:
debug: '*'
peerDependenciesMeta:
debug:
optional: true
for-each@0.3.3:
resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==}
@ -6938,6 +6950,10 @@ packages:
posthog-js@1.149.2:
resolution: {integrity: sha512-4tNtVJkq3wZ5CvfOEp3Jtl/r3ogZb5To+bdu7JoO5QjkpTY9TV1pfo/Ag4keODpAzRDahC8OaCoIr4mY3dSK4g==}
posthog-node@4.1.0:
resolution: {integrity: sha512-Fd+aMWLjUttlPrfOniDWs35v62rOEIqP5GBzUvRswsNY8rr1g1KuDobqaRFGMCNnrtDmhzUN8y7QucrcwMY/+w==}
engines: {node: '>=15.0.0'}
preact@10.22.0:
resolution: {integrity: sha512-RRurnSjJPj4rp5K6XoP45Ui33ncb7e4H7WiOHVpjbkvqvA3U+N8Z6Qbo0AE6leGYBV66n8EhEaFixvIu3SkxFw==}
@ -7301,6 +7317,9 @@ packages:
run-parallel@1.2.0:
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
rusha@0.8.14:
resolution: {integrity: sha512-cLgakCUf6PedEu15t8kbsjnwIFFR2D4RfL+W3iWFJ4iac7z4B0ZI8fxy4R3J956kAI68HclCFGL8MPoUVC3qVA==}
rxjs@7.8.1:
resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==}
@ -11698,6 +11717,14 @@ snapshots:
axe-core@4.7.0: {}
axios@1.7.4:
dependencies:
follow-redirects: 1.15.6
form-data: 4.0.0
proxy-from-env: 1.1.0
transitivePeerDependencies:
- debug
axobject-query@3.2.1:
dependencies:
dequal: 2.0.3
@ -13038,6 +13065,8 @@ snapshots:
flatted@3.3.1: {}
follow-redirects@1.15.6: {}
for-each@0.3.3:
dependencies:
is-callable: 1.2.7
@ -15160,6 +15189,13 @@ snapshots:
preact: 10.22.0
web-vitals: 4.2.2
posthog-node@4.1.0:
dependencies:
axios: 1.7.4
rusha: 0.8.14
transitivePeerDependencies:
- debug
preact@10.22.0: {}
prebuild-install@7.1.2:
@ -15628,6 +15664,8 @@ snapshots:
dependencies:
queue-microtask: 1.2.3
rusha@0.8.14: {}
rxjs@7.8.1:
dependencies:
tslib: 2.6.3