Skip to content
This repository was archived by the owner on Jul 29, 2025. It is now read-only.

Conversation

lricoy
Copy link
Member

@lricoy lricoy commented Apr 9, 2025

Problem

This Bluesky thread gave us the idea: https://bsky.app/profile/danabra.mov/post/3lmflnn62ys2y to have a tiny sdk option for simple navigation event capture.

This internal Slack thread also has some comments, it is my first SDK PR: https://posthog.slack.com/archives/C03P7NL6RMW/p1744225093576939

I've bundled a simple repo to test this out: https://lricoy.github.io/test-posthog-history/

Changes

Added an option to attach listeners to the browser's history api and autocapture pageviews.

Release info Sub-libraries affected

Bump level

  • Major
  • Minor
  • Patch

Libraries affected

  • All of them
  • posthog-web
  • posthog-node
  • posthog-ai
  • posthog-react-native

Changelog notes

  • Added trackHistoryEvents option to automatically capture navigation events in single-page applications using the History API.

Copy link

github-actions bot commented Apr 9, 2025

Size Change: +1.83 kB (+1.09%)

Total Size: 170 kB

Filename Size Change
posthog-react-native/lib/posthog-core/src/utils.js 979 B +23 B (+2.41%)
posthog-web/lib/index.cjs.js 22.1 kB +905 B (+4.26%)
posthog-web/lib/index.esm.js 22.1 kB +904 B (+4.27%)
ℹ️ View Unchanged
Filename Size
posthog-node/lib/index.cjs.js 34.9 kB
posthog-node/lib/index.esm.js 34.6 kB
posthog-react-native/lib/posthog-core/src/eventemitter.js 1.08 kB
posthog-react-native/lib/posthog-core/src/featureFlagUtils.js 1.51 kB
posthog-react-native/lib/posthog-core/src/index.js 12.6 kB
posthog-react-native/lib/posthog-core/src/lz-string.js 1.42 kB
posthog-react-native/lib/posthog-core/src/surveys-types.js 702 B
posthog-react-native/lib/posthog-core/src/types.js 492 B
posthog-react-native/lib/posthog-core/src/vendor/uuidv7.js 2.04 kB
posthog-react-native/lib/posthog-react-native/index.js 477 B
posthog-react-native/lib/posthog-react-native/src/autocapture.js 1.8 kB
posthog-react-native/lib/posthog-react-native/src/frameworks/wix-navigation.js 505 B
posthog-react-native/lib/posthog-react-native/src/hooks/useFeatureFlag.js 437 B
posthog-react-native/lib/posthog-react-native/src/hooks/useFeatureFlags.js 362 B
posthog-react-native/lib/posthog-react-native/src/hooks/useNavigationTracker.js 628 B
posthog-react-native/lib/posthog-react-native/src/hooks/usePostHog.js 249 B
posthog-react-native/lib/posthog-react-native/src/legacy.js 810 B
posthog-react-native/lib/posthog-react-native/src/native-deps.js 1.34 kB
posthog-react-native/lib/posthog-react-native/src/optional/OptionalAsyncStorage.js 183 B
posthog-react-native/lib/posthog-react-native/src/optional/OptionalExpoApplication.js 215 B
posthog-react-native/lib/posthog-react-native/src/optional/OptionalExpoDevice.js 211 B
posthog-react-native/lib/posthog-react-native/src/optional/OptionalExpoFileSystem.js 224 B
posthog-react-native/lib/posthog-react-native/src/optional/OptionalExpoLocalization.js 216 B
posthog-react-native/lib/posthog-react-native/src/optional/OptionalReactNativeDeviceInfo.js 220 B
posthog-react-native/lib/posthog-react-native/src/optional/OptionalReactNativeLocalize.js 169 B
posthog-react-native/lib/posthog-react-native/src/optional/OptionalReactNativeNavigation.js 218 B
posthog-react-native/lib/posthog-react-native/src/optional/OptionalReactNativeNavigationWix.js 222 B
posthog-react-native/lib/posthog-react-native/src/optional/OptionalReactNativeSafeArea.js 312 B
posthog-react-native/lib/posthog-react-native/src/optional/OptionalSessionReplay.js 231 B
posthog-react-native/lib/posthog-react-native/src/posthog-rn.js 4.85 kB
posthog-react-native/lib/posthog-react-native/src/PostHogContext.js 210 B
posthog-react-native/lib/posthog-react-native/src/PostHogProvider.js 1.74 kB
posthog-react-native/lib/posthog-react-native/src/storage.js 1.09 kB
posthog-react-native/lib/posthog-react-native/src/surveys/components/BottomSection.js 630 B
posthog-react-native/lib/posthog-react-native/src/surveys/components/Cancel.js 527 B
posthog-react-native/lib/posthog-react-native/src/surveys/components/ConfirmationMessage.js 742 B
posthog-react-native/lib/posthog-react-native/src/surveys/components/QuestionHeader.js 547 B
posthog-react-native/lib/posthog-react-native/src/surveys/components/QuestionTypes.js 2.81 kB
posthog-react-native/lib/posthog-react-native/src/surveys/components/SurveyModal.js 1.6 kB
posthog-react-native/lib/posthog-react-native/src/surveys/components/Surveys.js 1.82 kB
posthog-react-native/lib/posthog-react-native/src/surveys/getActiveMatchingSurveys.js 907 B
posthog-react-native/lib/posthog-react-native/src/surveys/icons.js 1.86 kB
posthog-react-native/lib/posthog-react-native/src/surveys/index.js 222 B
posthog-react-native/lib/posthog-react-native/src/surveys/PostHogSurveyProvider.js 1.82 kB
posthog-react-native/lib/posthog-react-native/src/surveys/surveys-utils.js 2.35 kB
posthog-react-native/lib/posthog-react-native/src/surveys/useActivatedSurveys.js 1.41 kB
posthog-react-native/lib/posthog-react-native/src/surveys/useSurveyStorage.js 690 B
posthog-react-native/lib/posthog-react-native/src/types.js 90 B
posthog-react-native/lib/posthog-react-native/src/version.js 123 B

