I’m going through the process of adding Segment to my project and I’d like to track page views.
Is there any way I can watch the router for changes? Thinking something along the lines of a beforeEach/afterEach hook that’s fired upon every navigation.
Cheers,
Jay
1 Like
Tobbe
August 10, 2020, 2:58pm
2
2 Likes
danny
August 10, 2020, 2:58pm
3
Hey @jmcmullen , thanks for posting here.
So the relevant bit of the documentation is here: https://redwoodjs.com/docs/redwood-router.html#uselocation
Please note that the types seem to be wrong here, where it complains about useLocation
not being an exported method.
Please let me know how you get on, but I just tried to test this and couldn’t see it call through. Report back in a bit if I see it working!
Update: beat me to it @Tobbe !
1 Like
@Tobbe . yeah I was just asking @danny and we had the exact same idea.
I am trying it in a layout to see.
1 Like
Cheers, that’s working perfectly in my layout.
1 Like
Nice.
Note to readers: this example below isn’t really listening for route changes, it looks for the current location pathname in a layout.
Edit: Well, maybe it is in a way. since the router sets the location. Semantics.
Did you useEffect as well or just useLocation get pathname and use that to send as the page to Analytics?
// in a main, top layout or layout want to track
import { useLocation } from '@redwoodjs/router'
// ...
const AppLayout = ({ children }) => {
const location = useLocation()
const [pathname, setPathname] = useState(location.pathname)
useEffect(() => {
console.log(pathname) // send to analytics
})
or
const location = useLocation()
console.log(location.pathname) // send to analytics
Be great if could share a code snippet with the community as I am sure others will encounter this.
Sure, here’s my attempt. With useEffect as well.
import { useEffect } from 'react'
import { useLocation } from '@redwoodjs/router'
import Navbar from 'src/components/Navbar'
import Footer from 'src/components/Footer'
const DefaultLayout = ({ children }) => {
const { pathname } = useLocation()
useEffect(() => {
try {
window.segment.page(pathname)
} catch (e) {
// Adblock
}
}, [pathname])
return (
<>
<Navbar />
{children}
<Footer />
</>
)
}
export default DefaultLayout
1 Like
Of course. Much better.
I actually started a PR that I abandoned to add parsed out params from the hash:
const LocationProvider = ({ location = window.location, children }) => {
const getContext = React.useCallback(() => {
const { pathname, search, hash } = location
return { pathname, search, hash }
const params = new URLSearchParams(search)
return { pathname, search, params, hash }
}, [location])
Because often when sending to Analytics, then pass on those to Page properties :
const { pathname, params } = useLocation()
useEffect(() => {
try {
window.segment.page(pathname, { params })
} catch (e) {
// Adblock
}
}, [pathname])
If useful, I can complete and submit.
Fortunately for me Segment already handles the query params, but I reckon it’s still a useful feature to have none the less. Might need to make sure URLSearchParams get’s polyfilled since it’s not supported on IE11 though.
I need to listen for routing changes outside the Routes tag
I tried useLocation and it complained that it was not within a LocationProvider
I wrapped one of those around the App just inside the RedwoodApolloProvider and routing stopped working
I imagine there is one of the already wrapping something for me
I need to do things in the AppBar, outside the Routes Element…
Guessing since the docs do not mention a LocationProvider…