-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Analytics scroll depth #12079
feat: Analytics scroll depth #12079
Changes from all commits
0f81d80
c12c0ca
c26bb44
125bf64
6abf7e5
0f32831
6ccc03c
ca0eecb
4b82d07
e2cb24b
5eeb288
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ import {Theme} from '@radix-ui/themes'; | |
import type {Metadata} from 'next'; | ||
import {Rubik} from 'next/font/google'; | ||
import Script from 'next/script'; | ||
import PlausibleProvider from 'next-plausible'; | ||
|
||
import {ThemeProvider} from 'sentry-docs/components/theme-provider'; | ||
|
||
|
@@ -31,6 +32,9 @@ export const metadata: Metadata = { | |
export default function RootLayout({children}: {children: React.ReactNode}) { | ||
return ( | ||
<html lang="en" suppressHydrationWarning> | ||
<head> | ||
<PlausibleProvider domain="docs.sentry.io,rollup.sentry.io" /> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we need dev docs as well? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Probably, we should ask @lizokm There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It doesn't look like we have Plausible installed on dev docs (if it is, it's not hooked up to the company account). |
||
</head> | ||
<body className={rubik.variable} suppressHydrationWarning> | ||
<ThemeProvider | ||
attribute="class" | ||
|
@@ -42,26 +46,20 @@ export default function RootLayout({children}: {children: React.ReactNode}) { | |
{children} | ||
</Theme> | ||
</ThemeProvider> | ||
<Script | ||
async | ||
src="https://widget.kapa.ai/kapa-widget.bundle.js" | ||
data-website-id="cac7cc70-969e-4bc1-a968-55534a839be4" | ||
data-button-hide // do not render kapa ai button | ||
data-modal-override-open-class="kapa-ai-class" // all elements with this class will open the kapa ai modal | ||
data-project-name="Sentry" | ||
data-project-color="#6A5FC1" | ||
data-project-logo="https://avatars.githubusercontent.com/u/1396951?s=280&v=4" | ||
data-font-family="var(--font-rubik)" | ||
data-modal-disclaimer="Disclaimer: Welcome to our knowledge search bot! While we'd love to be able to answer all your questions, please remember this is a tool for searching our publicly available sources and not a support forum. Don't include any sensitive or personal information in your queries. For more on how Sentry handles your data, see our [Privacy Policy](https://sentry.io/privacy/). This form is protected by reCAPTCHA. Google's Privacy Policy and Google's Terms of Service apply." | ||
data-modal-example-questions="How to set up Sentry for Next.js?,What are tracePropagationTargets?" | ||
/> | ||
</body> | ||
<Script | ||
defer | ||
data-domain="docs.sentry.io,rollup.sentry.io" | ||
data-api="https://plausible.io/api/event" | ||
src="https://plausible.io/js/script.tagged-events.js" | ||
/> | ||
<Script | ||
async | ||
src="https://widget.kapa.ai/kapa-widget.bundle.js" | ||
data-website-id="cac7cc70-969e-4bc1-a968-55534a839be4" | ||
data-button-hide // do not render kapa ai button | ||
data-modal-override-open-class="kapa-ai-class" // all elements with this class will open the kapa ai modal | ||
data-project-name="Sentry" | ||
data-project-color="#6A5FC1" | ||
data-project-logo="https://avatars.githubusercontent.com/u/1396951?s=280&v=4" | ||
data-font-family="var(--font-rubik)" | ||
data-modal-disclaimer="Disclaimer: Welcome to our knowledge search bot! While we'd love to be able to answer all your questions, please remember this is a tool for searching our publicly available sources and not a support forum. Don't include any sensitive or personal information in your queries. For more on how Sentry handles your data, see our [Privacy Policy](https://sentry.io/privacy/). This form is protected by reCAPTCHA. Google's Privacy Policy and Google's Terms of Service apply." | ||
data-modal-example-questions="How to set up Sentry for Next.js?,What are tracePropagationTargets?" | ||
/> | ||
</html> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
'use client'; | ||
import {useEffect} from 'react'; | ||
import {usePlausible} from 'next-plausible'; | ||
|
||
import {debounce} from 'sentry-docs/utils'; | ||
|
||
const EVENT = 'Read Progress'; | ||
const milestones = [25, 50, 75, 100] as const; | ||
type Milestone = (typeof milestones)[number]; | ||
type EVENT_PROPS = {page: string; readProgress: Milestone}; | ||
|
||
export function ReaderDepthTracker() { | ||
const plausible = usePlausible<{[EVENT]: EVENT_PROPS}>(); | ||
|
||
const sendProgressToPlausible = (progress: Milestone) => { | ||
plausible(EVENT, {props: {readProgress: progress, page: document.title}}); | ||
}; | ||
|
||
useEffect(() => { | ||
const reachedMilestones = new Set<Milestone>(); | ||
|
||
const trackProgress = () => { | ||
// calculate the progress based on the scroll position | ||
const scrollPosition = window.scrollY; | ||
const totalHeight = document.documentElement.scrollHeight - window.innerHeight; | ||
let progress = Math.floor((scrollPosition / totalHeight) * 100); | ||
// it's hard to trigger the 100% milestone, so we'll just assume beyond 95% | ||
if (progress > 95) { | ||
progress = 100; | ||
} | ||
|
||
// find the biggest milestone that has not been reached yet | ||
const milestone = milestones.findLast( | ||
m => | ||
progress >= m && | ||
!reachedMilestones.has(m) && | ||
// we shouldn't report smaller milestones once a bigger one has been reached | ||
Array.from(reachedMilestones).every(r => m > r) | ||
); | ||
if (milestone) { | ||
reachedMilestones.add(milestone); | ||
sendProgressToPlausible(milestone); | ||
} | ||
}; | ||
|
||
// if the page is not scrollable, we don't need to track anything | ||
if (document.documentElement.scrollHeight - window.innerHeight === 0) { | ||
return () => {}; | ||
} | ||
const debouncedTrackProgress = debounce(trackProgress, 50); | ||
|
||
window.addEventListener('scroll', debouncedTrackProgress); | ||
return () => { | ||
window.removeEventListener('scroll', debouncedTrackProgress); | ||
}; | ||
}); | ||
// do not render anything | ||
return null; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the advantage of having this instead of the script?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
send events dynamically through a hook, nice TS and local DX experience