@@ -8,7 +8,7 @@ import type { WizardSession } from '@lib/wizard-session';
88import type { ApiUser } from '@lib/api' ;
99import { v4 as uuidv4 } from 'uuid' ;
1010import { IS_PRODUCTION_BUILD } from '@env' ;
11- import { debug } from './debug' ;
11+ import { debug , logToFile } from './debug' ;
1212
1313/**
1414 * Extract a standard property bag from the current session.
@@ -58,6 +58,7 @@ export class Analytics {
5858 private appName = 'wizard' ;
5959 private activeFlags : Record < string , string > | null = null ;
6060 private groups : Record < string , string > = { } ;
61+ private personProperties : Record < string , string > = { } ;
6162
6263 constructor ( ) {
6364 this . client = new PostHog ( ANALYTICS_POSTHOG_PUBLIC_PROJECT_WRITE_KEY , {
@@ -107,10 +108,12 @@ export class Analytics {
107108 }
108109
109110 /**
110- * Associate the run with the logged-in user, once per id: identify them
111- * (email, name), then alias the run's anonymous id onto the identified
112- * person so pre-login events merge in. Alias only ever fires after
113- * identification.
111+ * Associate the run with the logged-in user, once per id. Identifies them
112+ * (email, name) and records those person properties so events carry them and
113+ * feature flags can target the individual user — without the email here the
114+ * wizard only sends `$app_name`, so email-targeted flags never match. Opens
115+ * the analytics session on first login, then aliases the run's anonymous id
116+ * onto the identified person so pre-login events merge in.
114117 */
115118 identifyUser ( user : ApiUser ) {
116119 const distinctId = user . distinct_id ;
@@ -127,25 +130,28 @@ export class Analytics {
127130 this . sessionId = uuidv4 ( ) ;
128131 this . tags . $session_id = this . sessionId ;
129132 }
130- this . client . identify ( {
131- distinctId,
132- properties : {
133- $set : {
134- ...( user . email ? { email : user . email } : { } ) ,
135- ...( user . first_name || user . last_name
136- ? {
137- name : [ user . first_name , user . last_name ]
138- . filter ( Boolean )
139- . join ( ' ' ) ,
140- }
141- : { } ) ,
142- } ,
143- } ,
144- } ) ;
133+ const props : Record < string , string > = { } ;
134+ if ( user . email ) props . email = user . email ;
135+ const name = [ user . first_name , user . last_name ]
136+ . filter ( Boolean )
137+ . join ( ' ' )
138+ . trim ( ) ;
139+ if ( name ) props . name = name ;
140+ this . personProperties = props ;
141+ this . client . identify ( { distinctId, properties : { $set : props } } ) ;
145142 this . client . alias ( {
146143 distinctId,
147144 alias : this . anonymousId ,
148145 } ) ;
146+ // The flag snapshot is per identity. Anything evaluated before login (the
147+ // intro screen reads the tools-menu flag) was anonymous — drop it so the
148+ // next read re-evaluates as this user.
149+ this . activeFlags = null ;
150+ }
151+
152+ /** Person properties sent with flag evaluation: app name plus the user's. */
153+ private flagPersonProperties ( ) : Record < string , string > {
154+ return { $app_name : this . appName , ...this . personProperties } ;
149155 }
150156
151157 setTag ( key : string , value : string | boolean | number | null | undefined ) {
@@ -188,9 +194,7 @@ export class Analytics {
188194 const distinctId = this . distinctId ?? this . anonymousId ;
189195 return await this . client . getFeatureFlag ( flagKey , distinctId , {
190196 sendFeatureFlagEvents : true ,
191- personProperties : {
192- $app_name : this . appName ,
193- } ,
197+ personProperties : this . flagPersonProperties ( ) ,
194198 } ) ;
195199 } catch ( error ) {
196200 debug ( 'Failed to get feature flag:' , flagKey , error ) ;
@@ -209,8 +213,13 @@ export class Analytics {
209213 }
210214 try {
211215 const distinctId = this . distinctId ?? this . anonymousId ;
216+ logToFile ( '[flags] evaluating as' , {
217+ distinctId,
218+ identified : this . distinctId !== undefined ,
219+ personProperties : this . flagPersonProperties ( ) ,
220+ } ) ;
212221 const result = await this . client . getAllFlagsAndPayloads ( distinctId , {
213- personProperties : { $app_name : this . appName } ,
222+ personProperties : this . flagPersonProperties ( ) ,
214223 } ) ;
215224 const flags = result . featureFlags ?? { } ;
216225 const out : Record < string , string > = { } ;
@@ -219,6 +228,7 @@ export class Analytics {
219228 out [ key ] = typeof value === 'boolean' ? String ( value ) : String ( value ) ;
220229 }
221230 this . activeFlags = out ;
231+ logToFile ( '[flags] evaluated' , out ) ;
222232 return out ;
223233 } catch ( error ) {
224234 debug ( 'Failed to get all feature flags:' , error ) ;
0 commit comments