Skip to content

Commit 379013c

Browse files
committed
Adds comprehensive analytics tracking integration
Integrates Datafast Analytics to track user behavior and key conversion events throughout the application. Implements automatic pageview tracking for single-page application navigation and adds event tracking for critical user actions including login, signup, checkout initiation, payment success, and payment cancellation. Exposes tracking utilities globally for future extensibility while maintaining clean separation of concerns through dedicated tracking module imports.
1 parent d10aa4a commit 379013c

File tree

5 files changed

+263
-1
lines changed

5 files changed

+263
-1
lines changed

public/index.html

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@
1616
<script type="module" src="/js/theme.js"></script>
1717
<script src="/js/alerts.js"></script>
1818
<script type="module" src="/js/main.js"></script>
19+
<!-- Datafast Analytics -->
20+
<script
21+
defer
22+
data-website-id="dfid_rQsudOt43XiGSgF6HkgBQ"
23+
data-domain="convert2doc.com"
24+
src="https://datafa.st/js/script.js">
25+
</script>
1926
</head>
2027
<body>
2128
<!-- App container for SPA mode -->

public/js/main.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import { initI18n, localizer } from './i18n-setup.js';
55
import { createRouter, defineRoutes } from './router.js';
66
import './components-loader.js'; // Import all components
7+
import { initAutoPageviewTracking } from './utils/datafast-tracking.js';
8+
import * as datafastTracking from './utils/datafast-tracking.js';
79

810
// Initialize the application
911
let initialized = false;
@@ -65,6 +67,10 @@ function initRouter() {
6567
// Define and register routes
6668
defineRoutes(router);
6769

70+
// Initialize automatic pageview tracking for SPA navigation
71+
initAutoPageviewTracking();
72+
console.log('Datafast pageview tracking initialized');
73+
6874
// Debug: Try to access the router's internal state
6975
console.log('Router internal state:', router);
7076

@@ -108,4 +114,8 @@ import {
108114
window.app = window.app || {};
109115
Object.assign(window.app, {
110116
initApp
111-
});
117+
});
118+
119+
// Expose Datafast tracking utilities globally for easy access
120+
window.datafast = window.datafast || {};
121+
window.datafastTracking = datafastTracking;

public/js/page-initializers.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
* Contains functions to initialize different pages in the application
44
*/
55

6+
import { trackLogin, trackSignup, trackGoal, trackApiKeyCreated } from './utils/datafast-tracking.js';
7+
68
/**
79
* Initialize login page
810
*/
@@ -141,6 +143,12 @@ export async function initLoginPage() {
141143
localStorage.setItem('user', JSON.stringify(userObject));
142144
}
143145

146+
// Track successful login
147+
trackLogin({
148+
email,
149+
method: 'email'
150+
});
151+
144152
// Dispatch auth changed event
145153
window.dispatchEvent(new CustomEvent('auth-changed'));
146154

