mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-09 15:52:40 +02:00
feat: Enhance PostHog integration with referral tracking and error handling
- Added referral code tracking in PostHog initialization to capture initial and last seen referral codes. - Wrapped PostHog capture calls in a safeCapture function to prevent app breakage due to ad-blockers. - Introduced PostHogReferral component in PostHogProvider for improved referral tracking.
This commit is contained in:
parent
88201d0209
commit
5e28125090
4 changed files with 156 additions and 80 deletions
|
|
@ -5,17 +5,17 @@ import posthog from "posthog-js";
|
||||||
import type { ReactNode } from "react";
|
import type { ReactNode } from "react";
|
||||||
import "../../instrumentation-client";
|
import "../../instrumentation-client";
|
||||||
import { PostHogIdentify } from "./PostHogIdentify";
|
import { PostHogIdentify } from "./PostHogIdentify";
|
||||||
|
import { PostHogReferral } from "./PostHogReferral";
|
||||||
|
|
||||||
interface PostHogProviderProps {
|
interface PostHogProviderProps {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function PostHogProvider({ children }: PostHogProviderProps) {
|
export function PostHogProvider({ children }: PostHogProviderProps) {
|
||||||
// posthog-js is initialized by importing instrumentation-client.ts above
|
|
||||||
// We wrap the app with the PostHogProvider for hook access
|
|
||||||
return (
|
return (
|
||||||
<PHProvider client={posthog}>
|
<PHProvider client={posthog}>
|
||||||
<PostHogIdentify />
|
<PostHogIdentify />
|
||||||
|
<PostHogReferral />
|
||||||
{children}
|
{children}
|
||||||
</PHProvider>
|
</PHProvider>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
34
surfsense_web/components/providers/PostHogReferral.tsx
Normal file
34
surfsense_web/components/providers/PostHogReferral.tsx
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useEffect } from "react";
|
||||||
|
import { trackReferralLanding } from "@/lib/posthog/events";
|
||||||
|
|
||||||
|
const REF_STORAGE_KEY = "surfsense_ref_code";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Captures the ?ref=<code> URL parameter on first landing and fires a
|
||||||
|
* PostHog event so marketing campaigns can be attributed.
|
||||||
|
*
|
||||||
|
* The ref code is persisted to sessionStorage so it survives client-side
|
||||||
|
* navigations that strip query params (e.g. login redirect), but a fresh
|
||||||
|
* event is fired for each new browser session with a ref param.
|
||||||
|
*/
|
||||||
|
export function PostHogReferral() {
|
||||||
|
useEffect(() => {
|
||||||
|
if (typeof window === "undefined") return;
|
||||||
|
|
||||||
|
const params = new URLSearchParams(window.location.search);
|
||||||
|
const ref = params.get("ref");
|
||||||
|
|
||||||
|
if (ref) {
|
||||||
|
try {
|
||||||
|
sessionStorage.setItem(REF_STORAGE_KEY, ref);
|
||||||
|
} catch {
|
||||||
|
// Private browsing may block sessionStorage
|
||||||
|
}
|
||||||
|
trackReferralLanding(ref, window.location.href);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
@ -1,29 +1,47 @@
|
||||||
import posthog from "posthog-js";
|
import posthog from "posthog-js";
|
||||||
|
|
||||||
function initPostHog() {
|
function initPostHog() {
|
||||||
if (!process.env.NEXT_PUBLIC_POSTHOG_KEY) return;
|
try {
|
||||||
|
if (!process.env.NEXT_PUBLIC_POSTHOG_KEY) return;
|
||||||
|
|
||||||
posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY, {
|
posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY, {
|
||||||
api_host: "/ingest",
|
api_host: "/ingest",
|
||||||
ui_host: "https://us.posthog.com",
|
ui_host: "https://us.posthog.com",
|
||||||
defaults: "2025-11-30",
|
defaults: "2025-11-30",
|
||||||
capture_pageview: "history_change",
|
capture_pageview: "history_change",
|
||||||
capture_pageleave: true,
|
capture_pageleave: true,
|
||||||
before_send: (event) => {
|
before_send: (event) => {
|
||||||
if (event.properties) {
|
if (event.properties) {
|
||||||
event.properties.$set = {
|
const params = new URLSearchParams(window.location.search);
|
||||||
...event.properties.$set,
|
const ref = params.get("ref");
|
||||||
last_seen_at: new Date().toISOString(),
|
if (ref) {
|
||||||
};
|
event.properties.ref_code = ref;
|
||||||
}
|
event.properties.$set = {
|
||||||
return event;
|
...event.properties.$set,
|
||||||
},
|
initial_ref_code: ref,
|
||||||
loaded: (ph) => {
|
};
|
||||||
if (typeof window !== "undefined") {
|
event.properties.$set_once = {
|
||||||
window.posthog = ph;
|
...event.properties.$set_once,
|
||||||
}
|
first_ref_code: ref,
|
||||||
},
|
};
|
||||||
});
|
}
|
||||||
|
|
||||||
|
event.properties.$set = {
|
||||||
|
...event.properties.$set,
|
||||||
|
last_seen_at: new Date().toISOString(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return event;
|
||||||
|
},
|
||||||
|
loaded: (ph) => {
|
||||||
|
if (typeof window !== "undefined") {
|
||||||
|
window.posthog = ph;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch {
|
||||||
|
// PostHog init failed (likely ad-blocker) – app must continue to work
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof window !== "undefined") {
|
if (typeof window !== "undefined") {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,10 @@ import posthog from "posthog-js";
|
||||||
/**
|
/**
|
||||||
* PostHog Analytics Event Definitions
|
* PostHog Analytics Event Definitions
|
||||||
*
|
*
|
||||||
* This file defines all custom analytics events tracked in SurfSense.
|
* All capture/identify/reset calls are wrapped in try-catch so that
|
||||||
|
* ad-blockers that interfere with posthog-js can never break app
|
||||||
|
* functionality (e.g. the chat flow).
|
||||||
|
*
|
||||||
* Events follow a consistent naming convention: category_action
|
* Events follow a consistent naming convention: category_action
|
||||||
*
|
*
|
||||||
* Categories:
|
* Categories:
|
||||||
|
|
@ -14,47 +17,47 @@ import posthog from "posthog-js";
|
||||||
* - connector: External connector events
|
* - connector: External connector events
|
||||||
* - contact: Contact form events
|
* - contact: Contact form events
|
||||||
* - settings: Settings changes
|
* - settings: Settings changes
|
||||||
|
* - marketing: Marketing/referral tracking
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
function safeCapture(event: string, properties?: Record<string, unknown>) {
|
||||||
|
try {
|
||||||
|
posthog.capture(event, properties);
|
||||||
|
} catch {
|
||||||
|
// Silently ignore – analytics should never break the app
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
// AUTH EVENTS
|
// AUTH EVENTS
|
||||||
// ============================================
|
// ============================================
|
||||||
|
|
||||||
export function trackLoginAttempt(method: "local" | "google") {
|
export function trackLoginAttempt(method: "local" | "google") {
|
||||||
posthog.capture("auth_login_attempt", {
|
safeCapture("auth_login_attempt", { method });
|
||||||
method,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function trackLoginSuccess(method: "local" | "google") {
|
export function trackLoginSuccess(method: "local" | "google") {
|
||||||
posthog.capture("auth_login_success", {
|
safeCapture("auth_login_success", { method });
|
||||||
method,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function trackLoginFailure(method: "local" | "google", error?: string) {
|
export function trackLoginFailure(method: "local" | "google", error?: string) {
|
||||||
posthog.capture("auth_login_failure", {
|
safeCapture("auth_login_failure", { method, error });
|
||||||
method,
|
|
||||||
error,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function trackRegistrationAttempt() {
|
export function trackRegistrationAttempt() {
|
||||||
posthog.capture("auth_registration_attempt");
|
safeCapture("auth_registration_attempt");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function trackRegistrationSuccess() {
|
export function trackRegistrationSuccess() {
|
||||||
posthog.capture("auth_registration_success");
|
safeCapture("auth_registration_success");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function trackRegistrationFailure(error?: string) {
|
export function trackRegistrationFailure(error?: string) {
|
||||||
posthog.capture("auth_registration_failure", {
|
safeCapture("auth_registration_failure", { error });
|
||||||
error,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function trackLogout() {
|
export function trackLogout() {
|
||||||
posthog.capture("auth_logout");
|
safeCapture("auth_logout");
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
|
|
@ -62,20 +65,20 @@ export function trackLogout() {
|
||||||
// ============================================
|
// ============================================
|
||||||
|
|
||||||
export function trackSearchSpaceCreated(searchSpaceId: number, name: string) {
|
export function trackSearchSpaceCreated(searchSpaceId: number, name: string) {
|
||||||
posthog.capture("search_space_created", {
|
safeCapture("search_space_created", {
|
||||||
search_space_id: searchSpaceId,
|
search_space_id: searchSpaceId,
|
||||||
name,
|
name,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function trackSearchSpaceDeleted(searchSpaceId: number) {
|
export function trackSearchSpaceDeleted(searchSpaceId: number) {
|
||||||
posthog.capture("search_space_deleted", {
|
safeCapture("search_space_deleted", {
|
||||||
search_space_id: searchSpaceId,
|
search_space_id: searchSpaceId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function trackSearchSpaceViewed(searchSpaceId: number) {
|
export function trackSearchSpaceViewed(searchSpaceId: number) {
|
||||||
posthog.capture("search_space_viewed", {
|
safeCapture("search_space_viewed", {
|
||||||
search_space_id: searchSpaceId,
|
search_space_id: searchSpaceId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -85,7 +88,7 @@ export function trackSearchSpaceViewed(searchSpaceId: number) {
|
||||||
// ============================================
|
// ============================================
|
||||||
|
|
||||||
export function trackChatCreated(searchSpaceId: number, chatId: number) {
|
export function trackChatCreated(searchSpaceId: number, chatId: number) {
|
||||||
posthog.capture("chat_created", {
|
safeCapture("chat_created", {
|
||||||
search_space_id: searchSpaceId,
|
search_space_id: searchSpaceId,
|
||||||
chat_id: chatId,
|
chat_id: chatId,
|
||||||
});
|
});
|
||||||
|
|
@ -100,7 +103,7 @@ export function trackChatMessageSent(
|
||||||
messageLength?: number;
|
messageLength?: number;
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
posthog.capture("chat_message_sent", {
|
safeCapture("chat_message_sent", {
|
||||||
search_space_id: searchSpaceId,
|
search_space_id: searchSpaceId,
|
||||||
chat_id: chatId,
|
chat_id: chatId,
|
||||||
has_attachments: options?.hasAttachments ?? false,
|
has_attachments: options?.hasAttachments ?? false,
|
||||||
|
|
@ -110,14 +113,14 @@ export function trackChatMessageSent(
|
||||||
}
|
}
|
||||||
|
|
||||||
export function trackChatResponseReceived(searchSpaceId: number, chatId: number) {
|
export function trackChatResponseReceived(searchSpaceId: number, chatId: number) {
|
||||||
posthog.capture("chat_response_received", {
|
safeCapture("chat_response_received", {
|
||||||
search_space_id: searchSpaceId,
|
search_space_id: searchSpaceId,
|
||||||
chat_id: chatId,
|
chat_id: chatId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function trackChatError(searchSpaceId: number, chatId: number, error?: string) {
|
export function trackChatError(searchSpaceId: number, chatId: number, error?: string) {
|
||||||
posthog.capture("chat_error", {
|
safeCapture("chat_error", {
|
||||||
search_space_id: searchSpaceId,
|
search_space_id: searchSpaceId,
|
||||||
chat_id: chatId,
|
chat_id: chatId,
|
||||||
error,
|
error,
|
||||||
|
|
@ -133,7 +136,7 @@ export function trackDocumentUploadStarted(
|
||||||
fileCount: number,
|
fileCount: number,
|
||||||
totalSizeBytes: number
|
totalSizeBytes: number
|
||||||
) {
|
) {
|
||||||
posthog.capture("document_upload_started", {
|
safeCapture("document_upload_started", {
|
||||||
search_space_id: searchSpaceId,
|
search_space_id: searchSpaceId,
|
||||||
file_count: fileCount,
|
file_count: fileCount,
|
||||||
total_size_bytes: totalSizeBytes,
|
total_size_bytes: totalSizeBytes,
|
||||||
|
|
@ -141,35 +144,35 @@ export function trackDocumentUploadStarted(
|
||||||
}
|
}
|
||||||
|
|
||||||
export function trackDocumentUploadSuccess(searchSpaceId: number, fileCount: number) {
|
export function trackDocumentUploadSuccess(searchSpaceId: number, fileCount: number) {
|
||||||
posthog.capture("document_upload_success", {
|
safeCapture("document_upload_success", {
|
||||||
search_space_id: searchSpaceId,
|
search_space_id: searchSpaceId,
|
||||||
file_count: fileCount,
|
file_count: fileCount,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function trackDocumentUploadFailure(searchSpaceId: number, error?: string) {
|
export function trackDocumentUploadFailure(searchSpaceId: number, error?: string) {
|
||||||
posthog.capture("document_upload_failure", {
|
safeCapture("document_upload_failure", {
|
||||||
search_space_id: searchSpaceId,
|
search_space_id: searchSpaceId,
|
||||||
error,
|
error,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function trackDocumentDeleted(searchSpaceId: number, documentId: number) {
|
export function trackDocumentDeleted(searchSpaceId: number, documentId: number) {
|
||||||
posthog.capture("document_deleted", {
|
safeCapture("document_deleted", {
|
||||||
search_space_id: searchSpaceId,
|
search_space_id: searchSpaceId,
|
||||||
document_id: documentId,
|
document_id: documentId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function trackDocumentBulkDeleted(searchSpaceId: number, count: number) {
|
export function trackDocumentBulkDeleted(searchSpaceId: number, count: number) {
|
||||||
posthog.capture("document_bulk_deleted", {
|
safeCapture("document_bulk_deleted", {
|
||||||
search_space_id: searchSpaceId,
|
search_space_id: searchSpaceId,
|
||||||
count,
|
count,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function trackYouTubeImport(searchSpaceId: number, url: string) {
|
export function trackYouTubeImport(searchSpaceId: number, url: string) {
|
||||||
posthog.capture("youtube_import_started", {
|
safeCapture("youtube_import_started", {
|
||||||
search_space_id: searchSpaceId,
|
search_space_id: searchSpaceId,
|
||||||
url,
|
url,
|
||||||
});
|
});
|
||||||
|
|
@ -180,7 +183,7 @@ export function trackYouTubeImport(searchSpaceId: number, url: string) {
|
||||||
// ============================================
|
// ============================================
|
||||||
|
|
||||||
export function trackConnectorSetupStarted(searchSpaceId: number, connectorType: string) {
|
export function trackConnectorSetupStarted(searchSpaceId: number, connectorType: string) {
|
||||||
posthog.capture("connector_setup_started", {
|
safeCapture("connector_setup_started", {
|
||||||
search_space_id: searchSpaceId,
|
search_space_id: searchSpaceId,
|
||||||
connector_type: connectorType,
|
connector_type: connectorType,
|
||||||
});
|
});
|
||||||
|
|
@ -191,7 +194,7 @@ export function trackConnectorSetupSuccess(
|
||||||
connectorType: string,
|
connectorType: string,
|
||||||
connectorId: number
|
connectorId: number
|
||||||
) {
|
) {
|
||||||
posthog.capture("connector_setup_success", {
|
safeCapture("connector_setup_success", {
|
||||||
search_space_id: searchSpaceId,
|
search_space_id: searchSpaceId,
|
||||||
connector_type: connectorType,
|
connector_type: connectorType,
|
||||||
connector_id: connectorId,
|
connector_id: connectorId,
|
||||||
|
|
@ -203,7 +206,7 @@ export function trackConnectorSetupFailure(
|
||||||
connectorType: string,
|
connectorType: string,
|
||||||
error?: string
|
error?: string
|
||||||
) {
|
) {
|
||||||
posthog.capture("connector_setup_failure", {
|
safeCapture("connector_setup_failure", {
|
||||||
search_space_id: searchSpaceId,
|
search_space_id: searchSpaceId,
|
||||||
connector_type: connectorType,
|
connector_type: connectorType,
|
||||||
error,
|
error,
|
||||||
|
|
@ -215,7 +218,7 @@ export function trackConnectorDeleted(
|
||||||
connectorType: string,
|
connectorType: string,
|
||||||
connectorId: number
|
connectorId: number
|
||||||
) {
|
) {
|
||||||
posthog.capture("connector_deleted", {
|
safeCapture("connector_deleted", {
|
||||||
search_space_id: searchSpaceId,
|
search_space_id: searchSpaceId,
|
||||||
connector_type: connectorType,
|
connector_type: connectorType,
|
||||||
connector_id: connectorId,
|
connector_id: connectorId,
|
||||||
|
|
@ -227,7 +230,7 @@ export function trackConnectorSynced(
|
||||||
connectorType: string,
|
connectorType: string,
|
||||||
connectorId: number
|
connectorId: number
|
||||||
) {
|
) {
|
||||||
posthog.capture("connector_synced", {
|
safeCapture("connector_synced", {
|
||||||
search_space_id: searchSpaceId,
|
search_space_id: searchSpaceId,
|
||||||
connector_type: connectorType,
|
connector_type: connectorType,
|
||||||
connector_id: connectorId,
|
connector_id: connectorId,
|
||||||
|
|
@ -239,14 +242,14 @@ export function trackConnectorSynced(
|
||||||
// ============================================
|
// ============================================
|
||||||
|
|
||||||
export function trackSettingsViewed(searchSpaceId: number, section: string) {
|
export function trackSettingsViewed(searchSpaceId: number, section: string) {
|
||||||
posthog.capture("settings_viewed", {
|
safeCapture("settings_viewed", {
|
||||||
search_space_id: searchSpaceId,
|
search_space_id: searchSpaceId,
|
||||||
section,
|
section,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function trackSettingsUpdated(searchSpaceId: number, section: string, setting: string) {
|
export function trackSettingsUpdated(searchSpaceId: number, section: string, setting: string) {
|
||||||
posthog.capture("settings_updated", {
|
safeCapture("settings_updated", {
|
||||||
search_space_id: searchSpaceId,
|
search_space_id: searchSpaceId,
|
||||||
section,
|
section,
|
||||||
setting,
|
setting,
|
||||||
|
|
@ -258,14 +261,14 @@ export function trackSettingsUpdated(searchSpaceId: number, section: string, set
|
||||||
// ============================================
|
// ============================================
|
||||||
|
|
||||||
export function trackPodcastGenerated(searchSpaceId: number, chatId: number) {
|
export function trackPodcastGenerated(searchSpaceId: number, chatId: number) {
|
||||||
posthog.capture("podcast_generated", {
|
safeCapture("podcast_generated", {
|
||||||
search_space_id: searchSpaceId,
|
search_space_id: searchSpaceId,
|
||||||
chat_id: chatId,
|
chat_id: chatId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function trackSourcesTabViewed(searchSpaceId: number, tab: string) {
|
export function trackSourcesTabViewed(searchSpaceId: number, tab: string) {
|
||||||
posthog.capture("sources_tab_viewed", {
|
safeCapture("sources_tab_viewed", {
|
||||||
search_space_id: searchSpaceId,
|
search_space_id: searchSpaceId,
|
||||||
tab,
|
tab,
|
||||||
});
|
});
|
||||||
|
|
@ -283,7 +286,7 @@ export function trackSearchSpaceInviteSent(
|
||||||
hasMaxUses?: boolean;
|
hasMaxUses?: boolean;
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
posthog.capture("search_space_invite_sent", {
|
safeCapture("search_space_invite_sent", {
|
||||||
search_space_id: searchSpaceId,
|
search_space_id: searchSpaceId,
|
||||||
role_name: options?.roleName,
|
role_name: options?.roleName,
|
||||||
has_expiry: options?.hasExpiry ?? false,
|
has_expiry: options?.hasExpiry ?? false,
|
||||||
|
|
@ -296,7 +299,7 @@ export function trackSearchSpaceInviteAccepted(
|
||||||
searchSpaceName: string,
|
searchSpaceName: string,
|
||||||
roleName?: string | null
|
roleName?: string | null
|
||||||
) {
|
) {
|
||||||
posthog.capture("search_space_invite_accepted", {
|
safeCapture("search_space_invite_accepted", {
|
||||||
search_space_id: searchSpaceId,
|
search_space_id: searchSpaceId,
|
||||||
search_space_name: searchSpaceName,
|
search_space_name: searchSpaceName,
|
||||||
role_name: roleName,
|
role_name: roleName,
|
||||||
|
|
@ -304,7 +307,7 @@ export function trackSearchSpaceInviteAccepted(
|
||||||
}
|
}
|
||||||
|
|
||||||
export function trackSearchSpaceInviteDeclined(searchSpaceName?: string) {
|
export function trackSearchSpaceInviteDeclined(searchSpaceName?: string) {
|
||||||
posthog.capture("search_space_invite_declined", {
|
safeCapture("search_space_invite_declined", {
|
||||||
search_space_name: searchSpaceName,
|
search_space_name: searchSpaceName,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -314,7 +317,7 @@ export function trackSearchSpaceUserAdded(
|
||||||
searchSpaceName: string,
|
searchSpaceName: string,
|
||||||
roleName?: string | null
|
roleName?: string | null
|
||||||
) {
|
) {
|
||||||
posthog.capture("search_space_user_added", {
|
safeCapture("search_space_user_added", {
|
||||||
search_space_id: searchSpaceId,
|
search_space_id: searchSpaceId,
|
||||||
search_space_name: searchSpaceName,
|
search_space_name: searchSpaceName,
|
||||||
role_name: roleName,
|
role_name: roleName,
|
||||||
|
|
@ -326,7 +329,7 @@ export function trackSearchSpaceUsersViewed(
|
||||||
userCount: number,
|
userCount: number,
|
||||||
ownerCount: number
|
ownerCount: number
|
||||||
) {
|
) {
|
||||||
posthog.capture("search_space_users_viewed", {
|
safeCapture("search_space_users_viewed", {
|
||||||
search_space_id: searchSpaceId,
|
search_space_id: searchSpaceId,
|
||||||
user_count: userCount,
|
user_count: userCount,
|
||||||
owner_count: ownerCount,
|
owner_count: ownerCount,
|
||||||
|
|
@ -342,7 +345,7 @@ export function trackConnectorConnected(
|
||||||
connectorType: string,
|
connectorType: string,
|
||||||
connectorId?: number
|
connectorId?: number
|
||||||
) {
|
) {
|
||||||
posthog.capture("connector_connected", {
|
safeCapture("connector_connected", {
|
||||||
search_space_id: searchSpaceId,
|
search_space_id: searchSpaceId,
|
||||||
connector_type: connectorType,
|
connector_type: connectorType,
|
||||||
connector_id: connectorId,
|
connector_id: connectorId,
|
||||||
|
|
@ -358,7 +361,7 @@ export function trackIndexWithDateRangeOpened(
|
||||||
connectorType: string,
|
connectorType: string,
|
||||||
connectorId: number
|
connectorId: number
|
||||||
) {
|
) {
|
||||||
posthog.capture("index_with_date_range_opened", {
|
safeCapture("index_with_date_range_opened", {
|
||||||
search_space_id: searchSpaceId,
|
search_space_id: searchSpaceId,
|
||||||
connector_type: connectorType,
|
connector_type: connectorType,
|
||||||
connector_id: connectorId,
|
connector_id: connectorId,
|
||||||
|
|
@ -374,7 +377,7 @@ export function trackIndexWithDateRangeStarted(
|
||||||
hasEndDate?: boolean;
|
hasEndDate?: boolean;
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
posthog.capture("index_with_date_range_started", {
|
safeCapture("index_with_date_range_started", {
|
||||||
search_space_id: searchSpaceId,
|
search_space_id: searchSpaceId,
|
||||||
connector_type: connectorType,
|
connector_type: connectorType,
|
||||||
connector_id: connectorId,
|
connector_id: connectorId,
|
||||||
|
|
@ -388,7 +391,7 @@ export function trackQuickIndexClicked(
|
||||||
connectorType: string,
|
connectorType: string,
|
||||||
connectorId: number
|
connectorId: number
|
||||||
) {
|
) {
|
||||||
posthog.capture("quick_index_clicked", {
|
safeCapture("quick_index_clicked", {
|
||||||
search_space_id: searchSpaceId,
|
search_space_id: searchSpaceId,
|
||||||
connector_type: connectorType,
|
connector_type: connectorType,
|
||||||
connector_id: connectorId,
|
connector_id: connectorId,
|
||||||
|
|
@ -400,7 +403,7 @@ export function trackConfigurePeriodicIndexingOpened(
|
||||||
connectorType: string,
|
connectorType: string,
|
||||||
connectorId: number
|
connectorId: number
|
||||||
) {
|
) {
|
||||||
posthog.capture("configure_periodic_indexing_opened", {
|
safeCapture("configure_periodic_indexing_opened", {
|
||||||
search_space_id: searchSpaceId,
|
search_space_id: searchSpaceId,
|
||||||
connector_type: connectorType,
|
connector_type: connectorType,
|
||||||
connector_id: connectorId,
|
connector_id: connectorId,
|
||||||
|
|
@ -413,7 +416,7 @@ export function trackPeriodicIndexingStarted(
|
||||||
connectorId: number,
|
connectorId: number,
|
||||||
frequencyMinutes: number
|
frequencyMinutes: number
|
||||||
) {
|
) {
|
||||||
posthog.capture("periodic_indexing_started", {
|
safeCapture("periodic_indexing_started", {
|
||||||
search_space_id: searchSpaceId,
|
search_space_id: searchSpaceId,
|
||||||
connector_type: connectorType,
|
connector_type: connectorType,
|
||||||
connector_id: connectorId,
|
connector_id: connectorId,
|
||||||
|
|
@ -426,24 +429,37 @@ export function trackPeriodicIndexingStarted(
|
||||||
// ============================================
|
// ============================================
|
||||||
|
|
||||||
export function trackIncentivePageViewed() {
|
export function trackIncentivePageViewed() {
|
||||||
posthog.capture("incentive_page_viewed");
|
safeCapture("incentive_page_viewed");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function trackIncentiveTaskCompleted(taskType: string, pagesRewarded: number) {
|
export function trackIncentiveTaskCompleted(taskType: string, pagesRewarded: number) {
|
||||||
posthog.capture("incentive_task_completed", {
|
safeCapture("incentive_task_completed", {
|
||||||
task_type: taskType,
|
task_type: taskType,
|
||||||
pages_rewarded: pagesRewarded,
|
pages_rewarded: pagesRewarded,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function trackIncentiveTaskClicked(taskType: string) {
|
export function trackIncentiveTaskClicked(taskType: string) {
|
||||||
posthog.capture("incentive_task_clicked", {
|
safeCapture("incentive_task_clicked", {
|
||||||
task_type: taskType,
|
task_type: taskType,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function trackIncentiveContactOpened() {
|
export function trackIncentiveContactOpened() {
|
||||||
posthog.capture("incentive_contact_opened");
|
safeCapture("incentive_contact_opened");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// MARKETING / REFERRAL EVENTS
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
export function trackReferralLanding(refCode: string, landingUrl: string) {
|
||||||
|
safeCapture("marketing_referral_landing", {
|
||||||
|
ref_code: refCode,
|
||||||
|
landing_url: landingUrl,
|
||||||
|
$set_once: { first_ref_code: refCode },
|
||||||
|
$set: { latest_ref_code: refCode },
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
|
|
@ -455,12 +471,20 @@ export function trackIncentiveContactOpened() {
|
||||||
* Call this after successful authentication
|
* Call this after successful authentication
|
||||||
*/
|
*/
|
||||||
export function identifyUser(userId: string, properties?: Record<string, unknown>) {
|
export function identifyUser(userId: string, properties?: Record<string, unknown>) {
|
||||||
posthog.identify(userId, properties);
|
try {
|
||||||
|
posthog.identify(userId, properties);
|
||||||
|
} catch {
|
||||||
|
// Silently ignore – ad-blockers may break posthog
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset user identity (call on logout)
|
* Reset user identity (call on logout)
|
||||||
*/
|
*/
|
||||||
export function resetUser() {
|
export function resetUser() {
|
||||||
posthog.reset();
|
try {
|
||||||
|
posthog.reset();
|
||||||
|
} catch {
|
||||||
|
// Silently ignore – ad-blockers may break posthog
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue