diff --git a/examples/nuxt-app/test/features/site/analytics.feature b/examples/nuxt-app/test/features/site/analytics.feature index 18110e28e5..9c5da8ca18 100644 --- a/examples/nuxt-app/test/features/site/analytics.feature +++ b/examples/nuxt-app/test/features/site/analytics.feature @@ -1,7 +1,7 @@ Feature: Analytics @mockserver - Scenario: DataLayer - page view + Scenario: Page view Given the site endpoint returns fixture "/site/reference" with status 200 And the page endpoint for path "/" returns fixture "/landingpage/home" with status 200 Given I visit the page "/" @@ -10,7 +10,7 @@ Feature: Analytics | routeChange | Demo Landing Page | / | landing_page | @mockserver - Scenario: DataLayer - breadcrumbs + Scenario: Breadcrumbs Given the site endpoint returns fixture "/site/vic" with status 200 And the page endpoint for path "/education" returns fixture "/landingpage/home" with status 200 Given I visit the page "/education" @@ -18,3 +18,20 @@ Feature: Analytics | title | | Information and services | | Education | + + @mockserver + Scenario: Back to top + Given the site endpoint returns fixture "/site/vic" with status 200 + And the page endpoint for path "/" returns fixture "/landingpage/home" with status 200 + Given I visit the page "/" + And I scroll 2020 pixels + Then I click the back to top button + And I scroll 4000 pixels + Then I click the back to top button + And I scroll 5980 pixels + Then I click the back to top button + Then the dataLayer should have the following back to top scroll percentages + | scroll | + | 25 | + | 50 | + | 75 | diff --git a/packages/nuxt-ripple-analytics/lib/index.ts b/packages/nuxt-ripple-analytics/lib/index.ts index 7e8d058ddb..30b04a504d 100644 --- a/packages/nuxt-ripple-analytics/lib/index.ts +++ b/packages/nuxt-ripple-analytics/lib/index.ts @@ -562,6 +562,17 @@ export default { }) } }, + 'rpl-layout-back-to-top/navigate': () => { + return (payload: any) => { + trackEvent({ + event: `${payload.action}_back_to_top`, + element_text: payload?.text, + value: payload?.value, + component: 'rpl-layout-back-to-top', + platform_event: 'navigate' + }) + } + }, // UI Forms components 'rpl-form/submit': () => { return (payload: any) => { diff --git a/packages/ripple-test-utils/step_definitions/common/navigation.ts b/packages/ripple-test-utils/step_definitions/common/navigation.ts index c5bbb74b39..9f1abf8b2d 100644 --- a/packages/ripple-test-utils/step_definitions/common/navigation.ts +++ b/packages/ripple-test-utils/step_definitions/common/navigation.ts @@ -112,3 +112,11 @@ Then( }) } ) + +Then('I scroll {int} pixels', (pixels: number) => { + cy.scrollTo(0, pixels) +}) + +Then('I click the back to top button', () => { + cy.get('.rpl-back-to-top__button').click() +}) diff --git a/packages/ripple-test-utils/step_definitions/common/site/analytics.ts b/packages/ripple-test-utils/step_definitions/common/site/analytics.ts index 8ee6e86557..9ceeb3ab5e 100644 --- a/packages/ripple-test-utils/step_definitions/common/site/analytics.ts +++ b/packages/ripple-test-utils/step_definitions/common/site/analytics.ts @@ -40,3 +40,21 @@ Then( }) } ) + +Then( + 'the dataLayer should have the following back to top scroll percentages', + (dataTable: DataTable) => { + const table = dataTable.hashes() + + cy.window().then((window) => { + const events = window.dataLayer?.filter( + (i) => i.event === 'click_back_to_top' + ) + + table.forEach((row, index) => { + expect(events[index].value).to.be.greaterThan(Number(row.scroll) - 3) + expect(events[index].value).to.be.lessThan(Number(row.scroll) + 3) + }) + }) + } +) diff --git a/packages/ripple-ui-core/src/components/layout/RplLayoutBackToTop.vue b/packages/ripple-ui-core/src/components/layout/RplLayoutBackToTop.vue index ae4c0670e7..7c74ea95ac 100644 --- a/packages/ripple-ui-core/src/components/layout/RplLayoutBackToTop.vue +++ b/packages/ripple-ui-core/src/components/layout/RplLayoutBackToTop.vue @@ -2,12 +2,25 @@ import RplButton from '../button/RplButton.vue' import { useWindowScroll, useElementBounding } from '@vueuse/core' import { ref, computed } from 'vue' +import { + useRippleEvent, + rplEventPayload +} from '../../composables/useRippleEvent' interface Props { + label?: string topElementId: string } -withDefaults(defineProps(), {}) +const props = withDefaults(defineProps(), { + label: 'Back to top' +}) + +const emit = defineEmits<{ + (e: 'navigate', payload: rplEventPayload & { action: 'click' }): void +}>() + +const { emitRplEvent } = useRippleEvent('rpl-layout-back-to-top', emit) // This is the number of pixels down the page you need to scroll before you see // the back to top button. @@ -29,6 +42,21 @@ const isSticky = computed(() => { return offsetTop.value > window.innerHeight }) + +const handleClick = () => { + const pageHeight = document.documentElement.scrollHeight - window.innerHeight + const scrollPercentage = Math.round((scrollY.value / pageHeight) * 100) + + emitRplEvent( + 'navigate', + { + action: 'click', + text: props.label, + value: scrollPercentage + }, + { global: true } + ) +}