55 * Privacy-compliant with no PII tracking.
66 */
77
8- // Extend Window interface to include gtag
8+ // Extend Window interface to include gtag and rdt
99declare global {
1010 interface Window {
1111 gtag ?: (
@@ -14,6 +14,7 @@ declare global {
1414 params ?: Record < string , any >
1515 ) => void ;
1616 dataLayer ?: any [ ] ;
17+ rdt ?: ( command : string , ...args : any [ ] ) => void ;
1718 }
1819}
1920
@@ -30,6 +31,48 @@ function trackEvent(eventName: string, params?: Record<string, any>) {
3031 }
3132}
3233
34+ /**
35+ * Safely send an event to Reddit Pixel
36+ */
37+ function trackRedditEvent ( eventName : string , metadata ?: Record < string , any > ) {
38+ if ( typeof window !== 'undefined' && window . rdt ) {
39+ try {
40+ if ( metadata ) {
41+ window . rdt ( 'track' , eventName , metadata ) ;
42+ } else {
43+ window . rdt ( 'track' , eventName ) ;
44+ }
45+ } catch ( error ) {
46+ console . warn ( 'Reddit Pixel tracking failed:' , error ) ;
47+ }
48+ }
49+ }
50+
51+ /**
52+ * Send event to Reddit Conversions API (server-side)
53+ */
54+ async function trackRedditConversion (
55+ eventType : string ,
56+ metadata ?: Record < string , any >
57+ ) {
58+ if ( typeof window !== 'undefined' ) {
59+ try {
60+ await fetch ( '/api/reddit-conversion' , {
61+ method : 'POST' ,
62+ headers : {
63+ 'Content-Type' : 'application/json' ,
64+ } ,
65+ body : JSON . stringify ( {
66+ eventType,
67+ metadata,
68+ } ) ,
69+ } ) ;
70+ } catch ( error ) {
71+ console . warn ( 'Reddit Conversions API tracking failed:' , error ) ;
72+ }
73+ }
74+ }
75+
3376// ============================================================================
3477// CORE USER JOURNEY EVENTS (12 total)
3578// ============================================================================
@@ -66,13 +109,30 @@ export function trackOnboardingStepViewed(step: string) {
66109 } ) ;
67110}
68111
112+ /**
113+ * User viewed the Explore tab
114+ */
115+ export function trackExploreTabViewed ( ) {
116+ trackEvent ( 'explore_tab_viewed' ) ;
117+
118+ // Track as ViewContent event on Reddit
119+ trackRedditEvent ( 'ViewContent' ) ;
120+ trackRedditConversion ( 'ViewContent' ) ;
121+ }
122+
69123/**
70124 * User ran a search query to find studies
71125 */
72- export function trackQueryRun ( resultCount : number ) {
126+ export function trackQueryRun ( resultCount : number , shouldTrackReddit : boolean = false ) {
73127 trackEvent ( 'query_run' , {
74128 result_count : resultCount ,
75129 } ) ;
130+
131+ // Only track as Search event on Reddit if explicitly requested (user-initiated search)
132+ if ( shouldTrackReddit ) {
133+ trackRedditEvent ( 'Search' ) ;
134+ trackRedditConversion ( 'Search' ) ;
135+ }
76136}
77137
78138/**
@@ -96,9 +156,20 @@ export function trackAIAnalysisRun() {
96156 * User loaded a genotype file (DNA data)
97157 */
98158export function trackGenotypeFileLoaded ( fileSize : number , variantCount : number ) {
99- trackEvent ( 'genotype_file_loaded' , {
159+ const metadata = {
100160 file_size_kb : Math . round ( fileSize / 1024 ) ,
101161 variant_count : variantCount ,
162+ } ;
163+
164+ trackEvent ( 'genotype_file_loaded' , metadata ) ;
165+
166+ // Track as Lead event on Reddit (DNA upload is a lead generation action)
167+ const conversionId = `dna_${ Date . now ( ) } _${ Math . random ( ) . toString ( 36 ) . substr ( 2 , 9 ) } ` ;
168+ trackRedditEvent ( 'Lead' , {
169+ conversionId,
170+ } ) ;
171+ trackRedditConversion ( 'Lead' , {
172+ conversion_id : conversionId ,
102173 } ) ;
103174}
104175
@@ -132,6 +203,15 @@ export function trackPremiumSectionViewed() {
132203 */
133204export function trackUserLoggedIn ( ) {
134205 trackEvent ( 'user_logged_in' ) ;
206+
207+ // Track as SignUp event on Reddit
208+ const conversionId = `login_${ Date . now ( ) } _${ Math . random ( ) . toString ( 36 ) . substr ( 2 , 9 ) } ` ;
209+ trackRedditEvent ( 'SignUp' , {
210+ conversionId,
211+ } ) ;
212+ trackRedditConversion ( 'SignUp' , {
213+ conversion_id : conversionId ,
214+ } ) ;
135215}
136216
137217/**
@@ -175,6 +255,23 @@ export function trackSubscribedWithCreditCard(durationDays: number) {
175255 trackEvent ( 'subscribed_credit_card' , {
176256 duration_days : durationDays ,
177257 } ) ;
258+
259+ // Track as Purchase event on Reddit
260+ const conversionId = `sub_cc_${ Date . now ( ) } _${ Math . random ( ) . toString ( 36 ) . substr ( 2 , 9 ) } ` ;
261+ const value = ( durationDays / 30 ) * 4.99 ; // Monthly price is $4.99
262+
263+ trackRedditEvent ( 'Purchase' , {
264+ conversionId,
265+ currency : 'USD' ,
266+ value : value ,
267+ item_count : 1 ,
268+ } ) ;
269+ trackRedditConversion ( 'Purchase' , {
270+ conversion_id : conversionId ,
271+ currency : 'USD' ,
272+ value : value ,
273+ item_count : 1 ,
274+ } ) ;
178275}
179276
180277/**
@@ -184,6 +281,23 @@ export function trackSubscribedWithStablecoin(durationDays: number) {
184281 trackEvent ( 'subscribed_stablecoin' , {
185282 duration_days : durationDays ,
186283 } ) ;
284+
285+ // Track as Purchase event on Reddit
286+ const conversionId = `sub_crypto_${ Date . now ( ) } _${ Math . random ( ) . toString ( 36 ) . substr ( 2 , 9 ) } ` ;
287+ const value = ( durationDays / 30 ) * 4.99 ; // Monthly price is $4.99
288+
289+ trackRedditEvent ( 'Purchase' , {
290+ conversionId,
291+ currency : 'USD' ,
292+ value : value ,
293+ item_count : 1 ,
294+ } ) ;
295+ trackRedditConversion ( 'Purchase' , {
296+ conversion_id : conversionId ,
297+ currency : 'USD' ,
298+ value : value ,
299+ item_count : 1 ,
300+ } ) ;
187301}
188302
189303/**
@@ -214,7 +328,8 @@ export function trackFileUploadSuccess(fileSize: number, variantCount: number) {
214328
215329/** @deprecated Use trackQueryRun instead */
216330export function trackSearch ( query : string , resultCount : number , loadTime : number ) {
217- trackQueryRun ( resultCount ) ;
331+ // Pass true to indicate this is a user-initiated search (should track on Reddit)
332+ trackQueryRun ( resultCount , true ) ;
218333}
219334
220335/** @deprecated Use trackMatchRevealed instead */
0 commit comments