@trakoo/posthog 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +63 -0
- package/dist/client.d.ts +25 -0
- package/dist/client.js +113 -0
- package/dist/environment.d.ts +1 -0
- package/dist/environment.js +3 -0
- package/dist/server.d.ts +29 -0
- package/dist/server.js +196 -0
- package/package.json +70 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 trakoo
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# @trakoo/posthog
|
|
2
|
+
|
|
3
|
+
PostHog providers for [trakoo](https://www.npmjs.com/package/trakoo), the typed, provider-agnostic analytics library.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Install the package with only the PostHog SDK for the side you use:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Browser
|
|
11
|
+
pnpm add trakoo @trakoo/posthog posthog-js
|
|
12
|
+
|
|
13
|
+
# Server
|
|
14
|
+
pnpm add trakoo @trakoo/posthog posthog-node
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
`appEvents` is your event registry, created with `defineEvents()` from `trakoo`.
|
|
20
|
+
|
|
21
|
+
```typescript title="lib/analytics.ts"
|
|
22
|
+
import { createClientAnalytics } from 'trakoo/client';
|
|
23
|
+
import { PostHogClientProvider } from '@trakoo/posthog/client';
|
|
24
|
+
import { appEvents } from './events';
|
|
25
|
+
|
|
26
|
+
export const analytics = createClientAnalytics({
|
|
27
|
+
events: appEvents,
|
|
28
|
+
providers: [
|
|
29
|
+
new PostHogClientProvider({
|
|
30
|
+
token: import.meta.env.VITE_POSTHOG_KEY,
|
|
31
|
+
api_host: import.meta.env.VITE_POSTHOG_HOST
|
|
32
|
+
})
|
|
33
|
+
]
|
|
34
|
+
});
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
```typescript title="lib/server-analytics.ts"
|
|
38
|
+
import { createServerAnalytics } from 'trakoo/server';
|
|
39
|
+
import { PostHogServerProvider } from '@trakoo/posthog/server';
|
|
40
|
+
import { appEvents } from './events';
|
|
41
|
+
|
|
42
|
+
export function createRequestAnalytics() {
|
|
43
|
+
return createServerAnalytics({
|
|
44
|
+
events: appEvents,
|
|
45
|
+
providers: [
|
|
46
|
+
new PostHogServerProvider({
|
|
47
|
+
apiKey: process.env.POSTHOG_API_KEY!,
|
|
48
|
+
host: 'https://us.i.posthog.com'
|
|
49
|
+
})
|
|
50
|
+
]
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
PostHog's Node client queues events. Call `shutdown()` on a request-owned instance before the request ends.
|
|
56
|
+
|
|
57
|
+
Server events take their distinct ID from each call. An event without a user is sent anonymously, without a person profile. Pass the visitor's IP and user agent as `context.server` so PostHog can locate the visitor and see their browser. The provider sends them as `$ip` and `$raw_user_agent`, and turns GeoIP on for events that carry an IP unless you set `disableGeoip`.
|
|
58
|
+
|
|
59
|
+
In the browser, PostHog captures page views on its own by default. If you call trakoo's `pageView()`, set `capture_pageview: false` so views aren't counted twice.
|
|
60
|
+
|
|
61
|
+
## Documentation
|
|
62
|
+
|
|
63
|
+
https://trakoo.co/docs/providers/posthog
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { BaseAnalyticsProvider, type BaseEvent, type EventContext } from "trakoo";
|
|
2
|
+
import type { PostHogConfig } from "posthog-js";
|
|
3
|
+
export type PostHogClientConfig = Partial<PostHogConfig> & {
|
|
4
|
+
token: string;
|
|
5
|
+
instanceName?: string;
|
|
6
|
+
debug?: boolean;
|
|
7
|
+
enabled?: boolean;
|
|
8
|
+
};
|
|
9
|
+
export declare class PostHogClientProvider extends BaseAnalyticsProvider {
|
|
10
|
+
name: string;
|
|
11
|
+
private posthog?;
|
|
12
|
+
private initialized;
|
|
13
|
+
private initializePromise?;
|
|
14
|
+
private readonly config;
|
|
15
|
+
private readonly instanceName;
|
|
16
|
+
constructor(config: PostHogClientConfig);
|
|
17
|
+
initialize(): Promise<void>;
|
|
18
|
+
private initializePostHog;
|
|
19
|
+
identify(userId: string, traits?: Record<string, unknown>): void;
|
|
20
|
+
track(event: BaseEvent, context?: EventContext): void;
|
|
21
|
+
pageView(properties?: Record<string, unknown>, context?: EventContext): void;
|
|
22
|
+
pageLeave(properties?: Record<string, unknown>, context?: EventContext): void;
|
|
23
|
+
reset(): void;
|
|
24
|
+
}
|
|
25
|
+
export type { PostHogConfig } from "posthog-js";
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { BaseAnalyticsProvider, } from "trakoo";
|
|
2
|
+
import { isBrowser } from "./environment.js";
|
|
3
|
+
let posthogProviderSequence = 0;
|
|
4
|
+
const nextInstanceName = () => `trakoo_${++posthogProviderSequence}`;
|
|
5
|
+
export class PostHogClientProvider extends BaseAnalyticsProvider {
|
|
6
|
+
name = "PostHog-Client";
|
|
7
|
+
posthog;
|
|
8
|
+
initialized = false;
|
|
9
|
+
initializePromise;
|
|
10
|
+
config;
|
|
11
|
+
instanceName;
|
|
12
|
+
constructor(config) {
|
|
13
|
+
super({ debug: config.debug, enabled: config.enabled });
|
|
14
|
+
this.config = config;
|
|
15
|
+
this.instanceName = config.instanceName ?? nextInstanceName();
|
|
16
|
+
}
|
|
17
|
+
initialize() {
|
|
18
|
+
if (!this.isEnabled() || this.initialized)
|
|
19
|
+
return Promise.resolve();
|
|
20
|
+
if (this.initializePromise)
|
|
21
|
+
return this.initializePromise;
|
|
22
|
+
// Check if we're in a browser environment
|
|
23
|
+
if (!isBrowser()) {
|
|
24
|
+
this.log("Skipping initialization - not in browser environment");
|
|
25
|
+
return Promise.resolve();
|
|
26
|
+
}
|
|
27
|
+
this.initializePromise = this.initializePostHog().catch((error) => {
|
|
28
|
+
this.initializePromise = undefined;
|
|
29
|
+
console.error(`[PostHog-Client] Failed to initialize (${this.getErrorClass(error)})`);
|
|
30
|
+
throw error;
|
|
31
|
+
});
|
|
32
|
+
return this.initializePromise;
|
|
33
|
+
}
|
|
34
|
+
async initializePostHog() {
|
|
35
|
+
// Validate config has required fields
|
|
36
|
+
if (!this.config.token || typeof this.config.token !== "string") {
|
|
37
|
+
throw new Error("PostHog requires a token");
|
|
38
|
+
}
|
|
39
|
+
// Dynamically import PostHog to avoid SSR issues
|
|
40
|
+
const { default: posthog } = await import("posthog-js");
|
|
41
|
+
const { token, instanceName: _instanceName, enabled: _enabled, debug: configDebug, ...posthogConfig } = this.config;
|
|
42
|
+
this.posthog = posthog.init(token, {
|
|
43
|
+
...posthogConfig,
|
|
44
|
+
debug: configDebug ?? this.debug,
|
|
45
|
+
}, this.instanceName);
|
|
46
|
+
this.initialized = true;
|
|
47
|
+
this.log("Initialized successfully");
|
|
48
|
+
}
|
|
49
|
+
identify(userId, traits) {
|
|
50
|
+
if (!this.isEnabled() || !this.initialized || !this.posthog)
|
|
51
|
+
return;
|
|
52
|
+
this.posthog.identify(userId, traits);
|
|
53
|
+
this.log("Identified user");
|
|
54
|
+
}
|
|
55
|
+
track(event, context) {
|
|
56
|
+
if (!this.isEnabled() || !this.initialized || !this.posthog)
|
|
57
|
+
return;
|
|
58
|
+
// `$current_url` is left to posthog-js, which reads the live location on
|
|
59
|
+
// every capture. The page context is only refreshed by pageView, and a
|
|
60
|
+
// caller's property would override the SDK's full URL.
|
|
61
|
+
//
|
|
62
|
+
// The time stays a property: posthog-js sends any capture that has an
|
|
63
|
+
// options argument, such as `timestamp`, outside its batch queue.
|
|
64
|
+
const properties = {
|
|
65
|
+
...event.properties,
|
|
66
|
+
category: event.category,
|
|
67
|
+
timestamp: event.timestamp || Date.now(),
|
|
68
|
+
...(event.userId && { userId: event.userId }),
|
|
69
|
+
...(event.sessionId && { sessionId: event.sessionId }),
|
|
70
|
+
...(context?.device && { device: context.device }),
|
|
71
|
+
...(context?.utm && { utm: context.utm }),
|
|
72
|
+
// Include user email and traits as regular event properties
|
|
73
|
+
...(context?.user?.email && { user_email: context.user.email }),
|
|
74
|
+
...(context?.user?.traits && { user_traits: context.user.traits }),
|
|
75
|
+
};
|
|
76
|
+
this.posthog.capture(event.action, properties);
|
|
77
|
+
this.log("Tracked event");
|
|
78
|
+
}
|
|
79
|
+
pageView(properties, context) {
|
|
80
|
+
if (!this.isEnabled() || !this.initialized || !this.posthog || !isBrowser())
|
|
81
|
+
return;
|
|
82
|
+
const pageProperties = {
|
|
83
|
+
...properties,
|
|
84
|
+
...(context?.page && {
|
|
85
|
+
path: context.page.path,
|
|
86
|
+
title: context.page.title,
|
|
87
|
+
referrer: context.page.referrer,
|
|
88
|
+
}),
|
|
89
|
+
};
|
|
90
|
+
this.posthog.capture("$pageview", pageProperties);
|
|
91
|
+
this.log("Tracked page view");
|
|
92
|
+
}
|
|
93
|
+
pageLeave(properties, context) {
|
|
94
|
+
if (!this.isEnabled() || !this.initialized || !this.posthog || !isBrowser())
|
|
95
|
+
return;
|
|
96
|
+
const pageLeaveProperties = {
|
|
97
|
+
...properties,
|
|
98
|
+
...(context?.page && {
|
|
99
|
+
path: context.page.path,
|
|
100
|
+
title: context.page.title,
|
|
101
|
+
referrer: context.page.referrer,
|
|
102
|
+
}),
|
|
103
|
+
};
|
|
104
|
+
this.posthog.capture("$pageleave", pageLeaveProperties);
|
|
105
|
+
this.log("Tracked page leave");
|
|
106
|
+
}
|
|
107
|
+
reset() {
|
|
108
|
+
if (!this.isEnabled() || !this.initialized || !this.posthog || !isBrowser())
|
|
109
|
+
return;
|
|
110
|
+
this.posthog.reset();
|
|
111
|
+
this.log("Reset user session");
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function isBrowser(): boolean;
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { BaseAnalyticsProvider, type BaseEvent, type EventContext } from "trakoo";
|
|
2
|
+
import type { PostHogOptions } from "posthog-node";
|
|
3
|
+
export declare class PostHogServerProvider extends BaseAnalyticsProvider {
|
|
4
|
+
name: string;
|
|
5
|
+
private client?;
|
|
6
|
+
private initialized;
|
|
7
|
+
private initializePromise?;
|
|
8
|
+
private config;
|
|
9
|
+
constructor(config: {
|
|
10
|
+
apiKey: string;
|
|
11
|
+
} & PostHogOptions & {
|
|
12
|
+
debug?: boolean;
|
|
13
|
+
enabled?: boolean;
|
|
14
|
+
});
|
|
15
|
+
initialize(): Promise<void>;
|
|
16
|
+
private initializePostHog;
|
|
17
|
+
identify(userId: string, traits?: Record<string, unknown>): void;
|
|
18
|
+
track(event: BaseEvent, context?: EventContext): void;
|
|
19
|
+
pageView(properties?: Record<string, unknown>, context?: EventContext): void;
|
|
20
|
+
/**
|
|
21
|
+
* Adds what PostHog reads from its own fields and properties: the event
|
|
22
|
+
* time, the visitor's IP and user agent, and the page and campaign. Identity
|
|
23
|
+
* comes from this call alone, because one server provider serves many users.
|
|
24
|
+
*/
|
|
25
|
+
private buildEventMessage;
|
|
26
|
+
reset(): Promise<void>;
|
|
27
|
+
shutdown(): Promise<void>;
|
|
28
|
+
}
|
|
29
|
+
export type { PostHogOptions } from "posthog-node";
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { BaseAnalyticsProvider, } from "trakoo";
|
|
2
|
+
const firstString = (...values) => {
|
|
3
|
+
for (const value of values) {
|
|
4
|
+
if (typeof value === "string" && value)
|
|
5
|
+
return value;
|
|
6
|
+
}
|
|
7
|
+
return undefined;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* The `device` context without its IP. The address travels as `$ip`, where
|
|
11
|
+
* PostHog's project setting to discard client IP data applies; a copy nested
|
|
12
|
+
* in `device` would escape that setting.
|
|
13
|
+
*/
|
|
14
|
+
const deviceWithoutIp = (device) => {
|
|
15
|
+
if (!device)
|
|
16
|
+
return undefined;
|
|
17
|
+
const { ip: _ip, ...rest } = device;
|
|
18
|
+
return Object.keys(rest).length > 0 ? rest : undefined;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* The context PostHog reads from its own standard properties: the page URL,
|
|
22
|
+
* and the campaign fields PostHog attributes traffic by.
|
|
23
|
+
*/
|
|
24
|
+
const standardProperties = (context) => {
|
|
25
|
+
const currentUrl = firstString(context?.page?.url, context?.page?.path);
|
|
26
|
+
const utm = context?.utm;
|
|
27
|
+
return {
|
|
28
|
+
...(currentUrl && { $current_url: currentUrl }),
|
|
29
|
+
...(utm?.source && { utm_source: utm.source }),
|
|
30
|
+
...(utm?.medium && { utm_medium: utm.medium }),
|
|
31
|
+
...(utm?.name && { utm_campaign: utm.name }),
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
const isMissingPackageError = (error, packageName) => {
|
|
35
|
+
try {
|
|
36
|
+
if (!error || typeof error !== "object")
|
|
37
|
+
return false;
|
|
38
|
+
const code = Reflect.get(error, "code");
|
|
39
|
+
const message = Reflect.get(error, "message");
|
|
40
|
+
if ((code !== "ERR_MODULE_NOT_FOUND" && code !== "MODULE_NOT_FOUND") ||
|
|
41
|
+
typeof message !== "string") {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
return (message.includes(`Cannot find package '${packageName}'`) ||
|
|
45
|
+
message.includes(`Cannot find module '${packageName}'`));
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
export class PostHogServerProvider extends BaseAnalyticsProvider {
|
|
52
|
+
name = "PostHog-Server";
|
|
53
|
+
client;
|
|
54
|
+
initialized = false;
|
|
55
|
+
initializePromise;
|
|
56
|
+
config;
|
|
57
|
+
constructor(config) {
|
|
58
|
+
super({ debug: config.debug, enabled: config.enabled });
|
|
59
|
+
this.config = config;
|
|
60
|
+
}
|
|
61
|
+
initialize() {
|
|
62
|
+
if (!this.isEnabled() || this.initialized)
|
|
63
|
+
return Promise.resolve();
|
|
64
|
+
if (this.initializePromise)
|
|
65
|
+
return this.initializePromise;
|
|
66
|
+
this.initializePromise = this.initializePostHog().catch((error) => {
|
|
67
|
+
this.initializePromise = undefined;
|
|
68
|
+
console.error(`[PostHog-Server] Failed to initialize (${this.getErrorClass(error)})`);
|
|
69
|
+
throw error;
|
|
70
|
+
});
|
|
71
|
+
return this.initializePromise;
|
|
72
|
+
}
|
|
73
|
+
async initializePostHog() {
|
|
74
|
+
// Validate config has required fields
|
|
75
|
+
if (!this.config.apiKey || typeof this.config.apiKey !== "string") {
|
|
76
|
+
throw new Error("PostHog requires an apiKey");
|
|
77
|
+
}
|
|
78
|
+
let PostHogClient;
|
|
79
|
+
try {
|
|
80
|
+
({ PostHog: PostHogClient } = await import("posthog-node"));
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
if (isMissingPackageError(error, "posthog-node")) {
|
|
84
|
+
throw new Error("PostHog server provider requires the optional peer package posthog-node");
|
|
85
|
+
}
|
|
86
|
+
throw error;
|
|
87
|
+
}
|
|
88
|
+
// The host is left to the SDK, whose default is PostHog's US ingestion
|
|
89
|
+
// host rather than the legacy app.posthog.com.
|
|
90
|
+
const { apiKey, ...posthogOptions } = this.config;
|
|
91
|
+
this.client = new PostHogClient(apiKey, {
|
|
92
|
+
flushAt: 20,
|
|
93
|
+
flushInterval: 10000,
|
|
94
|
+
...posthogOptions,
|
|
95
|
+
});
|
|
96
|
+
this.initialized = true;
|
|
97
|
+
this.log("Initialized successfully");
|
|
98
|
+
}
|
|
99
|
+
identify(userId, traits) {
|
|
100
|
+
if (!this.isEnabled() || !this.initialized || !this.client)
|
|
101
|
+
return;
|
|
102
|
+
this.client.identify({
|
|
103
|
+
distinctId: userId,
|
|
104
|
+
properties: traits,
|
|
105
|
+
});
|
|
106
|
+
this.log("Identified user");
|
|
107
|
+
}
|
|
108
|
+
track(event, context) {
|
|
109
|
+
if (!this.isEnabled() || !this.initialized || !this.client)
|
|
110
|
+
return;
|
|
111
|
+
const device = deviceWithoutIp(context?.device);
|
|
112
|
+
const properties = {
|
|
113
|
+
...event.properties,
|
|
114
|
+
category: event.category,
|
|
115
|
+
...(event.sessionId && { sessionId: event.sessionId }),
|
|
116
|
+
...(context?.page && {
|
|
117
|
+
$page_title: context.page.title,
|
|
118
|
+
$referrer: context.page.referrer,
|
|
119
|
+
}),
|
|
120
|
+
...(device && { device }),
|
|
121
|
+
...(context?.utm && { utm: context.utm }),
|
|
122
|
+
// Include user email and traits as regular event properties
|
|
123
|
+
...(context?.user?.email && { user_email: context.user.email }),
|
|
124
|
+
...(context?.user?.traits && { user_traits: context.user.traits }),
|
|
125
|
+
};
|
|
126
|
+
this.client.capture(this.buildEventMessage({
|
|
127
|
+
event: event.action,
|
|
128
|
+
distinctId: event.userId || context?.user?.userId,
|
|
129
|
+
properties,
|
|
130
|
+
context,
|
|
131
|
+
timestamp: event.timestamp,
|
|
132
|
+
}));
|
|
133
|
+
this.log("Tracked event");
|
|
134
|
+
}
|
|
135
|
+
pageView(properties, context) {
|
|
136
|
+
if (!this.isEnabled() || !this.initialized || !this.client)
|
|
137
|
+
return;
|
|
138
|
+
const pageProperties = {
|
|
139
|
+
...properties,
|
|
140
|
+
...(context?.page && {
|
|
141
|
+
path: context.page.path,
|
|
142
|
+
title: context.page.title,
|
|
143
|
+
referrer: context.page.referrer,
|
|
144
|
+
}),
|
|
145
|
+
};
|
|
146
|
+
this.client.capture(this.buildEventMessage({
|
|
147
|
+
event: "$pageview",
|
|
148
|
+
distinctId: context?.user?.userId || context?.user?.email,
|
|
149
|
+
properties: pageProperties,
|
|
150
|
+
context,
|
|
151
|
+
}));
|
|
152
|
+
this.log("Tracked page view");
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Adds what PostHog reads from its own fields and properties: the event
|
|
156
|
+
* time, the visitor's IP and user agent, and the page and campaign. Identity
|
|
157
|
+
* comes from this call alone, because one server provider serves many users.
|
|
158
|
+
*/
|
|
159
|
+
buildEventMessage({ event, distinctId, properties, context, timestamp, }) {
|
|
160
|
+
const ip = firstString(context?.server?.ip, context?.device?.ip);
|
|
161
|
+
const userAgent = firstString(context?.server?.userAgent, context?.device?.userAgent);
|
|
162
|
+
return {
|
|
163
|
+
// An event without a user gets a distinct ID of its own and no person
|
|
164
|
+
// profile, as PostHog recommends. A shared placeholder ID would merge
|
|
165
|
+
// every anonymous visitor into one person.
|
|
166
|
+
distinctId: distinctId || crypto.randomUUID(),
|
|
167
|
+
event,
|
|
168
|
+
properties: {
|
|
169
|
+
...properties,
|
|
170
|
+
...standardProperties(context),
|
|
171
|
+
...(ip && { $ip: ip }),
|
|
172
|
+
...(userAgent && { $raw_user_agent: userAgent }),
|
|
173
|
+
...(!distinctId && { $process_person_profile: false }),
|
|
174
|
+
},
|
|
175
|
+
...(timestamp !== undefined && { timestamp: new Date(timestamp) }),
|
|
176
|
+
// posthog-node disables GeoIP by default because it would locate the
|
|
177
|
+
// server. A forwarded visitor IP is the one to locate, unless the app
|
|
178
|
+
// configured `disableGeoip` itself.
|
|
179
|
+
...(ip &&
|
|
180
|
+
this.config.disableGeoip === undefined && { disableGeoip: false }),
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
async reset() {
|
|
184
|
+
if (!this.isEnabled() || !this.initialized || !this.client)
|
|
185
|
+
return;
|
|
186
|
+
// Flush any pending events
|
|
187
|
+
await this.client.flush();
|
|
188
|
+
this.log("Flushed pending events");
|
|
189
|
+
}
|
|
190
|
+
async shutdown() {
|
|
191
|
+
if (this.client) {
|
|
192
|
+
await this.client.shutdown();
|
|
193
|
+
this.log("Shutdown complete");
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@trakoo/posthog",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "PostHog provider for trakoo",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
"./client": {
|
|
8
|
+
"types": "./dist/client.d.ts",
|
|
9
|
+
"import": "./dist/client.js",
|
|
10
|
+
"default": "./dist/client.js"
|
|
11
|
+
},
|
|
12
|
+
"./server": {
|
|
13
|
+
"types": "./dist/server.d.ts",
|
|
14
|
+
"import": "./dist/server.js",
|
|
15
|
+
"default": "./dist/server.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"README.md",
|
|
21
|
+
"LICENSE"
|
|
22
|
+
],
|
|
23
|
+
"sideEffects": false,
|
|
24
|
+
"keywords": [
|
|
25
|
+
"analytics",
|
|
26
|
+
"trakoo",
|
|
27
|
+
"posthog",
|
|
28
|
+
"typescript"
|
|
29
|
+
],
|
|
30
|
+
"author": "Chris Jayden <https://github.com/multiplehats>",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "git+https://github.com/multiplehats/trakoo.git",
|
|
35
|
+
"directory": "packages/posthog"
|
|
36
|
+
},
|
|
37
|
+
"bugs": {
|
|
38
|
+
"url": "https://github.com/multiplehats/trakoo/issues"
|
|
39
|
+
},
|
|
40
|
+
"homepage": "https://trakoo.co/docs/providers/posthog",
|
|
41
|
+
"publishConfig": {
|
|
42
|
+
"access": "public"
|
|
43
|
+
},
|
|
44
|
+
"engines": {
|
|
45
|
+
"node": ">=20"
|
|
46
|
+
},
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"posthog-js": "^1.268.2",
|
|
49
|
+
"posthog-node": "^5.9.0",
|
|
50
|
+
"trakoo": "^1.2.1"
|
|
51
|
+
},
|
|
52
|
+
"peerDependenciesMeta": {
|
|
53
|
+
"posthog-js": {
|
|
54
|
+
"optional": true
|
|
55
|
+
},
|
|
56
|
+
"posthog-node": {
|
|
57
|
+
"optional": true
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"devDependencies": {
|
|
61
|
+
"posthog-js": "^1.434.12",
|
|
62
|
+
"posthog-node": "^5.53.0",
|
|
63
|
+
"trakoo": "1.2.1"
|
|
64
|
+
},
|
|
65
|
+
"scripts": {
|
|
66
|
+
"build": "tsc -p tsconfig.build.json",
|
|
67
|
+
"typecheck": "tsc --noEmit",
|
|
68
|
+
"test": "vitest run"
|
|
69
|
+
}
|
|
70
|
+
}
|