@treely/strapi-slices 7.7.1 → 7.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/components/ContextProvider/ContextProvider.d.ts +6 -0
  2. package/dist/components/SliceRenderer/SliceRenderer.d.ts +3 -1
  3. package/dist/components/StrapiLinkButton/StrapiLinkButton.d.ts +1 -0
  4. package/dist/strapi-slices.cjs.development.js +1506 -1369
  5. package/dist/strapi-slices.cjs.development.js.map +1 -1
  6. package/dist/strapi-slices.cjs.production.min.js +1 -1
  7. package/dist/strapi-slices.cjs.production.min.js.map +1 -1
  8. package/dist/strapi-slices.esm.js +1507 -1370
  9. package/dist/strapi-slices.esm.js.map +1 -1
  10. package/package.json +1 -1
  11. package/src/components/ContextProvider/ContextProvider.tsx +17 -1
  12. package/src/components/EventCard/EventCard.tsx +1 -0
  13. package/src/components/SliceRenderer/SliceRenderer.tsx +4 -1
  14. package/src/components/StrapiLinkButton/StrapiLinkButton.test.tsx +67 -7
  15. package/src/components/StrapiLinkButton/StrapiLinkButton.tsx +41 -4
  16. package/src/components/portfolio/Contact/Contact.tsx +7 -1
  17. package/src/components/portfolio/SmallCheckout/SmallCheckout.tsx +1 -0
  18. package/src/slices/BlogCards/BlogCards.tsx +2 -0
  19. package/src/slices/Comparison/Comparison.tsx +1 -0
  20. package/src/slices/Cta/Cta.tsx +1 -0
  21. package/src/slices/CtaOnly/CtaOnly.tsx +1 -1
  22. package/src/slices/Facts/Facts.tsx +1 -0
  23. package/src/slices/Hero/Hero.tsx +2 -0
  24. package/src/slices/IconGrid/IconGrid.tsx +1 -0
  25. package/src/slices/ImageGrid/ImageGrid.tsx +1 -0
  26. package/src/slices/ImageTextSequence/ImageTextSequence.tsx +1 -0
  27. package/src/slices/LeftTextRightCard/LeftTextRightCard.tsx +24 -2
  28. package/src/slices/LogoGridWithText/LogoGridWithText.tsx +1 -0
  29. package/src/slices/MapHero/MapHero.tsx +6 -1
  30. package/src/slices/QAndA/QAndA.tsx +21 -2
  31. package/src/slices/QuoteCards/QuoteCards.tsx +20 -2
  32. package/src/slices/SmallHero/SmallHero.tsx +6 -1
  33. package/src/slices/Steps/Steps.tsx +26 -2
  34. package/src/slices/TextCardGrid/TextCardGrid.tsx +1 -0
  35. package/src/slices/TextCarousel/TextCarousel.tsx +20 -1
  36. package/src/slices/TextWithCard/TextWithCard.tsx +1 -0
  37. package/src/slices/TextWithTextCards/TextWithTextCards.tsx +21 -3
  38. package/src/slices/Timeline/Timeline.tsx +1 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@treely/strapi-slices",
3
- "version": "7.7.1",
3
+ "version": "7.8.0",
4
4
  "license": "MIT",
5
5
  "author": "Tree.ly FlexCo",
6
6
  "description": "@treely/strapi-slices is a open source library maintained by Tree.ly.",
@@ -6,6 +6,18 @@ import getMessages from '../../utils/getMessages';
6
6
  import strapiClient from '../../integrations/strapi/strapiClient';
7
7
  import { SWRConfig } from 'swr/_internal';
8
8
 
9
+ export type AnalyticsFunction = ({
10
+ type,
11
+ props,
12
+ }: {
13
+ type: 'track' | 'page';
14
+ props?: Record<string, any>;
15
+ }) => void;
16
+
17
+ export const AnalyticsContext = createContext<AnalyticsFunction | undefined>(
18
+ undefined
19
+ );
20
+
9
21
  const cache = createIntlCache();
10
22
 
