@@ -241,6 +241,12 @@ export function createV6CompatibleWrapCreateBrowserRouter<
241241
242242 const activeRootSpan = getActiveRootSpan ( ) ;
243243
244+ // Track whether we've completed the initial pageload to properly distinguish
245+ // between POPs that occur during pageload vs. legitimate back/forward navigation.
246+ let isInitialPageloadComplete = false ;
247+ let hasSeenPageloadSpan = ! ! activeRootSpan && spanToJSON ( activeRootSpan ) . op === 'pageload' ;
248+ let hasSeenPopAfterPageload = false ;
249+
244250 // The initial load ends when `createBrowserRouter` is called.
245251 // This is the earliest convenient time to update the transaction name.
246252 // Callbacks to `router.subscribe` are not called for the initial load.
@@ -255,20 +261,31 @@ export function createV6CompatibleWrapCreateBrowserRouter<
255261 }
256262
257263 router . subscribe ( ( state : RouterState ) => {
258- if ( state . historyAction === 'PUSH' || state . historyAction === 'POP' ) {
259- // Wait for the next render if loading an unsettled route
260- if ( state . navigation . state !== 'idle' ) {
261- requestAnimationFrame ( ( ) => {
262- handleNavigation ( {
263- location : state . location ,
264- routes,
265- navigationType : state . historyAction ,
266- version,
267- basename,
268- allRoutes : Array . from ( allRoutes ) ,
269- } ) ;
270- } ) ;
271- } else {
264+ // Track pageload completion to distinguish POPs during pageload from legitimate back/forward navigation
265+ if ( ! isInitialPageloadComplete ) {
266+ const currentRootSpan = getActiveRootSpan ( ) ;
267+ const isCurrentlyInPageload = currentRootSpan && spanToJSON ( currentRootSpan ) . op === 'pageload' ;
268+
269+ if ( isCurrentlyInPageload ) {
270+ hasSeenPageloadSpan = true ;
271+ } else if ( hasSeenPageloadSpan ) {
272+ // Pageload span was active but is now gone - pageload has completed
273+ if ( state . historyAction === 'POP' && ! hasSeenPopAfterPageload ) {
274+ // Pageload ended: ignore the first POP after pageload
275+ hasSeenPopAfterPageload = true ;
276+ } else {
277+ // Pageload ended: either non-POP action or subsequent POP
278+ isInitialPageloadComplete = true ;
279+ }
280+ }
281+ // If we haven't seen a pageload span yet, keep waiting (don't mark as complete)
282+ }
283+
284+ const shouldHandleNavigation =
285+ state . historyAction === 'PUSH' || ( state . historyAction === 'POP' && isInitialPageloadComplete ) ;
286+
287+ if ( shouldHandleNavigation ) {
288+ const navigationHandler = ( ) : void => {
272289 handleNavigation ( {
273290 location : state . location ,
274291 routes,
@@ -277,6 +294,13 @@ export function createV6CompatibleWrapCreateBrowserRouter<
277294 basename,
278295 allRoutes : Array . from ( allRoutes ) ,
279296 } ) ;
297+ } ;
298+
299+ // Wait for the next render if loading an unsettled route
300+ if ( state . navigation . state !== 'idle' ) {
301+ requestAnimationFrame ( navigationHandler ) ;
302+ } else {
303+ navigationHandler ( ) ;
280304 }
281305 }
282306 } ) ;
@@ -327,7 +351,6 @@ export function createV6CompatibleWrapCreateMemoryRouter<
327351 const router = createRouterFunction ( routes , wrappedOpts ) ;
328352 const basename = opts ?. basename ;
329353
330- const activeRootSpan = getActiveRootSpan ( ) ;
331354 let initialEntry = undefined ;
332355
333356 const initialEntries = opts ?. initialEntries ;
@@ -348,21 +371,68 @@ export function createV6CompatibleWrapCreateMemoryRouter<
348371 : initialEntry
349372 : router . state . location ;
350373
351- if ( router . state . historyAction === 'POP' && activeRootSpan ) {
352- updatePageloadTransaction ( { activeRootSpan, location, routes, basename, allRoutes : Array . from ( allRoutes ) } ) ;
374+ const memoryActiveRootSpan = getActiveRootSpan ( ) ;
375+
376+ if ( router . state . historyAction === 'POP' && memoryActiveRootSpan ) {
377+ updatePageloadTransaction ( {
378+ activeRootSpan : memoryActiveRootSpan ,
379+ location,
380+ routes,
381+ basename,
382+ allRoutes : Array . from ( allRoutes ) ,
383+ } ) ;
353384 }
354385
386+ // Track whether we've completed the initial pageload to properly distinguish
387+ // between POPs that occur during pageload vs. legitimate back/forward navigation.
388+ let isInitialPageloadComplete = false ;
389+ let hasSeenPageloadSpan = ! ! memoryActiveRootSpan && spanToJSON ( memoryActiveRootSpan ) . op === 'pageload' ;
390+ let hasSeenPopAfterPageload = false ;
391+
355392 router . subscribe ( ( state : RouterState ) => {
393+ // Track pageload completion to distinguish POPs during pageload from legitimate back/forward navigation
394+ if ( ! isInitialPageloadComplete ) {
395+ const currentRootSpan = getActiveRootSpan ( ) ;
396+ const isCurrentlyInPageload = currentRootSpan && spanToJSON ( currentRootSpan ) . op === 'pageload' ;
397+
398+ if ( isCurrentlyInPageload ) {
399+ hasSeenPageloadSpan = true ;
400+ } else if ( hasSeenPageloadSpan ) {
401+ // Pageload span was active but is now gone - pageload has completed
402+ if ( state . historyAction === 'POP' && ! hasSeenPopAfterPageload ) {
403+ // Pageload ended: ignore the first POP after pageload
404+ hasSeenPopAfterPageload = true ;
405+ } else {
406+ // Pageload ended: either non-POP action or subsequent POP
407+ isInitialPageloadComplete = true ;
408+ }
409+ }
410+ // If we haven't seen a pageload span yet, keep waiting (don't mark as complete)
411+ }
412+
356413 const location = state . location ;
357- if ( state . historyAction === 'PUSH' || state . historyAction === 'POP' ) {
358- handleNavigation ( {
359- location,
360- routes,
361- navigationType : state . historyAction ,
362- version,
363- basename,
364- allRoutes : Array . from ( allRoutes ) ,
365- } ) ;
414+
415+ const shouldHandleNavigation =
416+ state . historyAction === 'PUSH' || ( state . historyAction === 'POP' && isInitialPageloadComplete ) ;
417+
418+ if ( shouldHandleNavigation ) {
419+ const navigationHandler = ( ) : void => {
420+ handleNavigation ( {
421+ location,
422+ routes,
423+ navigationType : state . historyAction ,
424+ version,
425+ basename,
426+ allRoutes : Array . from ( allRoutes ) ,
427+ } ) ;
428+ } ;
429+
430+ // Wait for the next render if loading an unsettled route
431+ if ( state . navigation . state !== 'idle' ) {
432+ requestAnimationFrame ( navigationHandler ) ;
433+ } else {
434+ navigationHandler ( ) ;
435+ }
366436 }
367437 } ) ;
368438
@@ -532,8 +602,16 @@ function wrapPatchRoutesOnNavigation(
532602 // Update navigation span after routes are patched
533603 const activeRootSpan = getActiveRootSpan ( ) ;
534604 if ( activeRootSpan && ( spanToJSON ( activeRootSpan ) as { op ?: string } ) . op === 'navigation' ) {
535- // For memory routers, we should not access window.location; use targetPath only
536- const pathname = isMemoryRouter ? targetPath : targetPath || WINDOW . location ?. pathname ;
605+ // Determine pathname based on router type
606+ let pathname : string | undefined ;
607+ if ( isMemoryRouter ) {
608+ // For memory routers, only use targetPath
609+ pathname = targetPath ;
610+ } else {
611+ // For browser routers, use targetPath or fall back to window.location
612+ pathname = targetPath || WINDOW . location ?. pathname ;
613+ }
614+
537615 if ( pathname ) {
538616 updateNavigationSpan (
539617 activeRootSpan ,
0 commit comments