@@ -295,6 +303,14 @@ export function initRegisterPage() {
295303

296304
const authData = await response.json();
297305

306+
// Track successful signup
307+
trackSignup({
308+
email,
309+
method: 'email',
310+
plan: selectedPlan,
311+
payment_method: selectedPayment
312+
});
313+
298314
if (authData && authData.session && authData.session.access_token) {
299315
// Store JWT token in localStorage
300316
localStorage.setItem('jwt_token', authData.session.access_token);
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
/**
2+
* Datafast Analytics Tracking Utility
3+
*
4+
* Provides a clean API for tracking pageviews and custom goals
5+
* using the Datafast analytics service.
6+
*
7+
* @module datafast-tracking
8+
*/
9+
10+
/**
11+
* Check if Datafast is available
12+
* @returns {boolean} True if datafast is loaded
13+
*/
14+
const isDatafastAvailable = () => typeof window?.datafast === 'function';
15+
16+
/**
17+
* Track a custom goal/event with Datafast
18+
*
19+
* @param {string} eventName - The name of the event/goal to track
20+
* @param {Object} [properties={}] - Optional properties to include with the event
21+
* @param {string} [properties.name] - User's name
22+
* @param {string} [properties.email] - User's email
23+
* @param {string} [properties.product_id] - Product identifier
24+
* @returns {boolean} True if the event was tracked successfully
25+
*
26+
* @example
27+
* // Track a checkout initiation
28+
* trackGoal('initiate_checkout', {
29+
* name: 'John Doe',
30+
* email: 'john@example.com',
31+
* product_id: 'prod_123'
32+
* });
33+
*
34+
* @example
35+
* // Track a simple event
36+
* trackGoal('button_click');
37+
*/
38+
export const trackGoal = (eventName, properties = {}) => {
39+
if (!eventName) {
40+
console.warn('[Datafast] Event name is required for tracking');
41+
return false;
42+
}
43+
44+
if (!isDatafastAvailable()) {
45+
console.warn('[Datafast] Analytics not loaded yet');
46+
return false;
47+
}
48+
49+
try {
50+
window.datafast(eventName, properties);
51+
return true;
52+
} catch (error) {
53+
console.error('[Datafast] Error tracking event:', error);
54+
return false;
55+
}
56+
};
57+
58+
/**
59+
* Track a pageview event
60+
*
61+
* @param {string} [path] - Optional path to track (defaults to current path)
62+
* @returns {boolean} True if the pageview was tracked successfully
63+
*
64+
* @example
65+
* // Track current page
66+
* trackPageview();
67+
*
68+
* @example
69+
* // Track specific path
70+
* trackPageview('/dashboard');
71+
*/
72+
export const trackPageview = (path) => {
73+
const pagePath = path ?? window.location.pathname;
74+
return trackGoal('pageview', { path: pagePath });
75+
};
76+
77+
/**
78+
* Track checkout initiation
79+
*
80+
* @param {Object} data - Checkout data
81+
* @param {string} [data.name] - Customer name
82+
* @param {string} [data.email] - Customer email
83+
* @param {string} [data.product_id] - Product identifier
84+
* @param {string} [data.plan] - Subscription plan name
85+
* @param {number} [data.amount] - Amount in cents
86+
* @returns {boolean} True if tracked successfully
87+
*
88+
* @example
89+
* trackCheckoutInitiated({
90+
* name: 'John Doe',
91+
* email: 'john@example.com',
92+
* product_id: 'prod_123',
93+
* plan: 'pro',
94+
* amount: 999
95+
* });
96+
*/
97+
export const trackCheckoutInitiated = (data = {}) => {
98+
return trackGoal('initiate_checkout', data);
99+
};
100+
101+
/**
102+
* Track successful payment/conversion
103+
*
104+
* @param {Object} data - Payment data
105+
* @param {string} [data.name] - Customer name
106+
* @param {string} [data.email] - Customer email
107+
* @param {string} [data.product_id] - Product identifier
108+
* @param {string} [data.plan] - Subscription plan name
109+
* @param {number} [data.amount] - Amount in cents
110+
* @param {string} [data.payment_method] - Payment method used
111+
* @returns {boolean} True if tracked successfully
112+
*/
113+
export const trackPaymentSuccess = (data = {}) => {
114+
return trackGoal('payment_success', data);
115+
};
116+
117+
/**
118+
* Track user signup
119+
*
120+
* @param {Object} data - Signup data
121+
* @param {string} [data.name] - User name
122+
* @param {string} [data.email] - User email
123+
* @param {string} [data.method] - Signup method (email, google, etc.)
124+
* @returns {boolean} True if tracked successfully
125+
*/
126+
export const trackSignup = (data = {}) => {
127+
return trackGoal('signup', data);
128+
};
129+
130+
/**
131+
* Track user login
132+
*
133+
* @param {Object} data - Login data
134+
* @param {string} [data.email] - User email
135+
* @param {string} [data.method] - Login method (email, google, etc.)
136+
* @returns {boolean} True if tracked successfully
137+
*/
138+
export const trackLogin = (data = {}) => {
139+
return trackGoal('login', data);
140+
};
141+
142+
/**
143+
* Track document conversion
144+
*
145+
* @param {Object} data - Conversion data
146+
* @param {string} data.from_format - Source format (pdf, docx, etc.)
147+
* @param {string} data.to_format - Target format (markdown, html, etc.)
148+
* @param {number} [data.file_size] - File size in bytes
149+
* @returns {boolean} True if tracked successfully
150+
*/
151+
export const trackConversion = (data = {}) => {
152+
return trackGoal('document_conversion', data);
153+
};
154+
155+
/**
156+
* Track API key creation
157+
*
158+
* @param {Object} data - API key data
159+
* @param {string} [data.key_name] - Name of the API key
160+
* @returns {boolean} True if tracked successfully
161+
*/
162+
export const trackApiKeyCreated = (data = {}) => {
163+
return trackGoal('api_key_created', data);
164+
};
165+
166+
/**
167+
* Track feature usage
168+
*
169+
* @param {string} featureName - Name of the feature used
170+
* @param {Object} [data={}] - Additional data about the feature usage
171+
* @returns {boolean} True if tracked successfully
172+
*/
173+
export const trackFeatureUsage = (featureName, data = {}) => {
174+
return trackGoal('feature_usage', { feature: featureName, ...data });
175+
};
176+
177+
/**
178+
* Initialize automatic pageview tracking for SPA navigation
179+
* Listens to the 'route-changed' event and tracks pageviews automatically
180+
*
181+
* @returns {Function} Cleanup function to remove the event listener
182+
*/
183+
export const initAutoPageviewTracking = () => {
184+
const handleRouteChange = () => {
185+
trackPageview();
186+
};
187+
188+
window.addEventListener('route-changed', handleRouteChange);
189+
190+
// Return cleanup function
191+
return () => {
192+
window.removeEventListener('route-changed', handleRouteChange);
193+
};
194+
};
195+
196+
// Default export with all tracking functions
197+
export default {
198+
trackGoal,
199+
trackPageview,
200+
trackCheckoutInitiated,
201+
trackPaymentSuccess,
202+
trackSignup,
203+
trackLogin,
204+
trackConversion,
205+
trackApiKeyCreated,
206+
trackFeatureUsage,
207+
initAutoPageviewTracking,
208+
isDatafastAvailable
209+
};

public/js/views/stripe-payment.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { trackCheckoutInitiated, trackPaymentSuccess, trackGoal } from '../utils/datafast-tracking.js';
2+
13
/**
24
* Initialize the Stripe payment page
35
*/
@@ -7,10 +9,18 @@ export function initStripePaymentPage() {
79

810
if (paymentStatus === 'success') {
911
window.showFloatingAlert('Payment successful! Your subscription is now active.', 'success');
12+
// Track successful payment
13+
trackPaymentSuccess({
14+
plan: localStorage.getItem('last_selected_plan') || 'unknown'
15+
});
1016
// Remove the query parameter from the URL
1117
window.history.replaceState({}, document.title, window.location.pathname);
1218
} else if (paymentStatus === 'cancel') {
1319
window.showFloatingAlert('Payment cancelled. You can try again when you\'re ready.', 'info');
20+
// Track payment cancellation
21+
trackGoal('payment_cancelled', {
22+
plan: localStorage.getItem('last_selected_plan') || 'unknown'
23+
});
1424
// Remove the query parameter from the URL
1525
window.history.replaceState({}, document.title, window.location.pathname);
1626
}
@@ -146,6 +156,16 @@ export function initStripePaymentPage() {
146156
try {
147157
console.log('Creating checkout session with:', { email, plan, successUrl, cancelUrl });
148158

159+
// Track checkout initiation
160+
trackCheckoutInitiated({
161+
email,
162+
plan,
163+
amount: plan === 'yearly' ? 3000 : 500
164+
});
165+
166+
// Store the selected plan for tracking on return
167+
localStorage.setItem('last_selected_plan', plan);
168+
149169
// Show processing state
150170
submitButton.disabled = true;
151171
submitButton.textContent = 'Processing...';

0 commit comments

Comments
 (0)