@axyle/expo-sdk 1.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/CONFIG.md +117 -0
- package/README.md +534 -0
- package/dist/client.d.ts +93 -0
- package/dist/client.js +416 -0
- package/dist/config.example.d.ts +8 -0
- package/dist/config.example.js +13 -0
- package/dist/configLoader.d.ts +10 -0
- package/dist/configLoader.js +22 -0
- package/dist/constants.d.ts +38 -0
- package/dist/constants.js +42 -0
- package/dist/context.d.ts +36 -0
- package/dist/context.js +216 -0
- package/dist/core.d.ts +9 -0
- package/dist/core.js +45 -0
- package/dist/hooks/useFeatureTracking.d.ts +34 -0
- package/dist/hooks/useFeatureTracking.js +60 -0
- package/dist/hooks/useOnboardingTracking.d.ts +85 -0
- package/dist/hooks/useOnboardingTracking.js +172 -0
- package/dist/hooks/useScreenTracking.d.ts +23 -0
- package/dist/hooks/useScreenTracking.js +52 -0
- package/dist/hooks/useScrollTracking.d.ts +39 -0
- package/dist/hooks/useScrollTracking.js +146 -0
- package/dist/index.d.ts +140 -0
- package/dist/index.js +171 -0
- package/dist/integrations/expoRouter.d.ts +42 -0
- package/dist/integrations/expoRouter.js +66 -0
- package/dist/integrations/reactNavigation.d.ts +27 -0
- package/dist/integrations/reactNavigation.js +101 -0
- package/dist/queue.d.ts +52 -0
- package/dist/queue.js +143 -0
- package/dist/session.d.ts +44 -0
- package/dist/session.js +139 -0
- package/dist/sessionAnalytics.d.ts +43 -0
- package/dist/sessionAnalytics.js +74 -0
- package/dist/storage.d.ts +67 -0
- package/dist/storage.js +210 -0
- package/dist/transport.d.ts +41 -0
- package/dist/transport.js +158 -0
- package/dist/types.d.ts +102 -0
- package/dist/types.js +5 -0
- package/dist/utils.d.ts +39 -0
- package/dist/utils.js +116 -0
- package/package.json +44 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* React hook for automatic screen tracking with time tracking
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.useScreenTracking = useScreenTracking;
|
|
7
|
+
const react_1 = require("react");
|
|
8
|
+
const core_1 = require("../core");
|
|
9
|
+
/**
|
|
10
|
+
* Hook to automatically track screen views with time tracking
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```tsx
|
|
14
|
+
* function HomeScreen() {
|
|
15
|
+
* useScreenTracking({ screenName: 'Home' });
|
|
16
|
+
* return <View>...</View>;
|
|
17
|
+
* }
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
function useScreenTracking(options) {
|
|
21
|
+
const { screenName, properties = {}, trackTime = true } = options;
|
|
22
|
+
const hasTracked = (0, react_1.useRef)(false);
|
|
23
|
+
const screenStartTime = (0, react_1.useRef)(null);
|
|
24
|
+
(0, react_1.useEffect)(() => {
|
|
25
|
+
// Track screen view only once when component mounts
|
|
26
|
+
if (!hasTracked.current) {
|
|
27
|
+
const startTime = Date.now();
|
|
28
|
+
screenStartTime.current = startTime;
|
|
29
|
+
(0, core_1.track)("Screen Viewed", {
|
|
30
|
+
screen: screenName,
|
|
31
|
+
screen_start_time: startTime,
|
|
32
|
+
...properties,
|
|
33
|
+
});
|
|
34
|
+
hasTracked.current = true;
|
|
35
|
+
}
|
|
36
|
+
// Track screen time when component unmounts
|
|
37
|
+
return () => {
|
|
38
|
+
if (trackTime && screenStartTime.current !== null) {
|
|
39
|
+
const endTime = Date.now();
|
|
40
|
+
const duration = endTime - screenStartTime.current;
|
|
41
|
+
(0, core_1.track)("Screen Time", {
|
|
42
|
+
screen: screenName,
|
|
43
|
+
duration_ms: duration,
|
|
44
|
+
duration_seconds: Math.round(duration / 1000),
|
|
45
|
+
screen_start_time: screenStartTime.current,
|
|
46
|
+
screen_end_time: endTime,
|
|
47
|
+
...properties,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}, [screenName, properties, trackTime]);
|
|
52
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React hook for scroll tracking
|
|
3
|
+
*/
|
|
4
|
+
import { ScrollView } from "react-native";
|
|
5
|
+
export interface ScrollTrackingOptions {
|
|
6
|
+
/** Screen/page name where scroll is being tracked */
|
|
7
|
+
screenName: string;
|
|
8
|
+
/** Additional properties to track with scroll events */
|
|
9
|
+
properties?: Record<string, any>;
|
|
10
|
+
/** Threshold percentages to track (default: [25, 50, 75, 100]) */
|
|
11
|
+
thresholds?: number[];
|
|
12
|
+
/** Minimum scroll distance before tracking (default: 100) */
|
|
13
|
+
minScrollDistance?: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Hook to automatically track scroll depth on ScrollView
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```tsx
|
|
20
|
+
* function ArticleScreen() {
|
|
21
|
+
* const scrollViewRef = useScrollTracking({
|
|
22
|
+
* screenName: 'Article',
|
|
23
|
+
* thresholds: [25, 50, 75, 100]
|
|
24
|
+
* });
|
|
25
|
+
*
|
|
26
|
+
* return (
|
|
27
|
+
* <ScrollView ref={scrollViewRef}>
|
|
28
|
+
* {/* content *\/}
|
|
29
|
+
* </ScrollView>
|
|
30
|
+
* );
|
|
31
|
+
* }
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export declare function useScrollTracking(options: ScrollTrackingOptions): import("react").RefObject<ScrollView>;
|
|
35
|
+
/**
|
|
36
|
+
* Hook for tracking scroll on web pages
|
|
37
|
+
* Use this for web/React implementations
|
|
38
|
+
*/
|
|
39
|
+
export declare function useWebScrollTracking(options: ScrollTrackingOptions): void;
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* React hook for scroll tracking
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.useScrollTracking = useScrollTracking;
|
|
7
|
+
exports.useWebScrollTracking = useWebScrollTracking;
|
|
8
|
+
const react_1 = require("react");
|
|
9
|
+
const core_1 = require("../core");
|
|
10
|
+
/**
|
|
11
|
+
* Hook to automatically track scroll depth on ScrollView
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* function ArticleScreen() {
|
|
16
|
+
* const scrollViewRef = useScrollTracking({
|
|
17
|
+
* screenName: 'Article',
|
|
18
|
+
* thresholds: [25, 50, 75, 100]
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* return (
|
|
22
|
+
* <ScrollView ref={scrollViewRef}>
|
|
23
|
+
* {/* content *\/}
|
|
24
|
+
* </ScrollView>
|
|
25
|
+
* );
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
function useScrollTracking(options) {
|
|
30
|
+
const { screenName, properties = {}, thresholds = [25, 50, 75, 100], minScrollDistance = 100, } = options;
|
|
31
|
+
const scrollViewRef = (0, react_1.useRef)(null);
|
|
32
|
+
const trackedThresholds = (0, react_1.useRef)(new Set());
|
|
33
|
+
const lastScrollY = (0, react_1.useRef)(0);
|
|
34
|
+
const contentHeight = (0, react_1.useRef)(0);
|
|
35
|
+
const scrollViewHeight = (0, react_1.useRef)(0);
|
|
36
|
+
(0, react_1.useEffect)(() => {
|
|
37
|
+
const scrollView = scrollViewRef.current;
|
|
38
|
+
if (!scrollView)
|
|
39
|
+
return;
|
|
40
|
+
const handleScroll = (event) => {
|
|
41
|
+
const { contentOffset, contentSize, layoutMeasurement } = event.nativeEvent;
|
|
42
|
+
const scrollY = contentOffset.y;
|
|
43
|
+
const contentHeightValue = contentSize.height;
|
|
44
|
+
const scrollViewHeightValue = layoutMeasurement.height;
|
|
45
|
+
contentHeight.current = contentHeightValue;
|
|
46
|
+
scrollViewHeight.current = scrollViewHeightValue;
|
|
47
|
+
// Calculate scroll percentage
|
|
48
|
+
const maxScroll = Math.max(0, contentHeightValue - scrollViewHeightValue);
|
|
49
|
+
if (maxScroll === 0)
|
|
50
|
+
return;
|
|
51
|
+
const scrollPercentage = Math.round((scrollY / maxScroll) * 100);
|
|
52
|
+
const scrollDistance = Math.abs(scrollY - lastScrollY.current);
|
|
53
|
+
// Only track if minimum scroll distance is met
|
|
54
|
+
if (scrollDistance < minScrollDistance)
|
|
55
|
+
return;
|
|
56
|
+
lastScrollY.current = scrollY;
|
|
57
|
+
// Track threshold milestones
|
|
58
|
+
for (const threshold of thresholds) {
|
|
59
|
+
if (scrollPercentage >= threshold &&
|
|
60
|
+
!trackedThresholds.current.has(threshold)) {
|
|
61
|
+
trackedThresholds.current.add(threshold);
|
|
62
|
+
(0, core_1.track)("Scroll Depth", {
|
|
63
|
+
screen: screenName,
|
|
64
|
+
scroll_percentage: scrollPercentage,
|
|
65
|
+
scroll_threshold: threshold,
|
|
66
|
+
scroll_y: scrollY,
|
|
67
|
+
content_height: contentHeightValue,
|
|
68
|
+
viewport_height: scrollViewHeightValue,
|
|
69
|
+
...properties,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// Track general scroll event periodically (every 10% scroll)
|
|
74
|
+
const scrollBucket = Math.floor(scrollPercentage / 10) * 10;
|
|
75
|
+
if (scrollBucket > 0 && scrollBucket % 10 === 0) {
|
|
76
|
+
(0, core_1.track)("Scroll Event", {
|
|
77
|
+
screen: screenName,
|
|
78
|
+
scroll_percentage: scrollPercentage,
|
|
79
|
+
scroll_y: scrollY,
|
|
80
|
+
...properties,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
// Note: ScrollView doesn't have a direct onScroll prop in React Native
|
|
85
|
+
// This would need to be implemented differently for React Native
|
|
86
|
+
// For web, we can use onScroll directly
|
|
87
|
+
if (scrollView && "addEventListener" in scrollView) {
|
|
88
|
+
// Web implementation
|
|
89
|
+
scrollView.addEventListener("scroll", handleScroll);
|
|
90
|
+
return () => {
|
|
91
|
+
scrollView.removeEventListener("scroll", handleScroll);
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}, [screenName, properties, thresholds, minScrollDistance]);
|
|
95
|
+
return scrollViewRef;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Hook for tracking scroll on web pages
|
|
99
|
+
* Use this for web/React implementations
|
|
100
|
+
*/
|
|
101
|
+
function useWebScrollTracking(options) {
|
|
102
|
+
const { screenName, properties = {}, thresholds = [25, 50, 75, 100], minScrollDistance = 100, } = options;
|
|
103
|
+
const trackedThresholds = (0, react_1.useRef)(new Set());
|
|
104
|
+
const lastScrollY = (0, react_1.useRef)(0);
|
|
105
|
+
(0, react_1.useEffect)(() => {
|
|
106
|
+
const handleScroll = () => {
|
|
107
|
+
// Type guard for web environment
|
|
108
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const scrollY = window.scrollY || document.documentElement.scrollTop;
|
|
112
|
+
const documentHeight = document.documentElement.scrollHeight;
|
|
113
|
+
const windowHeight = window.innerHeight;
|
|
114
|
+
const maxScroll = documentHeight - windowHeight;
|
|
115
|
+
if (maxScroll === 0)
|
|
116
|
+
return;
|
|
117
|
+
const scrollPercentage = Math.round((scrollY / maxScroll) * 100);
|
|
118
|
+
const scrollDistance = Math.abs(scrollY - lastScrollY.current);
|
|
119
|
+
if (scrollDistance < minScrollDistance)
|
|
120
|
+
return;
|
|
121
|
+
lastScrollY.current = scrollY;
|
|
122
|
+
// Track threshold milestones
|
|
123
|
+
for (const threshold of thresholds) {
|
|
124
|
+
if (scrollPercentage >= threshold &&
|
|
125
|
+
!trackedThresholds.current.has(threshold)) {
|
|
126
|
+
trackedThresholds.current.add(threshold);
|
|
127
|
+
(0, core_1.track)("Scroll Depth", {
|
|
128
|
+
screen: screenName,
|
|
129
|
+
scroll_percentage: scrollPercentage,
|
|
130
|
+
scroll_threshold: threshold,
|
|
131
|
+
scroll_y: scrollY,
|
|
132
|
+
content_height: documentHeight,
|
|
133
|
+
viewport_height: windowHeight,
|
|
134
|
+
...properties,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
if (typeof window !== "undefined") {
|
|
140
|
+
window.addEventListener("scroll", handleScroll, { passive: true });
|
|
141
|
+
return () => {
|
|
142
|
+
window.removeEventListener("scroll", handleScroll);
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
}, [screenName, properties, thresholds, minScrollDistance]);
|
|
146
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Axyle Analytics SDK
|
|
3
|
+
* Main entry point
|
|
4
|
+
*/
|
|
5
|
+
import type { AnalyticsEvent, AxyleInitConfig, EventContext, EventProperties, UserTraits } from "./types";
|
|
6
|
+
/**
|
|
7
|
+
* Axyle - Main SDK interface
|
|
8
|
+
*/
|
|
9
|
+
export declare const Axyle: {
|
|
10
|
+
/**
|
|
11
|
+
* Initialize the SDK with your API key
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* // Simple: just pass the API key as a string
|
|
16
|
+
* Axyle.init('your-api-key');
|
|
17
|
+
*
|
|
18
|
+
* // Or as an object
|
|
19
|
+
* Axyle.init({ apiKey: 'your-api-key' });
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
init: (config: AxyleInitConfig) => Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Track a custom event
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* Axyle.track('Button Clicked', {
|
|
29
|
+
* button: 'Sign Up',
|
|
30
|
+
* screen: 'Home'
|
|
31
|
+
* });
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
track: (eventName: string, properties?: EventProperties) => Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Identify a user
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* Axyle.identify('user-123', {
|
|
41
|
+
* email: 'user@example.com',
|
|
42
|
+
* plan: 'premium'
|
|
43
|
+
* });
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
identify: (userId: string, traits?: UserTraits) => Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* Reset user data (call on logout)
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```ts
|
|
52
|
+
* Axyle.reset();
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
reset: () => Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Opt out of tracking
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```ts
|
|
61
|
+
* Axyle.optOut();
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
optOut: () => Promise<void>;
|
|
65
|
+
/**
|
|
66
|
+
* Opt back in to tracking
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```ts
|
|
70
|
+
* Axyle.optIn();
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
optIn: () => Promise<void>;
|
|
74
|
+
/**
|
|
75
|
+
* Request user data deletion
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```ts
|
|
79
|
+
* Axyle.deleteUser('user-123');
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
deleteUser: (userId: string) => Promise<void>;
|
|
83
|
+
/**
|
|
84
|
+
* Manually flush all queued events to the server
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```ts
|
|
88
|
+
* await Axyle.flush();
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
flush: () => Promise<void>;
|
|
92
|
+
/**
|
|
93
|
+
* Shutdown the SDK (flushes events and cleans up resources)
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```ts
|
|
97
|
+
* await Axyle.shutdown();
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
shutdown: () => Promise<void>;
|
|
101
|
+
/**
|
|
102
|
+
* Get session analytics statistics
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```ts
|
|
106
|
+
* const stats = Axyle.getSessionStats();
|
|
107
|
+
* console.log('Total events:', stats?.totalEvents);
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
110
|
+
getSessionStats: () => import("./sessionAnalytics").SessionAnalyticsStats | null;
|
|
111
|
+
/**
|
|
112
|
+
* Get all events in current session
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```ts
|
|
116
|
+
* const events = Axyle.getSessionEvents();
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
getSessionEvents: () => AnalyticsEvent[];
|
|
120
|
+
/**
|
|
121
|
+
* Get events by type in current session
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* ```ts
|
|
125
|
+
* const buttonClicks = Axyle.getEventsByType('Button Clicked');
|
|
126
|
+
* ```
|
|
127
|
+
*/
|
|
128
|
+
getEventsByType: (eventName: string) => AnalyticsEvent[];
|
|
129
|
+
};
|
|
130
|
+
export type { AnalyticsEvent, AxyleInitConfig, EventContext, EventProperties, UserTraits, };
|
|
131
|
+
export type { SessionAnalyticsStats } from "./sessionAnalytics";
|
|
132
|
+
export { isValidApiKeyFormat } from "./configLoader";
|
|
133
|
+
export { trackFeatureUsage, trackFeatureUsageWithContext, useFeatureViewTracking, } from "./hooks/useFeatureTracking";
|
|
134
|
+
export { trackFlowAbandoned, trackFlowCompleted, trackOnboardingAbandoned, trackOnboardingCompleted, useFlowTracking, useOnboardingTracking, } from "./hooks/useOnboardingTracking";
|
|
135
|
+
export type { FlowTrackingOptions } from "./hooks/useOnboardingTracking";
|
|
136
|
+
export { useScreenTracking } from "./hooks/useScreenTracking";
|
|
137
|
+
export { useScrollTracking, useWebScrollTracking, } from "./hooks/useScrollTracking";
|
|
138
|
+
export { createNavigationTracker, trackNavigationReady, trackNavigationStateChange, } from "./integrations/reactNavigation";
|
|
139
|
+
export declare function trackScreen(screenName: string, properties?: Record<string, any>): void;
|
|
140
|
+
export default Axyle;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Axyle Analytics SDK
|
|
4
|
+
* Main entry point
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.trackNavigationStateChange = exports.trackNavigationReady = exports.createNavigationTracker = exports.useWebScrollTracking = exports.useScrollTracking = exports.useScreenTracking = exports.useOnboardingTracking = exports.useFlowTracking = exports.trackOnboardingCompleted = exports.trackOnboardingAbandoned = exports.trackFlowCompleted = exports.trackFlowAbandoned = exports.useFeatureViewTracking = exports.trackFeatureUsageWithContext = exports.trackFeatureUsage = exports.isValidApiKeyFormat = exports.Axyle = void 0;
|
|
8
|
+
exports.trackScreen = trackScreen;
|
|
9
|
+
const core_1 = require("./core");
|
|
10
|
+
/**
|
|
11
|
+
* Axyle - Main SDK interface
|
|
12
|
+
*/
|
|
13
|
+
exports.Axyle = {
|
|
14
|
+
/**
|
|
15
|
+
* Initialize the SDK with your API key
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* // Simple: just pass the API key as a string
|
|
20
|
+
* Axyle.init('your-api-key');
|
|
21
|
+
*
|
|
22
|
+
* // Or as an object
|
|
23
|
+
* Axyle.init({ apiKey: 'your-api-key' });
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
init: (config) => core_1.client.init(config),
|
|
27
|
+
/**
|
|
28
|
+
* Track a custom event
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* Axyle.track('Button Clicked', {
|
|
33
|
+
* button: 'Sign Up',
|
|
34
|
+
* screen: 'Home'
|
|
35
|
+
* });
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
track: (eventName, properties) => core_1.client.track(eventName, properties),
|
|
39
|
+
/**
|
|
40
|
+
* Identify a user
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```ts
|
|
44
|
+
* Axyle.identify('user-123', {
|
|
45
|
+
* email: 'user@example.com',
|
|
46
|
+
* plan: 'premium'
|
|
47
|
+
* });
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
identify: (userId, traits) => core_1.client.identify(userId, traits),
|
|
51
|
+
/**
|
|
52
|
+
* Reset user data (call on logout)
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts
|
|
56
|
+
* Axyle.reset();
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
reset: () => core_1.client.reset(),
|
|
60
|
+
/**
|
|
61
|
+
* Opt out of tracking
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```ts
|
|
65
|
+
* Axyle.optOut();
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
optOut: () => core_1.client.optOut(),
|
|
69
|
+
/**
|
|
70
|
+
* Opt back in to tracking
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```ts
|
|
74
|
+
* Axyle.optIn();
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
optIn: () => core_1.client.optIn(),
|
|
78
|
+
/**
|
|
79
|
+
* Request user data deletion
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```ts
|
|
83
|
+
* Axyle.deleteUser('user-123');
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
deleteUser: (userId) => core_1.client.deleteUser(userId),
|
|
87
|
+
/**
|
|
88
|
+
* Manually flush all queued events to the server
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```ts
|
|
92
|
+
* await Axyle.flush();
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
flush: () => core_1.client.flush(),
|
|
96
|
+
/**
|
|
97
|
+
* Shutdown the SDK (flushes events and cleans up resources)
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```ts
|
|
101
|
+
* await Axyle.shutdown();
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
shutdown: () => core_1.client.shutdown(),
|
|
105
|
+
/**
|
|
106
|
+
* Get session analytics statistics
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```ts
|
|
110
|
+
* const stats = Axyle.getSessionStats();
|
|
111
|
+
* console.log('Total events:', stats?.totalEvents);
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
getSessionStats: () => core_1.client.getSessionStats(),
|
|
115
|
+
/**
|
|
116
|
+
* Get all events in current session
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```ts
|
|
120
|
+
* const events = Axyle.getSessionEvents();
|
|
121
|
+
* ```
|
|
122
|
+
*/
|
|
123
|
+
getSessionEvents: () => core_1.client.getSessionEvents(),
|
|
124
|
+
/**
|
|
125
|
+
* Get events by type in current session
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* ```ts
|
|
129
|
+
* const buttonClicks = Axyle.getEventsByType('Button Clicked');
|
|
130
|
+
* ```
|
|
131
|
+
*/
|
|
132
|
+
getEventsByType: (eventName) => core_1.client.getEventsByType(eventName),
|
|
133
|
+
};
|
|
134
|
+
// Export API key validation utility (still useful)
|
|
135
|
+
var configLoader_1 = require("./configLoader");
|
|
136
|
+
Object.defineProperty(exports, "isValidApiKeyFormat", { enumerable: true, get: function () { return configLoader_1.isValidApiKeyFormat; } });
|
|
137
|
+
// Export hooks and integrations
|
|
138
|
+
var useFeatureTracking_1 = require("./hooks/useFeatureTracking");
|
|
139
|
+
Object.defineProperty(exports, "trackFeatureUsage", { enumerable: true, get: function () { return useFeatureTracking_1.trackFeatureUsage; } });
|
|
140
|
+
Object.defineProperty(exports, "trackFeatureUsageWithContext", { enumerable: true, get: function () { return useFeatureTracking_1.trackFeatureUsageWithContext; } });
|
|
141
|
+
Object.defineProperty(exports, "useFeatureViewTracking", { enumerable: true, get: function () { return useFeatureTracking_1.useFeatureViewTracking; } });
|
|
142
|
+
var useOnboardingTracking_1 = require("./hooks/useOnboardingTracking");
|
|
143
|
+
Object.defineProperty(exports, "trackFlowAbandoned", { enumerable: true, get: function () { return useOnboardingTracking_1.trackFlowAbandoned; } });
|
|
144
|
+
Object.defineProperty(exports, "trackFlowCompleted", { enumerable: true, get: function () { return useOnboardingTracking_1.trackFlowCompleted; } });
|
|
145
|
+
Object.defineProperty(exports, "trackOnboardingAbandoned", { enumerable: true, get: function () { return useOnboardingTracking_1.trackOnboardingAbandoned; } });
|
|
146
|
+
Object.defineProperty(exports, "trackOnboardingCompleted", { enumerable: true, get: function () { return useOnboardingTracking_1.trackOnboardingCompleted; } });
|
|
147
|
+
Object.defineProperty(exports, "useFlowTracking", { enumerable: true, get: function () { return useOnboardingTracking_1.useFlowTracking; } });
|
|
148
|
+
// Legacy exports for backward compatibility
|
|
149
|
+
Object.defineProperty(exports, "useOnboardingTracking", { enumerable: true, get: function () { return useOnboardingTracking_1.useOnboardingTracking; } });
|
|
150
|
+
var useScreenTracking_1 = require("./hooks/useScreenTracking");
|
|
151
|
+
Object.defineProperty(exports, "useScreenTracking", { enumerable: true, get: function () { return useScreenTracking_1.useScreenTracking; } });
|
|
152
|
+
var useScrollTracking_1 = require("./hooks/useScrollTracking");
|
|
153
|
+
Object.defineProperty(exports, "useScrollTracking", { enumerable: true, get: function () { return useScrollTracking_1.useScrollTracking; } });
|
|
154
|
+
Object.defineProperty(exports, "useWebScrollTracking", { enumerable: true, get: function () { return useScrollTracking_1.useWebScrollTracking; } });
|
|
155
|
+
var reactNavigation_1 = require("./integrations/reactNavigation");
|
|
156
|
+
Object.defineProperty(exports, "createNavigationTracker", { enumerable: true, get: function () { return reactNavigation_1.createNavigationTracker; } });
|
|
157
|
+
Object.defineProperty(exports, "trackNavigationReady", { enumerable: true, get: function () { return reactNavigation_1.trackNavigationReady; } });
|
|
158
|
+
Object.defineProperty(exports, "trackNavigationStateChange", { enumerable: true, get: function () { return reactNavigation_1.trackNavigationStateChange; } });
|
|
159
|
+
// Manual screen tracking helper
|
|
160
|
+
// Use this in your screens instead of automatic tracking
|
|
161
|
+
function trackScreen(screenName, properties) {
|
|
162
|
+
// Add a small delay to ensure SDK is initialized
|
|
163
|
+
setTimeout(() => {
|
|
164
|
+
(0, core_1.track)("Screen Viewed", {
|
|
165
|
+
screen: screenName,
|
|
166
|
+
...properties,
|
|
167
|
+
});
|
|
168
|
+
}, 100);
|
|
169
|
+
}
|
|
170
|
+
// Default export
|
|
171
|
+
exports.default = exports.Axyle;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Expo Router integration for automatic screen tracking
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Hook to track Expo Router navigation
|
|
6
|
+
* Add this to your root layout (_layout.tsx)
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```tsx
|
|
10
|
+
* // app/_layout.tsx
|
|
11
|
+
* import { useExpoRouterTracking } from '@expo-analytics/sdk';
|
|
12
|
+
*
|
|
13
|
+
* export default function RootLayout() {
|
|
14
|
+
* useExpoRouterTracking();
|
|
15
|
+
*
|
|
16
|
+
* return (
|
|
17
|
+
* <Stack>
|
|
18
|
+
* <Stack.Screen name="index" />
|
|
19
|
+
* <Stack.Screen name="profile" />
|
|
20
|
+
* </Stack>
|
|
21
|
+
* );
|
|
22
|
+
* }
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare function useExpoRouterTracking(): void;
|
|
26
|
+
/**
|
|
27
|
+
* Alternative: Manual tracking for specific routes
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```tsx
|
|
31
|
+
* import { trackExpoRoute } from '@expo-analytics/sdk';
|
|
32
|
+
*
|
|
33
|
+
* export default function ProfileScreen() {
|
|
34
|
+
* useEffect(() => {
|
|
35
|
+
* trackExpoRoute('Profile', { userId: '123' });
|
|
36
|
+
* }, []);
|
|
37
|
+
*
|
|
38
|
+
* return <View>...</View>;
|
|
39
|
+
* }
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export declare function trackExpoRoute(routeName: string, properties?: Record<string, any>): void;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Expo Router integration for automatic screen tracking
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.useExpoRouterTracking = useExpoRouterTracking;
|
|
7
|
+
exports.trackExpoRoute = trackExpoRoute;
|
|
8
|
+
const react_1 = require("react");
|
|
9
|
+
const expo_router_1 = require("expo-router");
|
|
10
|
+
const index_1 = require("../index");
|
|
11
|
+
/**
|
|
12
|
+
* Hook to track Expo Router navigation
|
|
13
|
+
* Add this to your root layout (_layout.tsx)
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```tsx
|
|
17
|
+
* // app/_layout.tsx
|
|
18
|
+
* import { useExpoRouterTracking } from '@expo-analytics/sdk';
|
|
19
|
+
*
|
|
20
|
+
* export default function RootLayout() {
|
|
21
|
+
* useExpoRouterTracking();
|
|
22
|
+
*
|
|
23
|
+
* return (
|
|
24
|
+
* <Stack>
|
|
25
|
+
* <Stack.Screen name="index" />
|
|
26
|
+
* <Stack.Screen name="profile" />
|
|
27
|
+
* </Stack>
|
|
28
|
+
* );
|
|
29
|
+
* }
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
function useExpoRouterTracking() {
|
|
33
|
+
const pathname = (0, expo_router_1.usePathname)();
|
|
34
|
+
const segments = (0, expo_router_1.useSegments)();
|
|
35
|
+
(0, react_1.useEffect)(() => {
|
|
36
|
+
// Track screen view when pathname changes
|
|
37
|
+
if (pathname) {
|
|
38
|
+
index_1.ExpoAnalytics.track('Screen Viewed', {
|
|
39
|
+
screen: pathname,
|
|
40
|
+
segments: segments.join('/'),
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}, [pathname, segments]);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Alternative: Manual tracking for specific routes
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```tsx
|
|
50
|
+
* import { trackExpoRoute } from '@expo-analytics/sdk';
|
|
51
|
+
*
|
|
52
|
+
* export default function ProfileScreen() {
|
|
53
|
+
* useEffect(() => {
|
|
54
|
+
* trackExpoRoute('Profile', { userId: '123' });
|
|
55
|
+
* }, []);
|
|
56
|
+
*
|
|
57
|
+
* return <View>...</View>;
|
|
58
|
+
* }
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
function trackExpoRoute(routeName, properties) {
|
|
62
|
+
index_1.ExpoAnalytics.track('Screen Viewed', {
|
|
63
|
+
screen: routeName,
|
|
64
|
+
...properties,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React Navigation integration for automatic screen tracking
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Create a navigation state change handler for React Navigation
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```tsx
|
|
9
|
+
* import { NavigationContainer } from '@react-navigation/native';
|
|
10
|
+
* import { createNavigationTracker } from '@axyle/expo-sdk';
|
|
11
|
+
*
|
|
12
|
+
* const navigationTracker = createNavigationTracker();
|
|
13
|
+
*
|
|
14
|
+
* function App() {
|
|
15
|
+
* return (
|
|
16
|
+
* <NavigationContainer
|
|
17
|
+
* onStateChange={navigationTracker}
|
|
18
|
+
* >
|
|
19
|
+
* {/* Your navigators *\/}
|
|
20
|
+
* </NavigationContainer>
|
|
21
|
+
* );
|
|
22
|
+
* }
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare function createNavigationTracker(): (state: any) => void;
|
|
26
|
+
export declare function trackNavigationReady(navigationRef: any): void;
|
|
27
|
+
export declare function trackNavigationStateChange(navigationRef: any): void;
|