11
23
  const intlFactory = (locale: string) =>
@@ -22,11 +34,13 @@ export const IntlContext = createContext(intlFactory('en'));
22
34
  export interface ContextProviderProps {
23
35
  children: React.ReactNode;
24
36
  locale: string;
37
+ analyticsFunction?: AnalyticsFunction;
25
38
  }
26
39
 
27
40
  export const ContextProvider: React.FC<ContextProviderProps> = ({
28
41
  children,
29
42
  locale,
43
+ analyticsFunction,
30
44
  }: ContextProviderProps): JSX.Element => {
31
45
  const fetcher = async (resource: any, init: any) => {
32
46
  const response = await strapiClient.get(`${resource}`, {
@@ -57,7 +71,9 @@ export const ContextProvider: React.FC<ContextProviderProps> = ({
57
71
  >
58
72
  <Global styles={{ GLOBAL_STYLE }} />
59
73
  <IntlContext.Provider value={intlFactory(locale)}>
60
- {children}
74
+ <AnalyticsContext.Provider value={analyticsFunction}>
75
+ {children}
76
+ </AnalyticsContext.Provider>
61
77
  </IntlContext.Provider>
62
78
  </SWRConfig>
63
79
  </>
@@ -295,6 +295,7 @@ export const EventCard = ({ event }: EventCardProps): JSX.Element => {
295
295
  link={event.button}
296
296
  rightIcon={<CaretRight size="10" />}
297
297
  width="full"
298
+ component="EventCard"
298
299
  />
299
300
  </Flex>
300
301
  )}
@@ -42,6 +42,7 @@ import Locale from '../../models/Locale';
42
42
  import { ContextProvider } from '../ContextProvider';
43
43
  import Timeline from '../../slices/Timeline';
44
44
  import Events from '../../slices/Events';
45
+ import { AnalyticsFunction } from '../ContextProvider/ContextProvider';
45
46
 
46
47
  export interface CustomSliceProps {
47
48
  slice: any;
@@ -55,6 +56,7 @@ export interface SliceRendererProps {
55
56
  customerStories: IStrapiData<StrapiCustomerStory>[];
56
57
  locale?: Locale;
57
58
  CustomSlice?: ({ slice, id }: CustomSliceProps) => JSX.Element;
59
+ analyticsFunction?: AnalyticsFunction;
58
60
  }
59
61
 
60
62
  export const SliceRenderer = ({
@@ -64,8 +66,9 @@ export const SliceRenderer = ({
64
66
  customerStories,
65
67
  locale = 'en',
66
68
  CustomSlice,
69
+ analyticsFunction,
67
70
  }: SliceRendererProps): JSX.Element => (
68
- <ContextProvider locale={locale}>
71
+ <ContextProvider locale={locale} analyticsFunction={analyticsFunction}>
69
72
  {slices.map((slice: any) => {
70
73
  switch (slice.__component) {
71
74
  case 'sections.hero':
@@ -1,8 +1,9 @@
1
1
  import React from 'react';
2
- import { render, screen } from '../../test/testUtils';
2
+ import { render, screen, fireEvent } from '../../test/testUtils';
3
3
  import StrapiLinkButton from '.';
4
4
  import { detectAdBlockSpy } from '../../../__mocks__/adblock-detect-react';
5
5
  import { StrapiLinkButtonProps } from './StrapiLinkButton';
6
+ import { AnalyticsContext } from '../ContextProvider/ContextProvider';
6
7
 
7
8
  const defaultProps: StrapiLinkButtonProps = {
8
9
  link: {
@@ -12,25 +13,30 @@ const defaultProps: StrapiLinkButtonProps = {
12
13
  },
13
14
  };
14
15
 
16
+ const mockAnalyticsFunction = jest.fn();
17
+
15
18
  const setup = (props = {}) => {
16
19
  const combinedProps = { ...defaultProps, ...props };
17
- render(<StrapiLinkButton {...combinedProps} />);
20
+ render(
21
+ <AnalyticsContext.Provider value={mockAnalyticsFunction}>
22
+ <StrapiLinkButton {...combinedProps} />
23
+ </AnalyticsContext.Provider>
24
+ );
18
25
  };
19
26
 
20
27
  describe('The StrapiLinkButton component', () => {
21
28
  afterEach(() => {
22
29
  detectAdBlockSpy.mockRestore();
30
+ mockAnalyticsFunction.mockClear();
23
31
  });
24
32
 
25
33
  it('displays a link', () => {
26
34
  setup();
27
-
28
35
  expect(screen.getByRole('link')).toBeInTheDocument();
29
36
  });
30
37
 
31
38
  it('displays the button as a link if an url is passed in the link', () => {
32
39
  setup();
33
-
34
40
  expect(screen.getByRole('link')).toHaveAttribute(
35
41
  'href',
36
42
  defaultProps.link.url
@@ -39,7 +45,6 @@ describe('The StrapiLinkButton component', () => {
39
45
 
40
46
  it('displays the custom HubSpot launcher if intercomLauncher is true in the link', () => {
41
47
  setup({ link: { id: 1, text: 'Text', intercomLauncher: true } });
42
-
43
48
  expect(screen.getByRole('button')).not.toHaveAttribute(
44
49
  'href',
45
50
  defaultProps.link.url
@@ -48,12 +53,67 @@ describe('The StrapiLinkButton component', () => {
48
53
 
49
54
  it('opens an email to hello@tree.ly if an ad blocker is active and intercomLauncher is true', () => {
50
55
  detectAdBlockSpy.mockReturnValue(true);
51
-
52
56
  setup({ link: { id: 1, text: 'Text', intercomLauncher: true } });
53
-
54
57
  expect(screen.getByRole('link')).toHaveAttribute(
55
58
  'href',
56
59
  'mailto:hello@tree.ly'
57
60
  );
58
61
  });
62
+
63
+ it('calls analytics function when clicking a regular link', () => {
64
+ setup();
65
+ fireEvent.click(screen.getByRole('link'));
66
+ expect(mockAnalyticsFunction).toHaveBeenCalledWith({
67
+ type: 'track',
68
+ props: {
69
+ action: 'click',
70
+ component: 'StrapiLinkButton',
71
+ buttonText: 'Text',
72
+ buttonUrl: '/url',
73
+ },
74
+ });
75
+ });
76
+
77
+ it('calls analytics function when clicking an intercom launcher', () => {
78
+ setup({ link: { id: 1, text: 'Text', intercomLauncher: true } });
79
+ fireEvent.click(screen.getByRole('button'));
80
+ expect(mockAnalyticsFunction).toHaveBeenCalledWith({
81
+ type: 'track',
82
+ props: {
83
+ action: 'click',
84
+ component: 'StrapiLinkButton',
85
+ buttonText: 'Text',
86
+ buttonUrl: '/',
87
+ },
88
+ });
89
+ });
90
+
91
+ it('calls analytics function when clicking a mailto link', () => {
92
+ detectAdBlockSpy.mockReturnValue(true);
93
+ setup({ link: { id: 1, text: 'Text', intercomLauncher: true } });
94
+ fireEvent.click(screen.getByRole('link'));
95
+ expect(mockAnalyticsFunction).toHaveBeenCalledWith({
96
+ type: 'track',
97
+ props: {
98
+ action: 'click',
99
+ component: 'StrapiLinkButton',
100
+ buttonText: 'Text',
101
+ buttonUrl: 'mailto:hello@tree.ly',
102
+ },
103
+ });
104
+ });
105
+
106
+ it('uses custom component name in analytics if provided', () => {
107
+ setup({ component: 'CustomComponent' });
108
+ fireEvent.click(screen.getByRole('link'));
109
+ expect(mockAnalyticsFunction).toHaveBeenCalledWith({
110
+ type: 'track',
111
+ props: {
112
+ action: 'click',
113
+ component: 'CustomComponent',
114
+ buttonText: 'Text',
115
+ buttonUrl: '/url',
116
+ },
117
+ });
118
+ });
59
119
  });
@@ -1,10 +1,11 @@
1
- import React from 'react';
1
+ import React, { useContext } from 'react';
2
2
  import { Button } from 'boemly';
3
3
  import Link from 'next/link';
4
4
  import { useDetectAdBlock } from 'adblock-detect-react';
5
5
  import StrapiLink from '../../models/strapi/StrapiLink';
6
6
  import strapiLinkUrl from '../../utils/strapiLinkUrl';
7
7
  import openHubSpotChat from '../../utils/openHubSpotChat';
8
+ import { AnalyticsContext } from '../ContextProvider/ContextProvider';
8
9
 
9
10
  export interface StrapiLinkButtonProps {
10
11
  link: StrapiLink;
@@ -21,32 +22,68 @@ export interface StrapiLinkButtonProps {
21
22
  my?: any;
22
23
  background?: string;
23
24
  width?: string;
25
+ component?: string;
24
26
  }
25
27
 
26
28
  export const StrapiLinkButton: React.FC<StrapiLinkButtonProps> = ({
27
29
  link,
30
+ component = 'StrapiLinkButton',
28
31
  ...buttonProps
29
32
  }: StrapiLinkButtonProps) => {
30
33
  const adBlockDetected = useDetectAdBlock();
34
+ const analyticsFunction = useContext(AnalyticsContext);
35
+
36
+ const handleClick = () => {
37
+ const buttonUrl =
38
+ link.intercomLauncher && adBlockDetected
39
+ ? 'mailto:hello@tree.ly'
40
+ : strapiLinkUrl(link);
41
+
42
+ analyticsFunction?.({
43
+ type: 'track',
44
+ props: {
45
+ action: 'click',
46
+ component,
47
+ buttonText: link.text,
48
+ buttonUrl,
49
+ },
50
+ });
51
+ };
31
52
 
32
53
  if (link.intercomLauncher) {
33
54
  if (adBlockDetected) {
34
55
  return (
35
- <Button {...buttonProps} as={Link} href="mailto:hello@tree.ly">
56
+ <Button
57
+ {...buttonProps}
58
+ as={Link}
59
+ href="mailto:hello@tree.ly"
60
+ onClick={handleClick}
61
+ >
36
62
  {link.text}
37
63
  </Button>
38
64
  );
39
65
  }
40
66
 
41
67
  return (
42
- <Button {...buttonProps} onClick={openHubSpotChat}>
68
+ <Button
69
+ {...buttonProps}
70
+ onClick={() => {
71
+ handleClick();
72
+ openHubSpotChat();
73
+ }}
74
+ >
43
75
  {link.text}
44
76
  </Button>
45
77
  );
46
78
  }
47
79
 
48
80
  return (
49
- <Button {...buttonProps} as={Link} href={strapiLinkUrl(link)}>
81
+ <Button
82
+ {...buttonProps}
83
+ as={Link}
84
+ href={strapiLinkUrl(link)}
85
+ onClick={handleClick}
86
+ >
50
87
  {link.text}
51
88
  </Button>
52
89
  );
@@ -65,7 +65,13 @@ export const Contact: React.FC<ContactProps> = ({
65
65
  <></>
66
66
  )}
67
67
  {button ? (
68
- <StrapiLinkButton mt="6" link={button} size="md" variant="outline" />
68
+ <StrapiLinkButton
69
+ mt="6"
70
+ link={button}
71
+ size="md"
72
+ variant="outline"
73
+ component="Contact"
74
+ />
69
75
  ) : (
70
76
  <></>
71
77
  )}
@@ -304,6 +304,7 @@ const SmallCheckout = ({
304
304
  ...button,
305
305
  }}
306
306
  variant="outline"
307
+ component="SmallCheckout"
307
308
  />
308
309
  )}
309
310
  </Flex>
@@ -111,6 +111,7 @@ export const BlogCards: React.FC<BlogCardsProps> = ({
111
111
  size="lg"
112
112
  variant="outline"
113
113
  rightIcon={<CaretRight color={gray700} />}
114
+ component="BlogCards"
114
115
  />
115
116
  </Box>
116
117
  </Flex>
@@ -196,6 +197,7 @@ export const BlogCards: React.FC<BlogCardsProps> = ({
196
197
  size="lg"
197
198
  variant="outline"
198
199
  rightIcon={<CaretRight color={gray700} />}
200
+ component="BlogCards"
199
201
  />
200
202
  </Box>
201
203
  </>
@@ -212,6 +212,7 @@ export const Comparison: React.FC<ComparisonProps> = ({
212
212
  size="md"
213
213
  variant="outline"
214
214
  rightIcon={<CaretRight size={16} weight="bold" />}
215
+ component="Comparison"
215
216
  />
216
217
  )}
217
218
  </Flex>
@@ -380,6 +380,7 @@ export const Cta: React.FC<CtaProps> = ({ slice }: CtaProps) => {
380
380
  link={button.button}
381
381
  size="md"
382
382
  variant={button.variant}
383
+ component="Cta"
383
384
  />
384
385
  ))}
385
386
  </Flex>
@@ -12,7 +12,7 @@ export interface CtaOnlyProps {
12
12
  export const CtaOnly: React.FC<CtaOnlyProps> = ({ slice }: CtaOnlyProps) => (
13
13
  <Wrapper>
14
14
  <Box position="absolute" top="-28" transform="translateY(50%)">
15
- <StrapiLinkButton size="md" link={slice.button} />
15
+ <StrapiLinkButton size="md" link={slice.button} component="CtaOnly" />
16
16
  </Box>
17
17
  </Wrapper>
18
18
  );
@@ -133,6 +133,7 @@ export const Facts: React.FC<FactsProps> = ({ slice }: FactsProps) => (
133
133
  link={slice.button}
134
134
  size="md"
135
135
  variant={slice.variant === 'green' ? 'outline' : 'solid'}
136
+ component="Facts"
136
137
  />
137
138
  </>
138
139
  )}
@@ -100,6 +100,7 @@ export const Hero = ({ slice }: HeroProps): JSX.Element => (
100
100
  mt="10"
101
101
  size="xl"
102
102
  link={slice.button}
103
+ component="Hero"
103
104
  />
104
105
  )}
105
106
  {slice.additionalButtons.map((button) => (
@@ -109,6 +110,7 @@ export const Hero = ({ slice }: HeroProps): JSX.Element => (
109
110
  size="xl"
110
111
  variant={button.variant}
111
112
  link={button.button}
113
+ component="Hero"
112
114
  />
113
115
  ))}
114
116
  </Flex>
@@ -109,6 +109,7 @@ export const IconGrid = ({ slice }: IconGridProps): JSX.Element => {
109
109
  size="md"
110
110
  variant="outline"
111
111
  link={iconWithTextAndButton.button}
112
+ component="IconGrid"
112
113
  />
113
114
  </Box>
114
115
  )}
@@ -79,6 +79,7 @@ export const ImageGrid: React.FC<ImageGridProps> = ({
79
79
  link={link}
80
80
  size="sm"
81
81
  variant="outline"
82
+ component="ImageGrid"
82
83
  />
83
84
  ))}
84
85
  </Flex>
@@ -140,6 +140,7 @@ export const ImageTextSequence: React.FC<ImageTextSequenceProps> = ({
140
140
  size="sm"
141
141
  variant="outline"
142
142
  rightIcon={<CaretRight size="10" color={gray700} />}
143
+ component="ImageTextSequence"
143
144
  />
144
145
  )}
145
146
  </Box>
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { useContext } from 'react';
2
2
  import {
3
3
  DefaultSectionContainer,
4
4
  DefaultSectionHeader,
@@ -18,6 +18,7 @@ import StrapiPortfolioCard from '../../models/strapi/StrapiPortfolioCard';
18
18
  import StrapiDefaultHeader from '../../models/strapi/StrapiDefaultHeader';
19
19
  import StrapiLink from '../../models/strapi/StrapiLink';
20
20
  import StrapiLinkButton from '../../components/StrapiLinkButton';
21
+ import { AnalyticsContext } from '../../components/ContextProvider/ContextProvider';
21
22
 
22
23
  interface LeftTextRightCardSlice extends StrapiDefaultHeader {
23
24
  checkMarkLabels?: {
@@ -35,6 +36,26 @@ export const LeftTextRightCard: React.FC<LeftTextRightCardProps> = ({
35
36
  slice,
36
37
  }: LeftTextRightCardProps) => {
37
38
  const { push } = useRouter();
39
+ const analyticsFunction = useContext(AnalyticsContext);
40
+
41
+ const handleCardButtonClick = () => {
42
+ if (slice.card?.button) {
43
+ if (analyticsFunction) {
44
+ analyticsFunction({
45
+ type: 'track',
46
+ props: {
47
+ action: 'click',
48
+ component: 'LeftTextRightCard',
49
+ buttonText: slice.card?.button?.text,
50
+ buttonUrl: strapiLinkUrl(slice.card?.button),
51
+ cardTitle: slice.card?.title,
52
+ },
53
+ });
54
+ }
55
+
56
+ push(strapiLinkUrl(slice.card?.button));
57
+ }
58
+ };
38
59
 
39
60
  return (
40
61
  <DefaultSectionContainer title={slice.title}>
@@ -72,6 +93,7 @@ export const LeftTextRightCard: React.FC<LeftTextRightCardProps> = ({
72
93
  colorScheme="white"
73
94
  variant="outline"
74
95
  rightIcon={<ArrowRight />}
96
+ component="LeftTextRightCard"
75
97
  />
76
98
  )}
77
99
  </GridItem>
@@ -86,7 +108,7 @@ export const LeftTextRightCard: React.FC<LeftTextRightCardProps> = ({
86
108
  button={
87
109
  slice.card.button && {
88
110
  text: slice.card.button.text,
89
- onClick: () => push(strapiLinkUrl(slice.card?.button)),
111
+ onClick: handleCardButtonClick,
90
112
  }
91
113
  }
92
114
  facts={slice.card.facts}
@@ -53,6 +53,7 @@ export const LogoGridWithText: React.FC<LogoGridWithTextProps> = ({
53
53
  variant="outline"
54
54
  mt="6"
55
55
  rightIcon={<ArrowRight />}
56
+ component="LogoGridWithText"
56
57
  />
57
58
  )}
58
59
  </Box>
@@ -54,12 +54,17 @@ export const MapHero: React.FC<MapHeroProps> = ({ slice }: MapHeroProps) => {
54
54
  />
55
55
  {slice.buttons && slice.buttons.length > 0 && (
56
56
  <Flex mt="10" flexDir="row" gap="5">
57
- <StrapiLinkButton link={slice.buttons[0]} size="xl" />
57
+ <StrapiLinkButton
58
+ link={slice.buttons[0]}
59
+ size="xl"
60
+ component="MapHero"
61
+ />
58
62
  {slice.buttons.length === 2 && (
59
63
  <StrapiLinkButton
60
64
  link={slice.buttons[1]}
61
65
  variant="outline"
62
66
  size="xl"
67
+ component="MapHero"
63
68
  />
64
69
  )}
65
70
  </Flex>
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { useContext } from 'react';
2
2
  import {
3
3
  Box,
4
4
  Heading,
@@ -19,6 +19,7 @@ import StrapiHeroCard from '../../models/strapi/StrapiHeroCard';
19
19
  import strapiMediaUrl from '../../utils/strapiMediaUrl';
20
20
  import StrapiLinkButton from '../../components/StrapiLinkButton';
21
21
  import convertToKebabCase from '../../utils/convertToKebabCase';
22
+ import { AnalyticsContext } from '../../components/ContextProvider/ContextProvider';
22
23
 
23
24
  const VARIANTS = {
24
25
  gray: {
@@ -63,6 +64,23 @@ export interface QAndAProps {
63
64
 
64
65
  export const QAndA: React.FC<QAndAProps> = ({ slice }: QAndAProps) => {
65
66
  const { push } = useRouter();
67
+ const analyticsFunction = useContext(AnalyticsContext);
68
+
69
+ const handleHeroButtonClick = () => {
70
+ if (slice.hero?.button) {
71
+ analyticsFunction?.({
72
+ type: 'track',
73
+ props: {
74
+ action: 'click',
75
+ component: 'QAndA',
76
+ buttonText: slice.hero.button.text,
77
+ buttonUrl: strapiLinkUrl(slice.hero.button),
78
+ section: 'hero',
79
+ },
80
+ });
81
+ push(strapiLinkUrl(slice.hero.button));
82
+ }
83
+ };
66
84
 
67
85
  const variant = VARIANTS[slice.variant ?? 'green'];
68
86
 
@@ -120,6 +138,7 @@ export const QAndA: React.FC<QAndAProps> = ({ slice }: QAndAProps) => {
120
138
  background="white"
121
139
  rightIcon={<ArrowRight />}
122
140
  link={slice.button}
141
+ component="QAndA"
123
142
  />
124
143
  </Flex>
125
144
  </Box>
@@ -137,7 +156,7 @@ export const QAndA: React.FC<QAndAProps> = ({ slice }: QAndAProps) => {
137
156
  link={
138
157
  slice.hero.button && {
139
158
  text: slice.hero.button.text,
140
- onClick: () => push(strapiLinkUrl(slice.hero?.button)),
159
+ onClick: handleHeroButtonClick,
141
160
  }
142
161
  }
143
162
  image={
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { useContext } from 'react';
2
2
  import Image from 'next/image';
3
3
  import {
4
4
  Box,
@@ -17,6 +17,7 @@ import strapiLinkUrl from '../../utils/strapiLinkUrl';
17
17
  import StrapiImage from '../../models/strapi/StrapiImage';
18
18
  import convertToKebabCase from '../../utils/convertToKebabCase';
19
19
  import { useRouter } from 'next/router';
20
+ import { AnalyticsContext } from '../../components/ContextProvider/ContextProvider';
20
21
 
21
22
  interface QuoteCardsSlice extends StrapiDefaultHeader {
22
23
  cards: StrapiQuoteCard[];
@@ -31,6 +32,23 @@ export const QuoteCards: React.FC<QuoteCardsProps> = ({
31
32
  slice,
32
33
  }: QuoteCardsProps) => {
33
34
  const { push } = useRouter();
35
+ const analyticsFunction = useContext(AnalyticsContext);
36
+
37
+ const handleHeroCardButtonClick = () => {
38
+ if (slice.hero?.button) {
39
+ analyticsFunction?.({
40
+ type: 'track',
41
+ props: {
42
+ action: 'click',
43
+ component: 'QuoteCards',
44
+ buttonText: slice.hero.button.text,
45
+ buttonUrl: strapiLinkUrl(slice.hero.button),
46
+ section: 'hero',
47
+ },
48
+ });
49
+ push(strapiLinkUrl(slice.hero.button));
50
+ }
51
+ };
34
52
 
35
53
  return (
36
54
  <>
@@ -120,7 +138,7 @@ export const QuoteCards: React.FC<QuoteCardsProps> = ({
120
138
  link={
121
139
  slice.hero.button && {
122
140
  text: slice.hero.button.text,
123
- onClick: () => push(strapiLinkUrl(slice.hero?.button)),
141
+ onClick: handleHeroCardButtonClick,
124
142
  }
125
143
  }
126
144
  image={
@@ -114,7 +114,12 @@ export const SmallHero: React.FC<SmallHeroProps> = ({
114
114
  }}
115
115
  />
116
116
  {slice.button && (
117
- <StrapiLinkButton link={slice.button} mt="6" size="lg" />
117
+ <StrapiLinkButton
118
+ link={slice.button}
119
+ mt="6"
120
+ size="lg"
121
+ component="SmallHero"
122
+ />
118
123
  )}
119
124
  </>
120
125
  </Wrapper>