compressed-size-action

@lricoy lricoy force-pushed the feat/add-history-api-autocapture-pageviews branch from 5dc9f12 to 9f84c7c Compare April 9, 2025 20:29
Copy link
Member

@rafaeelaudibert rafaeelaudibert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do love how easy this is for those using the History API, excellent job.

Main question: on our main posthog-js library we put a lot of effort into making sure we're tracking time spent in session and blahblahblah for SPAs, by sending some extra information in follow-up $pageview events. Are we doing the same in this lib? If not, we'll need to port that to this lib as well


Things that popped in my head

trackHistoryEvents is not a property that exists in our main posthog-js library, and I'm afraid I wouldn't want this library to have more features than our main lib.

I'm in favor of adding this feature to both as that might simplify some of our NextJS setup. That might be a slightly bigger undertaking, though, since you'll need to update a lot of docs :)

For dan in specific, he should be able to simply use the lite version and call the tracking automatically while this isn't merged - just like you did.

@lricoy lricoy marked this pull request as ready for review April 9, 2025 21:11
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Summary

The PR introduces a new feature for automatically capturing navigation events via the History API, updating types, documentation, implementation, and tests accordingly.

  • Updated posthog-web/src/types.ts to include the new trackHistoryEvents option.
  • Modified posthog-web/README.md to document History API tracking with examples.
  • Implemented overriding of history methods and added popstate listener in posthog-web/src/posthog-web.ts.
  • Added comprehensive tests for navigation events in posthog-web/test/posthog-web.spec.ts.
  • Changelog in posthog-web/CHANGELOG.md now reflects the added History API tracking feature.

5 file(s) reviewed, 1 comment(s)
Edit PR Review Bot Settings | Greptile

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
@lricoy
Copy link
Member Author

lricoy commented Apr 9, 2025

Main question: on our main posthog-js library we put a lot of effort into making sure we're tracking time spent in session and blahblahblah for SPAs, by sending some extra information in follow-up $pageview events. Are we doing the same in this lib? If not, we'll need to port that to this lib as well

That makes total sense, thanks! If approved, I was planning on porting that to posthog-js as well, as it seems useful enough. I'll probably add some more work to handle $pageleave as well and help with those session time calculations. It seems there are some work around that for the RN version of this lib.

I will take a look at those extra features on posthog-js as well, thanks!

