@thisbefine/analytics 0.1.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 +403 -0
- package/dist/core/analytics.d.ts +123 -0
- package/dist/core/analytics.d.ts.map +1 -0
- package/dist/core/analytics.js +334 -0
- package/dist/core/analytics.js.map +1 -0
- package/dist/core/errors.d.ts +94 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +420 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/logger.d.ts +28 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +36 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/logging.d.ts +12 -0
- package/dist/core/logging.d.ts.map +1 -0
- package/dist/core/logging.js +33 -0
- package/dist/core/logging.js.map +1 -0
- package/dist/core/privacy.d.ts +53 -0
- package/dist/core/privacy.d.ts.map +1 -0
- package/dist/core/privacy.js +94 -0
- package/dist/core/privacy.js.map +1 -0
- package/dist/core/queue.d.ts +59 -0
- package/dist/core/queue.d.ts.map +1 -0
- package/dist/core/queue.js +263 -0
- package/dist/core/queue.js.map +1 -0
- package/dist/core/session.d.ts +90 -0
- package/dist/core/session.d.ts.map +1 -0
- package/dist/core/session.js +246 -0
- package/dist/core/session.js.map +1 -0
- package/dist/core/storage.d.ts +64 -0
- package/dist/core/storage.d.ts.map +1 -0
- package/dist/core/storage.js +242 -0
- package/dist/core/storage.js.map +1 -0
- package/dist/core/types.d.ts +298 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +34 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/validation.d.ts +11 -0
- package/dist/core/validation.d.ts.map +1 -0
- package/dist/core/validation.js +82 -0
- package/dist/core/validation.js.map +1 -0
- package/dist/core/version.d.ts +2 -0
- package/dist/core/version.d.ts.map +1 -0
- package/dist/core/version.js +4 -0
- package/dist/core/version.js.map +1 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +41 -0
- package/dist/index.js.map +1 -0
- package/dist/next/analytics.d.ts +59 -0
- package/dist/next/analytics.d.ts.map +1 -0
- package/dist/next/analytics.js +87 -0
- package/dist/next/analytics.js.map +1 -0
- package/dist/next.d.ts +46 -0
- package/dist/next.d.ts.map +1 -0
- package/dist/next.js +44 -0
- package/dist/next.js.map +1 -0
- package/dist/react/analytics.d.ts +51 -0
- package/dist/react/analytics.d.ts.map +1 -0
- package/dist/react/analytics.js +63 -0
- package/dist/react/analytics.js.map +1 -0
- package/dist/react/bug-report-widget.d.ts +21 -0
- package/dist/react/bug-report-widget.d.ts.map +1 -0
- package/dist/react/bug-report-widget.js +34 -0
- package/dist/react/bug-report-widget.js.map +1 -0
- package/dist/react/hooks.d.ts +141 -0
- package/dist/react/hooks.d.ts.map +1 -0
- package/dist/react/hooks.js +186 -0
- package/dist/react/hooks.js.map +1 -0
- package/dist/react.d.ts +42 -0
- package/dist/react.d.ts.map +1 -0
- package/dist/react.js +39 -0
- package/dist/react.js.map +1 -0
- package/dist/widget/bug-report.d.ts +16 -0
- package/dist/widget/bug-report.d.ts.map +1 -0
- package/dist/widget/bug-report.js +416 -0
- package/dist/widget/bug-report.js.map +1 -0
- package/package.json +107 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { usePathname, useSearchParams } from "next/navigation";
|
|
4
|
+
import { Suspense, useEffect, useRef } from "react";
|
|
5
|
+
import { getAnalytics, initAnalytics } from "../core/analytics";
|
|
6
|
+
/**
|
|
7
|
+
* Internal component that tracks page views using Next.js navigation hooks
|
|
8
|
+
*/
|
|
9
|
+
const PageTracker = () => {
|
|
10
|
+
const pathname = usePathname();
|
|
11
|
+
const searchParams = useSearchParams();
|
|
12
|
+
const previousPath = useRef(null);
|
|
13
|
+
const hasTrackedInitial = useRef(false);
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
const analytics = getAnalytics();
|
|
16
|
+
if (!analytics)
|
|
17
|
+
return;
|
|
18
|
+
const search = searchParams?.toString();
|
|
19
|
+
const fullPath = search ? `${pathname}?${search}` : pathname;
|
|
20
|
+
if (previousPath.current === fullPath && hasTrackedInitial.current) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
analytics.page(pathname ?? undefined, {
|
|
24
|
+
path: pathname,
|
|
25
|
+
search: search || undefined,
|
|
26
|
+
url: typeof window !== "undefined" ? window.location.href : undefined,
|
|
27
|
+
});
|
|
28
|
+
previousPath.current = fullPath;
|
|
29
|
+
hasTrackedInitial.current = true;
|
|
30
|
+
}, [pathname, searchParams]);
|
|
31
|
+
return null;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Next.js Analytics component - initializes Thisbefine analytics
|
|
35
|
+
*
|
|
36
|
+
* Optimized for the Next.js App Router with automatic pageview tracking
|
|
37
|
+
* on client-side navigations using usePathname/useSearchParams.
|
|
38
|
+
*
|
|
39
|
+
* Add this component once at the root of your app (e.g., in layout.tsx).
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```tsx
|
|
43
|
+
* // app/layout.tsx
|
|
44
|
+
* // Zero config - reads from NEXT_PUBLIC_TBF_API_KEY
|
|
45
|
+
* import { Analytics } from '@thisbefine/analytics/next';
|
|
46
|
+
*
|
|
47
|
+
* export default function RootLayout({ children }) {
|
|
48
|
+
* return (
|
|
49
|
+
* <html>
|
|
50
|
+
* <body>
|
|
51
|
+
* {children}
|
|
52
|
+
* <Analytics />
|
|
53
|
+
* </body>
|
|
54
|
+
* </html>
|
|
55
|
+
* );
|
|
56
|
+
* }
|
|
57
|
+
*
|
|
58
|
+
* // With explicit config
|
|
59
|
+
* <Analytics apiKey="tbf_xxx" host="http://localhost:3000" debug />
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export const Analytics = ({ apiKey, host, debug = false, trackPageviews = true, config, }) => {
|
|
63
|
+
const initialized = useRef(false);
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
if (initialized.current)
|
|
66
|
+
return;
|
|
67
|
+
if (typeof window === "undefined")
|
|
68
|
+
return;
|
|
69
|
+
const resolvedApiKey = apiKey ?? process.env.NEXT_PUBLIC_TBF_API_KEY ?? "";
|
|
70
|
+
if (!resolvedApiKey) {
|
|
71
|
+
console.warn("[Thisbefine] No API key provided. Set NEXT_PUBLIC_TBF_API_KEY or pass apiKey prop.");
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
initAnalytics({
|
|
75
|
+
apiKey: resolvedApiKey,
|
|
76
|
+
host,
|
|
77
|
+
debug,
|
|
78
|
+
...config,
|
|
79
|
+
});
|
|
80
|
+
initialized.current = true;
|
|
81
|
+
}, [apiKey, host, debug, config]);
|
|
82
|
+
if (!trackPageviews) {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
return (_jsx(Suspense, { fallback: null, children: _jsx(PageTracker, {}) }));
|
|
86
|
+
};
|
|
87
|
+
//# sourceMappingURL=analytics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics.js","sourceRoot":"","sources":["../../src/next/analytics.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAmChE;;GAEG;AACH,MAAM,WAAW,GAAG,GAAG,EAAE;IACxB,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,MAAM,YAAY,GAAG,eAAe,EAAE,CAAC;IACvC,MAAM,YAAY,GAAG,MAAM,CAAgB,IAAI,CAAC,CAAC;IACjD,MAAM,iBAAiB,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAExC,SAAS,CAAC,GAAG,EAAE;QACd,MAAM,SAAS,GAAG,YAAY,EAAE,CAAC;QACjC,IAAI,CAAC,SAAS;YAAE,OAAO;QAEvB,MAAM,MAAM,GAAG,YAAY,EAAE,QAAQ,EAAE,CAAC;QACxC,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,QAAQ,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;QAE7D,IAAI,YAAY,CAAC,OAAO,KAAK,QAAQ,IAAI,iBAAiB,CAAC,OAAO,EAAE,CAAC;YACpE,OAAO;QACR,CAAC;QAED,SAAS,CAAC,IAAI,CAAC,QAAQ,IAAI,SAAS,EAAE;YACrC,IAAI,EAAE,QAAQ;YACd,MAAM,EAAE,MAAM,IAAI,SAAS;YAC3B,GAAG,EAAE,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;SACrE,CAAC,CAAC;QAEH,YAAY,CAAC,OAAO,GAAG,QAAQ,CAAC;QAChC,iBAAiB,CAAC,OAAO,GAAG,IAAI,CAAC;IAClC,CAAC,EAAE,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC;IAE7B,OAAO,IAAI,CAAC;AACb,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,EACzB,MAAM,EACN,IAAI,EACJ,KAAK,GAAG,KAAK,EACb,cAAc,GAAG,IAAI,EACrB,MAAM,GACc,EAAE,EAAE;IACxB,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAElC,SAAS,CAAC,GAAG,EAAE;QACd,IAAI,WAAW,CAAC,OAAO;YAAE,OAAO;QAChC,IAAI,OAAO,MAAM,KAAK,WAAW;YAAE,OAAO;QAE1C,MAAM,cAAc,GAAG,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,EAAE,CAAC;QAE3E,IAAI,CAAC,cAAc,EAAE,CAAC;YACrB,OAAO,CAAC,IAAI,CACX,oFAAoF,CACpF,CAAC;YACF,OAAO;QACR,CAAC;QAED,aAAa,CAAC;YACb,MAAM,EAAE,cAAc;YACtB,IAAI;YACJ,KAAK;YACL,GAAG,MAAM;SACT,CAAC,CAAC;QAEH,WAAW,CAAC,OAAO,GAAG,IAAI,CAAC;IAC5B,CAAC,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;IAElC,IAAI,CAAC,cAAc,EAAE,CAAC;QACrB,OAAO,IAAI,CAAC;IACb,CAAC;IAED,OAAO,CACN,KAAC,QAAQ,IAAC,QAAQ,EAAE,IAAI,YACvB,KAAC,WAAW,KAAG,GACL,CACX,CAAC;AACH,CAAC,CAAC"}
|
package/dist/next.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @thisbefine/analytics/next
|
|
3
|
+
*
|
|
4
|
+
* Next.js integration for Thisbefine Analytics.
|
|
5
|
+
*
|
|
6
|
+
* Optimized for the App Router with automatic pageview tracking
|
|
7
|
+
* on client-side navigations using usePathname/useSearchParams.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```tsx
|
|
11
|
+
* // app/layout.tsx
|
|
12
|
+
* import { Analytics } from '@thisbefine/analytics/next';
|
|
13
|
+
*
|
|
14
|
+
* export default function RootLayout({ children }) {
|
|
15
|
+
* return (
|
|
16
|
+
* <html lang="en">
|
|
17
|
+
* <body>
|
|
18
|
+
* {children}
|
|
19
|
+
* <Analytics />
|
|
20
|
+
* </body>
|
|
21
|
+
* </html>
|
|
22
|
+
* );
|
|
23
|
+
* }
|
|
24
|
+
*
|
|
25
|
+
* // components/signup-button.tsx
|
|
26
|
+
* 'use client';
|
|
27
|
+
* import { useTrack } from '@thisbefine/analytics/next';
|
|
28
|
+
*
|
|
29
|
+
* export function SignupButton() {
|
|
30
|
+
* const trackSignup = useTrack('signup_clicked');
|
|
31
|
+
*
|
|
32
|
+
* return (
|
|
33
|
+
* <button onClick={() => trackSignup({ location: 'header' })}>
|
|
34
|
+
* Sign Up
|
|
35
|
+
* </button>
|
|
36
|
+
* );
|
|
37
|
+
* }
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* @packageDocumentation
|
|
41
|
+
*/
|
|
42
|
+
export type { AccountTraits, Analytics as AnalyticsInstance, AnalyticsConfig, UserState, UserTraits, } from "./core/types";
|
|
43
|
+
export type { NextAnalyticsProps } from "./next/analytics";
|
|
44
|
+
export { Analytics } from "./next/analytics";
|
|
45
|
+
export { useAnalytics, useCaptureException, useGetUser, useGroup, useIdentify, useLog, usePage, useReset, useTrack, } from "./react/hooks";
|
|
46
|
+
//# sourceMappingURL=next.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"next.d.ts","sourceRoot":"","sources":["../src/next.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,YAAY,EACX,aAAa,EACb,SAAS,IAAI,iBAAiB,EAC9B,eAAe,EACf,SAAS,EACT,UAAU,GACV,MAAM,cAAc,CAAC;AAEtB,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,EACN,YAAY,EACZ,mBAAmB,EACnB,UAAU,EACV,QAAQ,EACR,WAAW,EACX,MAAM,EACN,OAAO,EACP,QAAQ,EACR,QAAQ,GACR,MAAM,eAAe,CAAC"}
|
package/dist/next.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @thisbefine/analytics/next
|
|
3
|
+
*
|
|
4
|
+
* Next.js integration for Thisbefine Analytics.
|
|
5
|
+
*
|
|
6
|
+
* Optimized for the App Router with automatic pageview tracking
|
|
7
|
+
* on client-side navigations using usePathname/useSearchParams.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```tsx
|
|
11
|
+
* // app/layout.tsx
|
|
12
|
+
* import { Analytics } from '@thisbefine/analytics/next';
|
|
13
|
+
*
|
|
14
|
+
* export default function RootLayout({ children }) {
|
|
15
|
+
* return (
|
|
16
|
+
* <html lang="en">
|
|
17
|
+
* <body>
|
|
18
|
+
* {children}
|
|
19
|
+
* <Analytics />
|
|
20
|
+
* </body>
|
|
21
|
+
* </html>
|
|
22
|
+
* );
|
|
23
|
+
* }
|
|
24
|
+
*
|
|
25
|
+
* // components/signup-button.tsx
|
|
26
|
+
* 'use client';
|
|
27
|
+
* import { useTrack } from '@thisbefine/analytics/next';
|
|
28
|
+
*
|
|
29
|
+
* export function SignupButton() {
|
|
30
|
+
* const trackSignup = useTrack('signup_clicked');
|
|
31
|
+
*
|
|
32
|
+
* return (
|
|
33
|
+
* <button onClick={() => trackSignup({ location: 'header' })}>
|
|
34
|
+
* Sign Up
|
|
35
|
+
* </button>
|
|
36
|
+
* );
|
|
37
|
+
* }
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* @packageDocumentation
|
|
41
|
+
*/
|
|
42
|
+
export { Analytics } from "./next/analytics";
|
|
43
|
+
export { useAnalytics, useCaptureException, useGetUser, useGroup, useIdentify, useLog, usePage, useReset, useTrack, } from "./react/hooks";
|
|
44
|
+
//# sourceMappingURL=next.js.map
|
package/dist/next.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"next.js","sourceRoot":"","sources":["../src/next.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAWH,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,EACN,YAAY,EACZ,mBAAmB,EACnB,UAAU,EACV,QAAQ,EACR,WAAW,EACX,MAAM,EACN,OAAO,EACP,QAAQ,EACR,QAAQ,GACR,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { AnalyticsConfig } from "../core/types";
|
|
2
|
+
export interface AnalyticsProps {
|
|
3
|
+
/**
|
|
4
|
+
* Your Thisbefine API key.
|
|
5
|
+
* If not provided, reads from NEXT_PUBLIC_TBF_API_KEY environment variable.
|
|
6
|
+
*/
|
|
7
|
+
apiKey?: string;
|
|
8
|
+
/**
|
|
9
|
+
* API host URL.
|
|
10
|
+
* Defaults to https://thisbefine.com
|
|
11
|
+
* For local development, use http://localhost:3000
|
|
12
|
+
*/
|
|
13
|
+
host?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Enable debug logging to console.
|
|
16
|
+
* @default false
|
|
17
|
+
*/
|
|
18
|
+
debug?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Automatically track page views.
|
|
21
|
+
* @default true
|
|
22
|
+
*/
|
|
23
|
+
trackPageviews?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Additional configuration options
|
|
26
|
+
*/
|
|
27
|
+
config?: Omit<AnalyticsConfig, "apiKey" | "host" | "debug">;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Analytics component - initializes Thisbefine analytics
|
|
31
|
+
*
|
|
32
|
+
* Add this component once at the root of your app (e.g., in layout.tsx).
|
|
33
|
+
* It will automatically initialize analytics and track page views.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```tsx
|
|
37
|
+
* // Zero config - reads from NEXT_PUBLIC_TBF_API_KEY
|
|
38
|
+
* <Analytics />
|
|
39
|
+
*
|
|
40
|
+
* // With explicit API key
|
|
41
|
+
* <Analytics apiKey="tbf_xxx" />
|
|
42
|
+
*
|
|
43
|
+
* // For local development
|
|
44
|
+
* <Analytics apiKey="tbf_xxx" host="http://localhost:3000" />
|
|
45
|
+
*
|
|
46
|
+
* // With debug mode
|
|
47
|
+
* <Analytics debug />
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export declare const Analytics: ({ apiKey, host, debug, trackPageviews, config, }: AnalyticsProps) => null;
|
|
51
|
+
//# sourceMappingURL=analytics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../../src/react/analytics.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,MAAM,WAAW,cAAc;IAC9B;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;OAEG;IACH,MAAM,CAAC,EAAE,IAAI,CAAC,eAAe,EAAE,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;CAC5D;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,SAAS,GAAI,kDAMvB,cAAc,SA6ChB,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useEffect, useRef } from "react";
|
|
3
|
+
import { initAnalytics } from "../core/analytics";
|
|
4
|
+
/**
|
|
5
|
+
* Analytics component - initializes Thisbefine analytics
|
|
6
|
+
*
|
|
7
|
+
* Add this component once at the root of your app (e.g., in layout.tsx).
|
|
8
|
+
* It will automatically initialize analytics and track page views.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* // Zero config - reads from NEXT_PUBLIC_TBF_API_KEY
|
|
13
|
+
* <Analytics />
|
|
14
|
+
*
|
|
15
|
+
* // With explicit API key
|
|
16
|
+
* <Analytics apiKey="tbf_xxx" />
|
|
17
|
+
*
|
|
18
|
+
* // For local development
|
|
19
|
+
* <Analytics apiKey="tbf_xxx" host="http://localhost:3000" />
|
|
20
|
+
*
|
|
21
|
+
* // With debug mode
|
|
22
|
+
* <Analytics debug />
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export const Analytics = ({ apiKey, host, debug = false, trackPageviews = true, config, }) => {
|
|
26
|
+
const initialized = useRef(false);
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
if (initialized.current)
|
|
29
|
+
return;
|
|
30
|
+
if (typeof window === "undefined")
|
|
31
|
+
return;
|
|
32
|
+
const resolvedApiKey = apiKey ?? process.env.NEXT_PUBLIC_TBF_API_KEY ?? "";
|
|
33
|
+
if (!resolvedApiKey) {
|
|
34
|
+
console.warn("[Thisbefine] No API key provided. Set NEXT_PUBLIC_TBF_API_KEY or pass apiKey prop.");
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const analytics = initAnalytics({
|
|
38
|
+
apiKey: resolvedApiKey,
|
|
39
|
+
host,
|
|
40
|
+
debug,
|
|
41
|
+
...config,
|
|
42
|
+
});
|
|
43
|
+
initialized.current = true;
|
|
44
|
+
if (trackPageviews) {
|
|
45
|
+
analytics.page();
|
|
46
|
+
}
|
|
47
|
+
}, [apiKey, host, debug, trackPageviews, config]);
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
if (!trackPageviews)
|
|
50
|
+
return;
|
|
51
|
+
if (typeof window === "undefined")
|
|
52
|
+
return;
|
|
53
|
+
const handlePopState = () => {
|
|
54
|
+
import("../core/analytics").then(({ getAnalytics }) => {
|
|
55
|
+
getAnalytics()?.page();
|
|
56
|
+
});
|
|
57
|
+
};
|
|
58
|
+
window.addEventListener("popstate", handlePopState);
|
|
59
|
+
return () => window.removeEventListener("popstate", handlePopState);
|
|
60
|
+
}, [trackPageviews]);
|
|
61
|
+
return null;
|
|
62
|
+
};
|
|
63
|
+
//# sourceMappingURL=analytics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics.js","sourceRoot":"","sources":["../../src/react/analytics.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAmClD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,EACzB,MAAM,EACN,IAAI,EACJ,KAAK,GAAG,KAAK,EACb,cAAc,GAAG,IAAI,EACrB,MAAM,GACU,EAAE,EAAE;IACpB,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAElC,SAAS,CAAC,GAAG,EAAE;QACd,IAAI,WAAW,CAAC,OAAO;YAAE,OAAO;QAChC,IAAI,OAAO,MAAM,KAAK,WAAW;YAAE,OAAO;QAE1C,MAAM,cAAc,GAAG,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,EAAE,CAAC;QAE3E,IAAI,CAAC,cAAc,EAAE,CAAC;YACrB,OAAO,CAAC,IAAI,CACX,oFAAoF,CACpF,CAAC;YACF,OAAO;QACR,CAAC;QAED,MAAM,SAAS,GAAG,aAAa,CAAC;YAC/B,MAAM,EAAE,cAAc;YACtB,IAAI;YACJ,KAAK;YACL,GAAG,MAAM;SACT,CAAC,CAAC;QAEH,WAAW,CAAC,OAAO,GAAG,IAAI,CAAC;QAE3B,IAAI,cAAc,EAAE,CAAC;YACpB,SAAS,CAAC,IAAI,EAAE,CAAC;QAClB,CAAC;IACF,CAAC,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC;IAElD,SAAS,CAAC,GAAG,EAAE;QACd,IAAI,CAAC,cAAc;YAAE,OAAO;QAC5B,IAAI,OAAO,MAAM,KAAK,WAAW;YAAE,OAAO;QAE1C,MAAM,cAAc,GAAG,GAAG,EAAE;YAC3B,MAAM,CAAC,mBAAmB,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,YAAY,EAAE,EAAE,EAAE;gBACrD,YAAY,EAAE,EAAE,IAAI,EAAE,CAAC;YACxB,CAAC,CAAC,CAAC;QACJ,CAAC,CAAC;QAEF,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;QACpD,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;IACrE,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC;IAErB,OAAO,IAAI,CAAC;AACb,CAAC,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { BugReportWidgetOptions } from "../widget/bug-report";
|
|
2
|
+
export interface BugReportFABProps extends BugReportWidgetOptions {
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* React component that mounts the bug report FAB widget.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```tsx
|
|
9
|
+
* import { BugReportFAB } from '@thisbefine/analytics/react';
|
|
10
|
+
*
|
|
11
|
+
* const App = () => (
|
|
12
|
+
* <>
|
|
13
|
+
* <Analytics apiKey="tbf_xxx" />
|
|
14
|
+
* <MyApp />
|
|
15
|
+
* <BugReportFAB position="bottom-right" />
|
|
16
|
+
* </>
|
|
17
|
+
* );
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export declare const BugReportFAB: (props: BugReportFABProps) => null;
|
|
21
|
+
//# sourceMappingURL=bug-report-widget.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bug-report-widget.d.ts","sourceRoot":"","sources":["../../src/react/bug-report-widget.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAInE,MAAM,WAAW,iBAAkB,SAAQ,sBAAsB;CAAG;AAEpE;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,YAAY,GAAI,OAAO,iBAAiB,SAepD,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useEffect, useRef } from "react";
|
|
3
|
+
import { createBugReportWidget } from "../widget/bug-report";
|
|
4
|
+
import { useAnalytics } from "./hooks";
|
|
5
|
+
/**
|
|
6
|
+
* React component that mounts the bug report FAB widget.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```tsx
|
|
10
|
+
* import { BugReportFAB } from '@thisbefine/analytics/react';
|
|
11
|
+
*
|
|
12
|
+
* const App = () => (
|
|
13
|
+
* <>
|
|
14
|
+
* <Analytics apiKey="tbf_xxx" />
|
|
15
|
+
* <MyApp />
|
|
16
|
+
* <BugReportFAB position="bottom-right" />
|
|
17
|
+
* </>
|
|
18
|
+
* );
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export const BugReportFAB = (props) => {
|
|
22
|
+
const analytics = useAnalytics();
|
|
23
|
+
const destroyRef = useRef(null);
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
const widget = createBugReportWidget(analytics, props);
|
|
26
|
+
destroyRef.current = widget.destroy;
|
|
27
|
+
return () => {
|
|
28
|
+
widget.destroy();
|
|
29
|
+
destroyRef.current = null;
|
|
30
|
+
};
|
|
31
|
+
}, [analytics, props.position, props.buttonColor, props.buttonText, props]);
|
|
32
|
+
return null;
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=bug-report-widget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bug-report-widget.js","sourceRoot":"","sources":["../../src/react/bug-report-widget.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAE1C,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAIvC;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,KAAwB,EAAE,EAAE;IACxD,MAAM,SAAS,GAAG,YAAY,EAAE,CAAC;IACjC,MAAM,UAAU,GAAG,MAAM,CAAsB,IAAI,CAAC,CAAC;IAErD,SAAS,CAAC,GAAG,EAAE;QACd,MAAM,MAAM,GAAG,qBAAqB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QACvD,UAAU,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;QAEpC,OAAO,GAAG,EAAE;YACX,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,UAAU,CAAC,OAAO,GAAG,IAAI,CAAC;QAC3B,CAAC,CAAC;IACH,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC;IAE5E,OAAO,IAAI,CAAC;AACb,CAAC,CAAC"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import type { LogLevel } from "../core/logging";
|
|
2
|
+
import type { AccountTraits, Analytics, UserTraits } from "../core/types";
|
|
3
|
+
/**
|
|
4
|
+
* Hook to access the Analytics instance
|
|
5
|
+
*
|
|
6
|
+
* @throws Error if Analytics component has not been mounted
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```tsx
|
|
10
|
+
* const analytics = useAnalytics();
|
|
11
|
+
*
|
|
12
|
+
* const handleClick = () => {
|
|
13
|
+
* analytics.track('button_clicked', { buttonId: 'signup' });
|
|
14
|
+
* };
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export declare const useAnalytics: () => Analytics;
|
|
18
|
+
/**
|
|
19
|
+
* Hook to get a memoized track function for a specific event
|
|
20
|
+
*
|
|
21
|
+
* This is useful for event handlers where you want to avoid
|
|
22
|
+
* creating new function references on each render.
|
|
23
|
+
*
|
|
24
|
+
* @param eventName - The name of the event to track
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```tsx
|
|
28
|
+
* const trackSignup = useTrack('signup_clicked');
|
|
29
|
+
*
|
|
30
|
+
* return (
|
|
31
|
+
* <button onClick={() => trackSignup({ location: 'header' })}>
|
|
32
|
+
* Sign Up
|
|
33
|
+
* </button>
|
|
34
|
+
* );
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export declare const useTrack: (eventName: string) => (properties?: Record<string, unknown>) => void;
|
|
38
|
+
/**
|
|
39
|
+
* Hook to identify the current user
|
|
40
|
+
*
|
|
41
|
+
* Returns a memoized identify function.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```tsx
|
|
45
|
+
* const identify = useIdentify();
|
|
46
|
+
*
|
|
47
|
+
* // After login
|
|
48
|
+
* identify(user.id, {
|
|
49
|
+
* email: user.email,
|
|
50
|
+
* name: user.name,
|
|
51
|
+
* plan: user.plan,
|
|
52
|
+
* });
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export declare const useIdentify: () => (userId: string, traits?: UserTraits) => void;
|
|
56
|
+
/**
|
|
57
|
+
* Hook to associate the current user with an account/company
|
|
58
|
+
*
|
|
59
|
+
* Returns a memoized group function.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```tsx
|
|
63
|
+
* const group = useGroup();
|
|
64
|
+
*
|
|
65
|
+
* // After user selects workspace/company
|
|
66
|
+
* group(workspace.id, {
|
|
67
|
+
* name: workspace.name,
|
|
68
|
+
* plan: workspace.plan,
|
|
69
|
+
* mrr: workspace.mrr,
|
|
70
|
+
* });
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export declare const useGroup: () => (accountId: string, traits?: AccountTraits) => void;
|
|
74
|
+
/**
|
|
75
|
+
* Hook to track page views
|
|
76
|
+
*
|
|
77
|
+
* Returns a memoized page function.
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```tsx
|
|
81
|
+
* const trackPage = usePage();
|
|
82
|
+
*
|
|
83
|
+
* useEffect(() => {
|
|
84
|
+
* trackPage('/dashboard', { section: 'overview' });
|
|
85
|
+
* }, [trackPage]);
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
export declare const usePage: () => (name?: string, properties?: Record<string, unknown>) => void;
|
|
89
|
+
/**
|
|
90
|
+
* Hook to reset the analytics session (call on logout)
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```tsx
|
|
94
|
+
* const resetAnalytics = useReset();
|
|
95
|
+
*
|
|
96
|
+
* const handleLogout = () => {
|
|
97
|
+
* resetAnalytics();
|
|
98
|
+
* // ... other logout logic
|
|
99
|
+
* };
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
export declare const useReset: () => () => void;
|
|
103
|
+
/**
|
|
104
|
+
* Hook to get the current user state
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```tsx
|
|
108
|
+
* const getUser = useGetUser();
|
|
109
|
+
*
|
|
110
|
+
* const handleDebug = () => {
|
|
111
|
+
* console.log(getUser());
|
|
112
|
+
* // { anonymousId: '...', userId: '...', traits: { ... } }
|
|
113
|
+
* };
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
export declare const useGetUser: () => () => import("..").UserState | undefined;
|
|
117
|
+
/**
|
|
118
|
+
* Hook to capture exceptions
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* ```tsx
|
|
122
|
+
* const captureException = useCaptureException();
|
|
123
|
+
*
|
|
124
|
+
* try { ... } catch (error) {
|
|
125
|
+
* captureException(error as Error, { component: 'Checkout' });
|
|
126
|
+
* }
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
export declare const useCaptureException: () => (error: Error, context?: Record<string, unknown>) => void;
|
|
130
|
+
/**
|
|
131
|
+
* Hook to send structured log events
|
|
132
|
+
*
|
|
133
|
+
* @example
|
|
134
|
+
* ```tsx
|
|
135
|
+
* const log = useLog();
|
|
136
|
+
*
|
|
137
|
+
* log('User completed onboarding', 'info', { step: 3 });
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
140
|
+
export declare const useLog: () => (message: string, level: LogLevel, metadata?: Record<string, unknown>) => void;
|
|
141
|
+
//# sourceMappingURL=hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/react/hooks.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAiB1E;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,YAAY,QAAO,SAE/B,CAAC;AAEF;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,QAAQ,GAAI,WAAW,MAAM,mBAE1B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,SAKtC,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,WAAW,iBACK,MAAM,WAAW,UAAU,SAGvD,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,QAAQ,oBACW,MAAM,WAAW,aAAa,SAG7D,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,OAAO,gBACQ,MAAM,eAAe,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,SAGvE,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,QAAQ,kBAIpB,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,UAAU,gDAItB,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,mBAAmB,gBACJ,KAAK,YAAY,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,SAGnE,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,MAAM,kBAEP,MAAM,SAAS,QAAQ,aAAa,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,SAKtE,CAAC"}
|