wouter icon indicating copy to clipboard operation
wouter copied to clipboard

Subscribe to router changes for analytics

Open jahilldev opened this issue 11 months ago • 3 comments

I'm looking for a way to centrally define GTM dataLayer pushes based on router state changes, e.g whenever a navigation occurs. We use the dataLayer for tracking all sorts of things for observability.

What's the recommended way of achieving this with wouter?

Something like this (although the onChange property doesn't exist, I know):

<Router
  onChange={
    () => window.dataLayer.push({ event: 'navigation', /*[...]*/ })
  }
>
  {/*[...]*/}
</Router>

Perhaps this can be done via hooks?

Thanks in advance for the help

P.S: So glad we don't need to use the behemoth of react-router for simple React apps anymore! Good work!

jahilldev avatar Jan 31 '25 20:01 jahilldev

Wouter doesn't support events yet, as an alternative I can suggest listening to changes of the current location:

const [location] = useLocation()

useEffect(() => {
 // some additional logic if you want to avoid sending events on mount or duplicate events
 ... 
}, [location])

molefrog avatar Feb 01 '25 04:02 molefrog

@molefrog @jahilldev

For similar things, when I need to perform some action on every navigation, I am using kind of monkey patching of the useLocation

export function useCustomLocation(): HookReturnValue<LocationHook> {
  const [location, setLocation] = useBrowserLocation();
  const appSetLocation = useCallback(async (to: Path, options?: { replace?: boolean }) => {
      // do whatever I want, for example override the to
       const destination = `MY_PREFIX/${to}`; 
       setLocation(destination, options);
    }
  }, [setLocation]);

  return [location, appSetLocation];
}

        <Router hook={useCustomLocation}>
{/*  when components here call useLocation the useCustomLocation will be used */}
</Router>

nikita-starostin avatar Feb 13 '25 08:02 nikita-starostin

@jahilldev If you pass something like a callback to the router, you should also keep in mind that something inside the router might change the title. This means the router should wait until all content has been rendered before running anything, especially when there’s specific data fetching inside nested useEffects that can change the title.

max-mykhailenko avatar Apr 17 '25 08:04 max-mykhailenko

Closing this for now. The approach @nikita-starostin suggested is actually quite good!

molefrog avatar Nov 21 '25 13:11 molefrog