Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions example/src/components/ContentTracking/ContentTrackingMethods.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Box, Button, Paper } from '@mui/material'
import { ElementRef, useEffect, useRef } from 'react'
import { ContentTracking } from '@piwikpro/react-piwik-pro'

export function ContentTrackingMethods() {
const ref = useRef<ElementRef<'div'>>(null)

useEffect(() => {
if (!ref.current) return

ContentTracking.trackContentImpressionsWithinNode(ref.current)
ContentTracking.trackContentInteractionNode(ref.current, 'click')
}, [])

return (
<>
<Paper sx={{ p: 2 }}>
<Box
ref={ref}
data-track-content
data-content-name='element'
data-content-piece='slow element'
>
Track content within a specific dom node
</Box>
</Paper>

<Box sx={{ my: 5 }}>
<Button
variant='outlined'
onClick={() =>
ContentTracking.trackContentImpression(
'tracking element',
'button',
'button'
)
}
>
Manual content tracking on demand
</Button>
</Box>
</>
)
}
57 changes: 57 additions & 0 deletions example/src/components/ContentTrackingForm/ContentTrackingForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import Box from '@mui/material/Box'
import Tab from '@mui/material/Tab'
import Tabs from '@mui/material/Tabs'
import { useState } from 'react'
import { Login } from './Login'
import { Register } from './Register'

interface TabPanelProps {
children?: React.ReactNode
index: number
value: number
}

function CustomTabPanel(props: TabPanelProps) {
const { children, value, index, ...other } = props

return (
<div
role='tabpanel'
hidden={value !== index}
id={`simple-tabpanel-${index}`}
aria-labelledby={`simple-tab-${index}`}
{...other}
>
{value === index && <Box sx={{ p: 3 }}>{children}</Box>}
</div>
)
}

export function ContentTrackingForm() {
const [value, setValue] = useState(0)

const handleChange = (_event: React.SyntheticEvent, newValue: number) => {
setValue(newValue)
}

return (
<Box sx={{ width: '100%', maxWidth: '750px' }}>
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
<Tabs
value={value}
onChange={handleChange}
aria-label='basic tabs example'
>
<Tab label='Login' />
<Tab label='Register' />
</Tabs>
</Box>
<CustomTabPanel value={value} index={0}>
<Login />
</CustomTabPanel>
<CustomTabPanel value={value} index={1}>
<Register />
</CustomTabPanel>
</Box>
)
}
22 changes: 22 additions & 0 deletions example/src/components/ContentTrackingForm/Login.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Button, Stack, TextField } from '@mui/material'
import { useEffect } from 'react'
import { ContentTracking } from '@piwikpro/react-piwik-pro'

export function Login() {
// NOTE: candidate for a custom hook useTrackAllContentImpressions()
useEffect(() => {
ContentTracking.trackAllContentImpressions()

return () => ContentTracking.clearTrackedContentImpressions()
}, [])

return (
<Stack gap={2} data-track-content data-content-name='Login form'>
<TextField label='Login' data-content-piece='Login input' />
<TextField label='Password' data-content-piece='Password input' />
<Button variant='contained' data-content-piece='Login button'>
Login
</Button>
</Stack>
)
}
31 changes: 31 additions & 0 deletions example/src/components/ContentTrackingForm/Register.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Button, Stack, TextField } from '@mui/material'
import { ContentTracking } from '@piwikpro/react-piwik-pro'
import { useEffect } from 'react'

export function Register() {
useEffect(() => {
ContentTracking.trackAllContentImpressions()

return () => ContentTracking.clearTrackedContentImpressions()
}, [])

return (
<Stack gap={2} data-track-content data-content-name='Register form'>
<TextField label='Login' data-content-piece='Login input' />
<TextField type='email' label='Email' data-content-piece='Email input' />
<TextField
type='password'
label='Password'
data-content-piece='Password input'
/>
<TextField
type='password'
label='Confirm Password'
data-content-piece='Confirm password input'
/>
<Button variant='contained' data-content-piece='Register button'>
Register
</Button>
</Stack>
)
}
71 changes: 71 additions & 0 deletions example/src/pages/ContentTrackingPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { Box, CircularProgress } from '@mui/material'
import Paper from '@mui/material/Paper'
import Typography from '@mui/material/Typography'
import { FunctionComponent, useEffect, useState } from 'react'
import { ContentTrackingMethods } from '../components/ContentTracking/ContentTrackingMethods'
import { ContentTrackingForm } from '../components/ContentTrackingForm/ContentTrackingForm'

const ContentTrackingPage: FunctionComponent = () => {
const [isLoading, setIsLoading] = useState(true)

useEffect(() => {
document.title = 'Content Tracking'
}, [])

useEffect(() => {
const timeout = setTimeout(() => {
setIsLoading(false)
}, 3000)

return () => {
clearTimeout(timeout)
}
}, [])

return (
<Paper
sx={{
p: 2,
display: 'flex',
flexDirection: 'column'
}}
>
<Typography component='h1' variant='h4' align='center'>
Content Tracking Example
</Typography>

<Box>
<Paper sx={{ p: 5, mt: 5 }}>
<Typography
data-track-content
data-content-name='block'
data-content-piece='paragraph'
data-content-target='target'
>
This element will be tracked automatically if it's present in DOM
before tracking script is loaded and `Interactions with popups and
content` setting is turned on in the administration panel
</Typography>
</Paper>

<Paper sx={{ mt: 5, p: 3 }}>
<Typography>
For content that will appear later in the DOM, like modals or
components that are waiting for data to be loaded, use{' '}
<b>ContentTracking</b> module
</Typography>

<Box sx={{ py: 5 }}>
{isLoading ? <CircularProgress /> : <ContentTrackingMethods />}
</Box>
</Paper>

<Paper sx={{ mt: 3 }}>
<ContentTrackingForm />
</Paper>
</Box>
</Paper>
)
}

export default ContentTrackingPage
6 changes: 6 additions & 0 deletions example/src/routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import HomePage from './pages/HomePage.tsx'
import ECommercePage from './pages/ECommercePage.tsx'
import CustomEventPage from './pages/CustomEventPage.tsx'
import GoalConversionsPage from './pages/GoalConversionsPage.tsx'
import ContentTrackingPage from './pages/ContentTrackingPage.tsx'

export const routes = [
{
Expand All @@ -23,5 +24,10 @@ export const routes = [
path: '/goal-conversions',
name: 'Goal Conversions',
element: <GoalConversionsPage />
},
{
path: '/content-tracking',
name: 'Content Tracking',
element: <ContentTrackingPage />
}
]
1 change: 1 addition & 0 deletions src/constants/track-event.constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export enum TRACK_EVENT {
LOG_ALL_CONTENT_BLOCKS_ON_PAGE = 'logAllContentBlocksOnPage',
CONTENT_INTERACTION_NODE = 'trackContentInteractionNode',
CONTENT_INTERACTION = 'trackContentInteraction',
CLEAR_TRACKED_CONTENT_IMPRESSIONS = 'clearTrackedContentImpressions',
LINK = 'trackLink',
ENABLE_LINK_TRACKING = 'enableLinkTracking',
SET_IGNORE_CLASSES = 'setIgnoreClasses',
Expand Down
4 changes: 4 additions & 0 deletions src/services/content-tracking/contentTracking.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,7 @@ export function trackContentInteraction(contentInteraction: string, contentName:
contentTarget
]);
}

export function clearTrackedContentImpressions(){
PaqService.push([TRACK_EVENT.CLEAR_TRACKED_CONTENT_IMPRESSIONS])
}