@@ -15,6 +15,7 @@ import windowsLaunchingDecentraland from '../../images/download/windows_launchin
1515import windowsSetup from '../../images/download/windows_setup.webp'
1616import microsoftLogo from '../../images/microsoft-logo.svg'
1717import { calculateDownloadUrl } from '../../modules/downloadWithIdentity'
18+ import { collectClientFingerprint } from '../../modules/fingerprint'
1819import { DownloadPlace , SectionViewedTrack , SegmentEvent , resolveDownloadPlace } from '../../modules/segment'
1920import { streamOrFallback } from '../../modules/streamOrFallback'
2021import { FALLBACK_CDN_RELEASE_LINKS , addQueryParamsToUrlString } from '../../modules/url'
@@ -221,23 +222,30 @@ const DownloadSuccess = memo(() => {
221222 // "the file finished downloading" rather than "the user clicked".
222223 // If the transfer fails the .catch() below fires DOWNLOAD_FAILED
223224 // instead, so success/failed are mutually exclusive.
225+ //
226+ // The `fingerprint` payload below is what the data team's server-side
227+ // join uses to match this download with the launcher's first-run
228+ // event from the same machine — see the IP + heuristic fingerprint
229+ // attribution doc.
230+ const fingerprint = collectClientFingerprint ( )
224231 await waitForAnalytics ( )
225232 if ( signal . aborted || ! isInitializedRef . current ) return
226233 // eslint-disable-next-line @typescript-eslint/naming-convention
227- trackRef . current ( SegmentEvent . DOWNLOAD_STARTED , { place, href : osLink , auth_state : authStateRef . current } )
234+ trackRef . current ( SegmentEvent . DOWNLOAD_STARTED , { place, href : osLink , auth_state : authStateRef . current , ... fingerprint } )
228235 // eslint-disable-next-line @typescript-eslint/naming-convention
229- trackRef . current ( SegmentEvent . DOWNLOAD_SUCCESS , { place, href : url , filename, auth_state : authStateRef . current } )
236+ trackRef . current ( SegmentEvent . DOWNLOAD_SUCCESS , { place, href : url , filename, auth_state : authStateRef . current , ... fingerprint } )
230237 }
231238
232239 startDownload ( )
233240 . catch ( async error => {
234241 if ( signal . aborted ) return
235242 console . error ( 'Download error:' , error )
236243 setDownloadError ( error instanceof Error ? error . message : 'Download failed' )
244+ const fingerprint = collectClientFingerprint ( )
237245 await waitForAnalytics ( )
238246 if ( signal . aborted || ! isInitializedRef . current ) return
239247 // eslint-disable-next-line @typescript-eslint/naming-convention
240- trackRef . current ( SegmentEvent . DOWNLOAD_FAILED , { place, href : osLink , auth_state : authStateRef . current } )
248+ trackRef . current ( SegmentEvent . DOWNLOAD_FAILED , { place, href : osLink , auth_state : authStateRef . current , ... fingerprint } )
241249 } )
242250 . finally ( ( ) => {
243251 if ( ! signal . aborted ) {
@@ -267,9 +275,10 @@ const DownloadSuccess = memo(() => {
267275 const footerPlace = DownloadPlace . DOWNLOAD_SUCCESS_FOOTER
268276 // Re-download from the footer link is its own funnel event so analytics
269277 // can distinguish it from the auto-download that fires on page mount.
278+ const fingerprint = collectClientFingerprint ( )
270279 if ( isInitializedRef . current ) {
271280 // eslint-disable-next-line @typescript-eslint/naming-convention
272- trackRef . current ( SegmentEvent . DOWNLOAD_STARTED , { place : footerPlace , href : osLink , auth_state : authState } )
281+ trackRef . current ( SegmentEvent . DOWNLOAD_STARTED , { place : footerPlace , href : osLink , auth_state : authState , ... fingerprint } )
273282 }
274283
275284 try {
@@ -297,16 +306,23 @@ const DownloadSuccess = memo(() => {
297306 // DOWNLOAD_SUCCESS only fires after streamOrFallback has resolved,
298307 // i.e. the bytes have effectively landed (Windows) or the
299308 // fallback hold elapsed (macOS / Windows fetch failure).
300- // eslint-disable-next-line @typescript-eslint/naming-convention
301- trackRef . current ( SegmentEvent . DOWNLOAD_SUCCESS , { place : footerPlace , href : downloadUrl , filename, auth_state : authState } )
309+
310+ trackRef . current ( SegmentEvent . DOWNLOAD_SUCCESS , {
311+ place : footerPlace ,
312+ href : downloadUrl ,
313+ filename,
314+ // eslint-disable-next-line @typescript-eslint/naming-convention
315+ auth_state : authState ,
316+ ...fingerprint
317+ } )
302318 }
303319 } catch ( error ) {
304320 if ( signal . aborted ) return
305321 console . error ( 'Download error:' , error )
306322 setDownloadError ( error instanceof Error ? error . message : 'Download failed' )
307323 if ( isInitializedRef . current ) {
308324 // eslint-disable-next-line @typescript-eslint/naming-convention
309- trackRef . current ( SegmentEvent . DOWNLOAD_FAILED , { place : footerPlace , href : osLink , auth_state : authState } )
325+ trackRef . current ( SegmentEvent . DOWNLOAD_FAILED , { place : footerPlace , href : osLink , auth_state : authState , ... fingerprint } )
310326 }
311327 } finally {
312328 downloadingRef . current = false
0 commit comments