Skip to content

Commit cd70532

Browse files
committed
Tracks sandbox interactions for analytics
Implements event tracking for user interactions within the sandbox environment. This change captures key interactions, such as clicks and hovers, to provide insights into user behavior and improve the sandbox experience. The data collected will inform decisions on sandbox discoverability, engagement, and overall user satisfaction.
1 parent 5714e61 commit cd70532

File tree

5 files changed

+43
-16
lines changed

5 files changed

+43
-16
lines changed

src/components/interactive-lab-callout/index.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { useInstruqtEmbed } from 'contexts/instruqt-lab'
1010
import { FC } from 'react'
1111
import s from './interactive-lab-callout.module.css'
1212
import SANDBOX_CONFIG from 'content/sandbox/sandbox.json' assert { type: 'json' }
13+
import { trackSandboxInteraction } from 'views/sandbox-view'
1314

1415
interface InteractiveLabCalloutProps {
1516
labId?: string
@@ -34,6 +35,9 @@ const InteractiveLabCallout: FC<InteractiveLabCalloutProps> = ({ labId }) => {
3435

3536
const handleStartLab = () => {
3637
if (effectiveLabId) {
38+
trackSandboxInteraction('click', effectiveLabId, {
39+
source: 'interactive-lab-callout',
40+
})
3741
ctx.openLab(effectiveLabId)
3842
ctx.setActive(true)
3943
} else {

src/components/lab-embed/embed-element/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ const EmbedElement = memo(function EmbedElement(): JSX.Element {
5050
}))
5151

5252
if (labId) {
53-
trackSandboxEvent(SANDBOX_EVENT.SANDBOX_LOADED, {
53+
trackSandboxEvent(SANDBOX_EVENT.SANDBOX_OPEN, {
5454
labId,
5555
page: router.asPath,
5656
})

src/components/navigation-header/components/sandbox-dropdown/index.tsx

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { SandboxLab } from 'types/sandbox'
2323
import { ProductSlug } from 'types/products'
2424
import { buildLabIdWithConfig } from 'lib/build-instruqt-url'
2525
import { useTheme } from 'next-themes'
26+
import { trackSandboxInteraction } from 'views/sandbox-view'
2627

2728
interface SandboxDropdownProps {
2829
ariaLabel: string
@@ -122,9 +123,6 @@ const SandboxDropdown = ({ ariaLabel, label }: SandboxDropdownProps) => {
122123
}
123124
}
124125

125-
/**
126-
* Handle lab selection
127-
*/
128126
const handleLabClick = (lab: SandboxLab) => {
129127
const labWithTrack = {
130128
...lab,
@@ -133,16 +131,13 @@ const SandboxDropdown = ({ ariaLabel, label }: SandboxDropdownProps) => {
133131
const fullLabId = buildLabIdWithConfig(labWithTrack)
134132
openLab(fullLabId)
135133
setActive(true)
136-
trackSandboxEvent(SANDBOX_EVENT.SANDBOX_STARTED, {
134+
trackSandboxEvent(SANDBOX_EVENT.SANDBOX_OPEN, {
137135
labId: fullLabId,
138136
page: router.asPath,
139137
})
140138
setIsOpen(false)
141139
}
142140

143-
/**
144-
* Navigate to the sandbox page
145-
*/
146141
const navigateToSandboxPage = (e: React.MouseEvent) => {
147142
e.preventDefault()
148143
router.push(`/${currentProduct.slug}/sandbox`)
@@ -230,7 +225,6 @@ const SandboxDropdown = ({ ariaLabel, label }: SandboxDropdownProps) => {
230225
</Text>
231226
</button>
232227

233-
{/* Available Product Sandboxes Section */}
234228
<Text
235229
asElement="p"
236230
className={s.sectionTitle}
@@ -245,7 +239,12 @@ const SandboxDropdown = ({ ariaLabel, label }: SandboxDropdownProps) => {
245239
<li key={lab.labId || index} className={s.itemContainer}>
246240
<button
247241
className={s.sandboxItem}
248-
onClick={() => handleLabClick(lab)}
242+
onClick={() => {
243+
handleLabClick(lab)
244+
trackSandboxInteraction('hover', lab.labId, {
245+
page: router.asPath,
246+
})
247+
}}
249248
onKeyDown={handleKeyDown}
250249
>
251250
<div className={s.content}>

src/components/sandbox-card/index.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import CardFooter from 'components/card/components/card-footer'
1212
import ButtonLink from 'components/button-link'
1313
import ProductIcon from 'components/product-icon'
1414
import s from './sandbox-card.module.css'
15+
import { trackSandboxInteraction } from 'views/sandbox-view'
1516

1617
export interface SandboxCardProps {
1718
title: string
@@ -20,6 +21,7 @@ export interface SandboxCardProps {
2021
products: string[]
2122
onLaunch: () => void
2223
className?: string
24+
clickBehavior?: 'card' | 'button'
2325
}
2426

2527
const SandboxCard: React.FC<SandboxCardProps> = ({
@@ -55,6 +57,7 @@ const SandboxCard: React.FC<SandboxCardProps> = ({
5557
onClick={(e) => {
5658
e.preventDefault()
5759
e.stopPropagation()
60+
trackSandboxInteraction('click', labId, { lab_title: title })
5861
onLaunch()
5962
}}
6063
size="medium"

src/views/sandbox-view/index.tsx

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,21 @@ interface SandboxPageProps {
3636
availableSandboxes: SandboxLab[]
3737
otherSandboxes: SandboxLab[]
3838
}
39+
export const trackSandboxInteraction = (
40+
interactionType: string,
41+
sandboxId: string,
42+
additionalProps: Record<string, unknown> = {}
43+
) => {
44+
if (typeof window !== 'undefined' && posthog?.capture) {
45+
posthog.capture(SANDBOX_EVENT.SANDBOX_OPEN, {
46+
interaction_type: interactionType,
47+
sandbox_id: sandboxId,
48+
...additionalProps,
49+
timestamp: new Date().toISOString(),
50+
page_url: window.location.href,
51+
})
52+
}
53+
}
3954

4055
const trackSandboxPageError = (
4156
errorType: string,
@@ -70,12 +85,17 @@ export const SandboxView = ({
7085
const handleLabClick = useCallback(
7186
(lab: SandboxLab) => {
7287
try {
88+
trackSandboxInteraction(SANDBOX_EVENT.SANDBOX_OPEN, lab.labId, {
89+
lab_title: lab.title,
90+
products: lab.products,
91+
})
92+
7393
const primaryProduct = lab.products[0]
7494
if (primaryProduct !== product.slug) {
7595
// Redirect to the lab's primary product sandbox page with auto-launch
7696
const targetUrl = `/${primaryProduct}/sandbox?launch=${lab.labId}`
7797

78-
trackSandboxEvent(SANDBOX_EVENT.SANDBOX_STARTED, {
98+
trackSandboxEvent(SANDBOX_EVENT.SANDBOX_OPEN, {
7999
labId: lab.labId,
80100
page: targetUrl,
81101
})
@@ -86,7 +106,7 @@ export const SandboxView = ({
86106

87107
if (hasConfigError) {
88108
trackSandboxPageError(
89-
'config_error_lab_launch',
109+
SANDBOX_EVENT.SANDBOX_ERROR,
90110
'Cannot launch lab due to configuration error',
91111
{
92112
lab_id: lab.labId,
@@ -106,7 +126,7 @@ export const SandboxView = ({
106126

107127
if (!openLab) {
108128
trackSandboxPageError(
109-
'open_lab_function_missing',
129+
SANDBOX_EVENT.SANDBOX_ERROR,
110130
'openLab function is not available',
111131
{
112132
lab_id: lab.labId,
@@ -128,7 +148,7 @@ export const SandboxView = ({
128148

129149
if (!embedLabId) {
130150
trackSandboxPageError(
131-
'missing_lab_id',
151+
SANDBOX_EVENT.SANDBOX_ERROR,
132152
'Lab embed ID is missing or invalid',
133153
{
134154
lab_id: lab.labId,
@@ -149,7 +169,7 @@ export const SandboxView = ({
149169
openLab(embedLabId)
150170
setActive(true)
151171

152-
trackSandboxEvent(SANDBOX_EVENT.SANDBOX_STARTED, {
172+
trackSandboxEvent(SANDBOX_EVENT.SANDBOX_OPEN, {
153173
labId: lab.labId,
154174
page: `/${product.slug}/sandbox`,
155175
})
@@ -236,7 +256,7 @@ export const SandboxView = ({
236256
)
237257
} catch (error) {
238258
trackSandboxPageError(
239-
'documentation_render_failed',
259+
SANDBOX_EVENT.SANDBOX_ERROR,
240260
'Failed to render sandbox documentation',
241261
{
242262
error_message: error instanceof Error ? error.message : String(error),
@@ -313,6 +333,7 @@ export const SandboxView = ({
313333
labId={lab.labId}
314334
products={lab.products}
315335
onLaunch={() => handleLabClick(lab)}
336+
clickBehavior="button"
316337
/>
317338
)
318339
})}

0 commit comments

Comments
 (0)