const posthog = new PostHog('my-api-key', {
/* options, e.g. for self-hosted users */
// host: "https://my-posthog.app.com"
// trackHistoryEvents: true // Enable tracking of History API navigation events as pageviews
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

trackHistoryEvents is not a property that exists in our main posthog-js library, and I'm afraid I wouldn't want this library to have more features than our main lib.

i'm ok with adding this here if we then also add it in posthog-js... it's a super cool improvement

(we should definitely play with it running agains posthog locally since that's a SPA to figure out if it does anything weird but that's only me being cautious :))


in the main lib we tend to call config options captureX so might be worth keeping that here and calling it captureHistoryEvents seems nit-picky but the cognitive overload of config grows over time :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will apply the changes, I've bundled this version into a repo to give it a few shots as well: https://lricoy.github.io/test-posthog-history/

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// trackHistoryEvents: true // Enable tracking of History API navigation events as pageviews
// captureHistoryEvents: true // Enable tracking of History API navigation events as pageviews

const originalPushState = window.history.pushState
const originalReplaceState = window.history.replaceState

window.history.pushState = (state, title, url) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in the main lib we copied a patch function from rrweb, which was in turn originally copied from sentry

(but there are hundreds out there)

https://github.com/PostHog/posthog-js/blob/main/src/extensions/replay/rrweb-plugins/patch.ts

the main thing to copy from that would be marking the thing as wrapped

https://github.com/PostHog/posthog-js/blob/main/src/extensions/replay/rrweb-plugins/patch.ts#L24-L32

again seems nit-picky but I really struggled to fix bugs between Angular's Zone detection stuff and replay because it was hard to track what was wrapped, so it's nice for the future traveller to be able to easily see that something isn't the original when debugging something

also means we can check for that and not wrap the function a second time if this gets called more than once

return
}

this.capture('$pageview', { navigation_type: navigationType })
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to Rafa's point about there being lots of good stuff on page view in the main lib
we should check if there's anything we can very easily add here

but otherwise it's also fine for us to say "yep, lite doesn't do that, you can use the full fat posthog to get that"

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checking this now to see if we can easily grab something there.

Copy link
Member Author

@lricoy lricoy Apr 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the features @rafaeelaudibert mentioned are mostly handled by the PageViewManager/ScrollManager which does not seem crazy to have it here as well.

The page view durations and increments don't even need the ScrollManager bits; they are calculated based on the last pageview ref that is kept around on the PageViewManager.

But there is also session-related stuff that is way way simpler here than what we have on both SessionIdManager
and SessionPropsManager... So I am not sure how much we should port without documenting or keeping track of the differences.

WDYT @robbie-c ?

I'm inclined to say, "Yep, lite doesn't do that," for now, but a direction for our future work would be cool, even if just for docs.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm.

We don't actually use the scroll information or time on page in web analytics - so I'd be tempted to leave it out here actually!

We haven't exactly defined what posthog-js-lite is for, but one version I would propose would be: "the smallest bundle size possible where everything in web analytics still works", wdyt?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I'm pretty sure we don't meet that goal right now, FWIW, e.g. I don't think we handle $pageleave events in this library)

Copy link
Member

@pauldambra pauldambra Apr 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'd say "the smallest bundle where basic analytics and flags work"

that way we're not tied to chasing a feature set for a subset of customers who want feature X, y, and Z and a tiny bundle

this is the "i can live with almost nothing" bundle

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The argument of whether session props are "basic analytics" or not can be made. I think it would be worth keeping at least that in sync between js and lite, as it is very helpful for attribution analysis, and although not as lite, having the session definitions is core to a lot of our metrics from what I can tell... It would involve way more testing, than what's in this PR IMO.

If you agree, I can take a better look later at how to add that and still keep the bundle size in check later on. Sounds like a good plan for me.

@pauldambra
Copy link
Member

this is super cool though @lricoy , love it!

@lricoy lricoy requested a review from marandaneto as a code owner April 9, 2025 21:41
@lricoy lricoy force-pushed the feat/add-history-api-autocapture-pageviews branch from cb8b1b1 to 56df28c Compare April 9, 2025 21:43
@lricoy lricoy requested a review from robbie-c April 9, 2025 21:44
Copy link
Member

@pauldambra pauldambra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

couple of comment edits
i didn't run/test this but I can if helpful, your example website was great for seeing it run though! 🙌

very excited for the posthog-js follow-up and then all the documentation simplication 🚀

@lricoy
Copy link
Member Author

lricoy commented Apr 10, 2025

For reference, I've started the work on posthog-js yesterday on this PR: PostHog/posthog-js#1886

I will wrap it up later today.

@lricoy lricoy requested a review from pauldambra April 11, 2025 00:50
@lricoy lricoy merged commit 5992bc1 into main Apr 11, 2025
4 checks passed
@lricoy lricoy deleted the feat/add-history-api-autocapture-pageviews branch April 11, 2025 20:17
@lricoy
Copy link
Member Author

lricoy commented Apr 11, 2025

Merging this as it is a simpler change, while PostHog/posthog-js#1886 still waits for a ✅

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants