Bluesky app fork with some witchin' additions 💫 witchsky.app
bluesky fork client

[APP-1787] Some analytics cleanup (#9736)

* Clean up flags

* Move getMetadataForLogger

* Nail down attributers

* Polyfill features cache

authored by

Eric Bailey and committed by
GitHub
df89b79c 6534630d

+72 -39
+38 -11
src/analytics/features/index.ts
··· 1 + import {MMKV} from '@bsky.app/react-native-mmkv' 2 + import {setPolyfills} from '@growthbook/growthbook' 1 3 import {GrowthBook} from '@growthbook/growthbook-react' 2 4 3 - import {type Metadata} from '#/analytics/metadata' 5 + import {getNavigationMetadata, type Metadata} from '#/analytics/metadata' 4 6 import * as env from '#/env' 5 7 6 8 export {Features} from '#/analytics/features/types' 9 + 10 + const CACHE = new MMKV({id: 'bsky_features_cache'}) 11 + 12 + setPolyfills({ 13 + localStorage: { 14 + getItem: key => { 15 + const value = CACHE.getString(key) 16 + return value != null ? JSON.parse(value) : null 17 + }, 18 + setItem: async (key, value) => { 19 + CACHE.set(key, JSON.stringify(value)) 20 + }, 21 + }, 22 + }) 7 23 8 24 /** 9 25 * We vary the amount of time we wait for GrowthBook to fetch feature ··· 46 62 } 47 63 48 64 /** 49 - * Converts our metadata into GrowthBook attributes and sets them. 65 + * Converts our metadata into GrowthBook attributes and sets them. GrowthBook 66 + * attributes are manually configured in the GrowthBook dashboard. So these 67 + * values need to match exactly. Therefore, let's add them here manually to and 68 + * not spread them to avoid mistakes. 50 69 */ 51 - export function setAttributes({base, session, preferences}: Metadata) { 52 - const {deviceId, sessionId, ...br} = base 70 + export function setAttributes({ 71 + base, 72 + geolocation, 73 + session, 74 + preferences, 75 + }: Metadata) { 53 76 features.setAttributes({ 54 - device_id: deviceId, // GrowthBook special field 55 - session_id: sessionId, // GrowthBook special field 56 - user_id: session?.did, // GrowthBook special field 57 - id: session?.did, // GrowthBook special field 58 - ...br, 59 - ...(session || {}), 60 - ...(preferences || {}), 77 + deviceId: base.deviceId, 78 + sessionId: base.sessionId, 79 + platform: base.platform, 80 + appVersion: base.appVersion, 81 + countryCode: geolocation.countryCode, 82 + regionCode: geolocation.regionCode, 83 + did: session?.did, 84 + isBskyPds: session?.isBskyPds, 85 + appLanguage: preferences?.appLanguage, 86 + contentLanguages: preferences?.contentLanguages, 87 + currentScreen: getNavigationMetadata()?.currentScreen, 61 88 }) 62 89 }
+10 -5
src/analytics/features/types.ts
··· 1 1 export enum Features { 2 - DebugFeedContext = 'debug_show_feedcontext', 3 - IsBskyTeam = 'is_bsky_team_member', 4 - DisableOnboardingFindContacts = 'disable_onboarding_find_contacts', 5 - DisableSettingsFindContacts = 'disable_settings_find_contacts', 6 - DisableLiveNowBeta = 'disable_live_now_beta', 2 + // core flags 3 + IsBskyTeam = 'is_bsky_team', 4 + 5 + // debug flags 6 + DebugFeedContext = 'debug_feed_context', 7 + 8 + // feature flags 9 + ImportContactsOnboardingDisable = 'import_contacts:onboarding:disable', 10 + ImportContactsSettingsDisable = 'import_contacts:settings:disable', 11 + LiveNowBetaDisable = 'live_now_beta:disable', 7 12 }
+1 -1
src/analytics/index.tsx
··· 16 16 useSessionId, 17 17 } from '#/analytics/identifiers' 18 18 import { 19 + getMetadataForLogger, 19 20 getNavigationMetadata, 20 21 type MergeableMetadata, 21 22 type Metadata, 22 23 } from '#/analytics/metadata' 23 24 import {type Metrics, metrics} from '#/analytics/metrics' 24 25 import * as refParams from '#/analytics/misc/refParams' 25 - import {getMetadataForLogger} from '#/analytics/utils' 26 26 import * as env from '#/env' 27 27 import {useGeolocation} from '#/geolocation' 28 28 import {device} from '#/storage'
+19 -1
src/analytics/metadata.ts
··· 53 53 } 54 54 let navigationMetadata: NavigationMetadata | undefined 55 55 export function getNavigationMetadata() { 56 - console.log('metadata', JSON.stringify(navigationMetadata, null, 2)) 57 56 return navigationMetadata 58 57 } 59 58 export function setNavigationMetadata(meta: NavigationMetadata | undefined) { 60 59 navigationMetadata = meta 61 60 } 61 + 62 + /** 63 + * We don't want or need to send all data to the logger 64 + */ 65 + export function getMetadataForLogger({ 66 + base, 67 + geolocation, 68 + session, 69 + }: Metadata): Record<string, any> { 70 + return { 71 + deviceId: base.deviceId, 72 + sessionId: base.sessionId, 73 + platform: base.platform, 74 + appVersion: base.appVersion, 75 + countryCode: geolocation.countryCode, 76 + regionCode: geolocation.regionCode, 77 + isBskyPds: session?.isBskyPds || 'anonymous', 78 + } 79 + }
-17
src/analytics/utils.ts
··· 4 4 import {type SessionAccount} from '#/state/session' 5 5 import { 6 6 type MergeableMetadata, 7 - type Metadata, 8 7 type SessionMetadata, 9 8 } from '#/analytics/metadata' 10 9 ··· 32 31 } 33 32 } 34 33 } 35 - 36 - export function getMetadataForLogger({ 37 - base, 38 - geolocation, 39 - session, 40 - }: Metadata): Record<string, any> { 41 - return { 42 - deviceId: base.deviceId, 43 - sessionId: base.sessionId, 44 - platform: base.platform, 45 - appVersion: base.appVersion, 46 - countryCode: geolocation.countryCode, 47 - regionCode: geolocation.regionCode, 48 - isBskyPds: session?.isBskyPds || 'anonymous', 49 - } 50 - }
+1 -1
src/components/dialogs/nuxs/LiveNowBetaDialog.tsx
··· 24 24 '2026-01-16T00:00:00.000Z', 25 25 props.currentProfile.createdAt, 26 26 ) && 27 - !props.features.enabled(props.features.DisableLiveNowBeta) 27 + !props.features.enabled(props.features.LiveNowBetaDisable) 28 28 ) 29 29 }) 30 30
+1 -1
src/screens/Onboarding/index.tsx
··· 48 48 ENV !== 'e2e' && 49 49 IS_NATIVE && 50 50 findContactsEnabled && 51 - !ax.features.enabled(ax.features.DisableOnboardingFindContacts) 51 + !ax.features.enabled(ax.features.ImportContactsOnboardingDisable) 52 52 53 53 const [state, dispatch] = useReducer( 54 54 reducer,
+1 -1
src/screens/Settings/Settings.tsx
··· 213 213 </SettingsList.LinkItem> 214 214 {IS_NATIVE && 215 215 findContactsEnabled && 216 - !ax.features.enabled(ax.features.DisableSettingsFindContacts) && ( 216 + !ax.features.enabled(ax.features.ImportContactsSettingsDisable) && ( 217 217 <SettingsList.LinkItem 218 218 to="/settings/find-contacts" 219 219 label={_(msg`Find friends from contacts`)}>
+1 -1
src/state/service-config.tsx
··· 106 106 const ax = useAnalytics() 107 107 const {hasSession} = useSession() 108 108 if (!hasSession) return false 109 - return IS_DEV ? true : !ax.features.enabled(ax.features.DisableLiveNowBeta) 109 + return IS_DEV ? true : !ax.features.enabled(ax.features.LiveNowBetaDisable) 110 110 } 111 111 112 112 export function useCheckEmailConfirmed() {