@@ -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 ) {
@@ -198,9 +204,7 @@ export class Analytics {
198204 const distinctId = this . distinctId ?? this . anonymousId ;
199205 return await this . client . getFeatureFlag ( flagKey , distinctId , {
200206 sendFeatureFlagEvents : true ,
201- personProperties : {
202- $app_name : this . appName ,
203- } ,
207+ personProperties : this . flagPersonProperties ( ) ,
204208 } ) ;
205209 } catch ( error ) {
206210 debug ( 'Failed to get feature flag:' , flagKey , error ) ;
@@ -219,8 +223,13 @@ export class Analytics {
219223 }
220224 try {
221225 const distinctId = this . distinctId ?? this . anonymousId ;
226+ logToFile ( '[flags] evaluating as' , {
227+ distinctId,
228+ identified : this . distinctId !== undefined ,
229+ personProperties : this . flagPersonProperties ( ) ,
230+ } ) ;
222231 const result = await this . client . getAllFlagsAndPayloads ( distinctId , {
223- personProperties : { $app_name : this . appName } ,
232+ personProperties : this . flagPersonProperties ( ) ,
224233 } ) ;
225234 const flags = result . featureFlags ?? { } ;
226235 const out : Record < string , string > = { } ;
@@ -229,6 +238,7 @@ export class Analytics {
229238 out [ key ] = typeof value === 'boolean' ? String ( value ) : String ( value ) ;
230239 }
231240 this . activeFlags = out ;
241+ logToFile ( '[flags] evaluated' , out ) ;
232242 return out ;
233243 } catch ( error ) {
234244 debug ( 'Failed to get all feature flags:' , error ) ;
0 commit comments