plausible / analytics

Simple, open source, lightweight (< 1 KB) and privacy-friendly web analytics alternative to Google Analytics.
https://plausible.io
GNU Affero General Public License v3.0
20.44k stars 1.09k forks source link

`hash` extension does not work as expected due to history.pushState API #2203

Closed vincent-czi closed 2 years ago

vincent-czi commented 2 years ago

Past Issues Searched

Issue is a Bug Report

Using official Plausible Cloud hosting or self-hosting?

Plausible Cloud from plausible.io

Describe the bug

It's questionable if this is a bug -- feel free to close and mark as wontfix if you think it's outside what Plausible should handle -- but the hash extension for supporting hash-based routing does not work as expected in certain configurations.

A common configuration for routing in a SPA is React + react-router-dom. However, if you then run it in hash-based routing (via HashRouter), it causes all react-router navigation (via navigate/useNavigate or Link) to not trigger page events with Plausible. Here's what's going wrong:

  1. react-router-dom uses history.pushState under the hood, which does not trigger the hashchange event.
  2. When using the hash extension in Plausible, the Plausible tracker's page function is purely watching for hashchange events. The logic for watching the history.pushState is in the else branch to the above, so when you use Plausible's hash extension, it's no longer watching where the location changes are coming from. So routes are changing, but Plausible is not firing events.

Like I said, it's questionable if this is a bug. It's based on the implementation of the router. I don't know if react-router-dom's implementation is what's being done for most React routing solutions, but I think the usage of history.pushState as the underlying API is pretty common. Which means that any hash-based location system built on top of that will not trigger Plausible page events currently. So it's not really a bug in Plausible, but it might impact a fair number of potential Plausible users. On the other hand, hash-based routing isn't very common these days. Still, some hosts necessitate it -- such as GitHub Pages -- so it might be worth looking into this issue.

If you'd like to replicate the issue, the repo I'm working in is here, and you can see where I load Plausible here. If you run the app locally (and set the VITE_PLAUSIBLE_KEY to a Plausible account key you can watch), you can see what I'm talking about by navigating in the app (load root page, click the "Load Demo" button, notice that no event has fired for the change to /#/app).

Expected behavior

Expected using hash-based routing in React SPA plus Plausible's hash extension to (basically) give the same visibility to location changes as non-hash-based routing. Instead, you only see an event for the initial page load, and then all subsequent navigation in the app does not show up in Plausible.

Screenshots

No response

Environment

- OS: MacOS
- Browser: Chrome
- Browser Version: 105.0.5195.102 (Official Build) (x86_64)
RobertJoonas commented 2 years ago

Thanks for the feedback @vincent-czi!

This is definitely a use case to consider. I think we could have an optional script attribute like hash-history-api, that would make the hash extension use the History API instead of listening to the hashchange event. Just an idea, not sure if there are other ways to do it, but I feel like this is not a trivial change. It would require some more effort and has to be tested as well. Unfortunately, at this point, I cannot make any promises on when we'll be able to work on this. Sorry about that!