gatsby-core-theme 30.0.55 → 30.0.56
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.
- package/CHANGELOG.md +14 -0
- package/package.json +3 -2
- package/src/components/atoms/button/operator-cta.js +6 -42
- package/src/components/atoms/operator-info-block/index.js +8 -8
- package/src/components/atoms/pretty-link/index.js +54 -0
- package/src/components/atoms/pretty-link/pretty-link.test.js +80 -0
- package/src/components/molecules/bonus/template-one/index.js +10 -15
- package/src/components/molecules/bonus/template-two/index.js +9 -15
- package/src/components/molecules/bonus-box/template-one/index.js +11 -7
- package/src/components/molecules/bonus-box/template-three/index.js +10 -8
- package/src/components/molecules/bonus-box/template-two/index.js +11 -8
- package/src/components/molecules/main/index.js +2 -1
- package/src/components/molecules/toplist/default-row/index.js +10 -13
- package/src/components/pages/body/index.js +5 -19
- package/src/helpers/tracker.mjs +52 -10
- package/src/helpers/tracker.test.js +33 -16
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## [30.0.56](https://git.ilcd.rocks/team-floyd/themes/gatsby-themes/compare/v30.0.55...v30.0.56) (2024-01-18)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* added new component and new tracking api params ([a1aa8d6](https://git.ilcd.rocks/team-floyd/themes/gatsby-themes/commit/a1aa8d6cae7c3512d96674576adfc805e11a36bf))
|
|
7
|
+
* added new component and new tracking api params ([6a20d08](https://git.ilcd.rocks/team-floyd/themes/gatsby-themes/commit/6a20d08a9554646d57eb3c52f222b82d6cae6b40))
|
|
8
|
+
* added new component and new tracking api params ([fcf7428](https://git.ilcd.rocks/team-floyd/themes/gatsby-themes/commit/fcf74283c044032893adca4e0596a82aae62d376))
|
|
9
|
+
* added new params ([c1d76c5](https://git.ilcd.rocks/team-floyd/themes/gatsby-themes/commit/c1d76c5b5981c9bd1e10e7d5a35c91c2220bd646))
|
|
10
|
+
* added new params ([6841ac3](https://git.ilcd.rocks/team-floyd/themes/gatsby-themes/commit/6841ac361eff51f6e1ba4b08bafed762da4eb27c))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
* Merge branch 'tm-3989-tracking-api-params' into 'master' ([7077dff](https://git.ilcd.rocks/team-floyd/themes/gatsby-themes/commit/7077dffcfb0632e608f99608b555e6d2c5f3ef5e))
|
|
14
|
+
|
|
1
15
|
## [30.0.55](https://git.ilcd.rocks/team-floyd/themes/gatsby-themes/compare/v30.0.54...v30.0.55) (2024-01-17)
|
|
2
16
|
|
|
3
17
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gatsby-core-theme",
|
|
3
|
-
"version": "30.0.
|
|
3
|
+
"version": "30.0.56",
|
|
4
4
|
"description": "Gatsby Theme NPM Package",
|
|
5
5
|
"author": "",
|
|
6
6
|
"license": "ISC",
|
|
@@ -52,7 +52,8 @@
|
|
|
52
52
|
"react-google-recaptcha": "^2.1.0",
|
|
53
53
|
"react-lazyload": "^3.2.0",
|
|
54
54
|
"react-masonry-css": "^1.0.16",
|
|
55
|
-
"sass": "^1.63.6"
|
|
55
|
+
"sass": "^1.63.6",
|
|
56
|
+
"uuid": "^9.0.1"
|
|
56
57
|
},
|
|
57
58
|
"devDependencies": {
|
|
58
59
|
"@babel/core": "^7.22.5",
|
|
@@ -4,6 +4,7 @@ import PropTypes from 'prop-types';
|
|
|
4
4
|
import { Context } from '~context/MainProvider';
|
|
5
5
|
import { prettyTracker, translate } from '~helpers/getters';
|
|
6
6
|
import { setCookie } from '~helpers/cookies';
|
|
7
|
+
import { getTrackingAPIParams } from '~helpers/tracker';
|
|
7
8
|
|
|
8
9
|
import styles from './button.module.scss';
|
|
9
10
|
|
|
@@ -28,51 +29,14 @@ const OperatorCtaButton = ({
|
|
|
28
29
|
const status = operator?.status || '';
|
|
29
30
|
const trackerType = tracker?.toLowerCase()?.replace(' ', '_');
|
|
30
31
|
const url = typeof window !== 'undefined' ? window.location.href : '';
|
|
31
|
-
const urlParams = {};
|
|
32
|
-
|
|
33
|
-
function deparam(paramStr) {
|
|
34
|
-
const paramArr = paramStr.split('&');
|
|
35
|
-
const paramObj = {};
|
|
36
|
-
paramArr.forEach((e) => {
|
|
37
|
-
const param = e.split('=');
|
|
38
|
-
paramObj[param[0]] = decodeURIComponent(param[1]);
|
|
39
|
-
});
|
|
40
|
-
return paramObj;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
if (process.env.IS_TRACKING_SSR === 'true') {
|
|
44
|
-
if (pageTemplate) {
|
|
45
|
-
urlParams.page_type = pageTemplate;
|
|
46
|
-
}
|
|
47
|
-
if (module) {
|
|
48
|
-
urlParams.module = module;
|
|
49
|
-
}
|
|
50
|
-
if (tracker !== 'main') {
|
|
51
|
-
urlParams.tracker_name = tracker;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (url && url.split('?').length === 2) {
|
|
55
|
-
// eslint-disable-next-line prefer-destructuring
|
|
56
|
-
urlParams.request_url = url.split('?')[0];
|
|
57
|
-
const extraData = deparam(url.split('?')[1]);
|
|
58
|
-
if (extraData.fbclid) {
|
|
59
|
-
urlParams.facebook_click_id = extraData.fbclid;
|
|
60
|
-
}
|
|
61
|
-
if (extraData.msclkid) {
|
|
62
|
-
urlParams.microsoft_click_id = extraData.msclkid;
|
|
63
|
-
}
|
|
64
|
-
if (extraData.gclid) {
|
|
65
|
-
urlParams.google_click_id = extraData.gclid;
|
|
66
|
-
}
|
|
67
|
-
} else if (url) {
|
|
68
|
-
urlParams.request_url = url;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
32
|
const prettyLink = `${prettyTracker(operator, trackerType, false, pageTemplate)}`;
|
|
73
33
|
|
|
74
34
|
const onCTAClick = () => {
|
|
75
|
-
process.env.IS_TRACKING_SSR &&
|
|
35
|
+
process.env.IS_TRACKING_SSR &&
|
|
36
|
+
setCookie(
|
|
37
|
+
'affObject',
|
|
38
|
+
JSON.stringify(getTrackingAPIParams(pageTemplate, module, tracker, 'cta', url))
|
|
39
|
+
);
|
|
76
40
|
};
|
|
77
41
|
|
|
78
42
|
const translateBtn =
|
|
@@ -2,15 +2,13 @@
|
|
|
2
2
|
/* eslint-disable no-nested-ternary */
|
|
3
3
|
import React from 'react';
|
|
4
4
|
import PropTypes from 'prop-types';
|
|
5
|
-
|
|
6
|
-
import { prettyTracker } from '~helpers/getters';
|
|
5
|
+
import PrettyLink from '~atoms/pretty-link';
|
|
7
6
|
import styles from './operator-info-block.module.scss';
|
|
8
7
|
import keygen from '~helpers/keygen';
|
|
9
8
|
|
|
10
9
|
const OperatorInfoBlock = ({ page }) => {
|
|
11
10
|
const { relation } = page;
|
|
12
11
|
const status = relation?.status;
|
|
13
|
-
const prettyLink = prettyTracker(relation, 'main', false, page.template);
|
|
14
12
|
if (status !== 'active') return null;
|
|
15
13
|
const infos = [
|
|
16
14
|
{ field_name: 'url', field_label: 'URL' },
|
|
@@ -29,14 +27,16 @@ const OperatorInfoBlock = ({ page }) => {
|
|
|
29
27
|
<p className={styles.label || ''}>{item.field_label}</p>
|
|
30
28
|
<div className={styles.value || ''}>
|
|
31
29
|
{item.field_name === 'url' ? (
|
|
32
|
-
<
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
<PrettyLink
|
|
31
|
+
operator={item}
|
|
32
|
+
pageTemplate={page.template}
|
|
33
|
+
module="operator_info_block"
|
|
34
|
+
tracker="main"
|
|
35
|
+
clickedElement="operator_name"
|
|
35
36
|
className="operator-info-block-gtm"
|
|
36
|
-
rel="noindex nofollow noreferrer sponsored"
|
|
37
37
|
>
|
|
38
38
|
{relation[item.field_name]}
|
|
39
|
-
</
|
|
39
|
+
</PrettyLink>
|
|
40
40
|
) : item.field_name === 'support_types' ? (
|
|
41
41
|
relation.support_types.toLowerCase().includes('live chat') ? (
|
|
42
42
|
<p>Yes</p>
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import { prettyTracker } from '~helpers/getters';
|
|
4
|
+
import { setCookie } from '~helpers/cookies';
|
|
5
|
+
import { getTrackingAPIParams } from '~helpers/tracker';
|
|
6
|
+
|
|
7
|
+
const PrettyLink = ({
|
|
8
|
+
operator,
|
|
9
|
+
pageTemplate,
|
|
10
|
+
module,
|
|
11
|
+
tracker,
|
|
12
|
+
clickedElement,
|
|
13
|
+
className,
|
|
14
|
+
children,
|
|
15
|
+
}) => {
|
|
16
|
+
const prettyLink = prettyTracker(operator, tracker, false, pageTemplate);
|
|
17
|
+
const url = typeof window !== 'undefined' ? window.location.href : '';
|
|
18
|
+
const onCTAClick = () => {
|
|
19
|
+
// eslint-disable-next-line no-unused-expressions
|
|
20
|
+
process.env.IS_TRACKING_SSR &&
|
|
21
|
+
setCookie(
|
|
22
|
+
'affObject',
|
|
23
|
+
JSON.stringify(getTrackingAPIParams(pageTemplate, module, tracker, clickedElement, url))
|
|
24
|
+
);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<a
|
|
29
|
+
href={prettyLink || '#'}
|
|
30
|
+
title={operator.name}
|
|
31
|
+
className={className}
|
|
32
|
+
target="_blank"
|
|
33
|
+
rel="noreferrer sponsored nofollow"
|
|
34
|
+
aria-label={`${operator.name} Link`}
|
|
35
|
+
onClick={onCTAClick}
|
|
36
|
+
>
|
|
37
|
+
{children}
|
|
38
|
+
</a>
|
|
39
|
+
);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
PrettyLink.propTypes = {
|
|
43
|
+
operator: PropTypes.shape({
|
|
44
|
+
name: PropTypes.string,
|
|
45
|
+
}),
|
|
46
|
+
pageTemplate: PropTypes.string,
|
|
47
|
+
module: PropTypes.string,
|
|
48
|
+
tracker: PropTypes.string,
|
|
49
|
+
clickedElement: PropTypes.string,
|
|
50
|
+
className: PropTypes.string,
|
|
51
|
+
children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node, PropTypes.any]),
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export default PrettyLink;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/* eslint-disable no-lone-blocks */
|
|
2
|
+
/* eslint-disable no-unused-expressions */
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { render, cleanup, fireEvent } from '@testing-library/react';
|
|
5
|
+
import '@testing-library/jest-dom/extend-expect';
|
|
6
|
+
|
|
7
|
+
import PrettyLink from '.';
|
|
8
|
+
|
|
9
|
+
const data = (activeStatus = 'active') => ({
|
|
10
|
+
operator: {
|
|
11
|
+
status: activeStatus,
|
|
12
|
+
links: {
|
|
13
|
+
main: 'https://www.google.com',
|
|
14
|
+
},
|
|
15
|
+
short_name: 'operator',
|
|
16
|
+
},
|
|
17
|
+
pageTemplate: 'default',
|
|
18
|
+
tracker: 'main',
|
|
19
|
+
children: <h1>Test children</h1>,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
describe('PrettyLink Component', () => {
|
|
23
|
+
test('PrettyLink children and link', () => {
|
|
24
|
+
const { getByText, container } = render(<PrettyLink {...data()} />);
|
|
25
|
+
expect(getByText('Test children')).toBeTruthy();
|
|
26
|
+
expect(container.querySelector('a').getAttribute('href')).toEqual('/no/visit/operator');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test('Affiliate object in cookie', () => {
|
|
30
|
+
window = Object.create(window);
|
|
31
|
+
const url = 'http://test.com/?fbclid=param1&msclkid=param2&gclid=param3';
|
|
32
|
+
Object.defineProperty(window, 'location', {
|
|
33
|
+
value: {
|
|
34
|
+
href: url,
|
|
35
|
+
},
|
|
36
|
+
writable: true, // possibility to override
|
|
37
|
+
});
|
|
38
|
+
const { container } = render(
|
|
39
|
+
<PrettyLink
|
|
40
|
+
{...data()}
|
|
41
|
+
pageTemplate="test"
|
|
42
|
+
module="test2"
|
|
43
|
+
tracker="testing"
|
|
44
|
+
clickedElement="cta"
|
|
45
|
+
/>
|
|
46
|
+
);
|
|
47
|
+
const button = container.querySelector('a');
|
|
48
|
+
fireEvent.click(button);
|
|
49
|
+
const affObject = JSON.parse(document.cookie.split('=')[1]);
|
|
50
|
+
expect(affObject.page_type).toEqual('test');
|
|
51
|
+
expect(affObject.module).toEqual('test2');
|
|
52
|
+
expect(affObject.request_url).toEqual('http://test.com/');
|
|
53
|
+
expect(affObject.facebook_click_id).toEqual('param1');
|
|
54
|
+
expect(affObject.microsoft_click_id).toEqual('param2');
|
|
55
|
+
expect(affObject.google_click_id).toEqual('param3');
|
|
56
|
+
expect(affObject.tracker_name).toEqual('testing');
|
|
57
|
+
expect(affObject.clicked_element).toEqual('cta');
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test('Default Affiliate object in cookie', () => {
|
|
61
|
+
window = Object.create(window);
|
|
62
|
+
const url = 'http://testdomain.com/';
|
|
63
|
+
Object.defineProperty(window, 'location', {
|
|
64
|
+
value: {
|
|
65
|
+
href: url,
|
|
66
|
+
},
|
|
67
|
+
writable: true, // possibility to override
|
|
68
|
+
});
|
|
69
|
+
const { container } = render(<PrettyLink {...data()} />);
|
|
70
|
+
const button = container.querySelector('a');
|
|
71
|
+
fireEvent.click(button);
|
|
72
|
+
const affObject = JSON.parse(document.cookie.split('=')[1]);
|
|
73
|
+
expect(affObject.page_type).toEqual('default');
|
|
74
|
+
expect(affObject.request_url).toEqual('http://testdomain.com/');
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
afterEach(() => {
|
|
79
|
+
cleanup();
|
|
80
|
+
});
|
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import PropTypes from 'prop-types';
|
|
4
4
|
import { FaArrowRight } from '@react-icons/all-files/fa/FaArrowRight';
|
|
5
|
-
import {
|
|
5
|
+
import { imagePrettyUrl } from '~helpers/getters';
|
|
6
6
|
import LazyImage from '~hooks/lazy-image';
|
|
7
7
|
import BonusBox from '~molecules/bonus-box/template-four';
|
|
8
8
|
import OperatorCta from '~atoms/button/operator-cta';
|
|
9
9
|
import Rating from '~molecules/star-rating/one-star';
|
|
10
10
|
import Tnc from '~molecules/tnc';
|
|
11
|
+
import PrettyLink from '~atoms/pretty-link';
|
|
11
12
|
import styles from './bonus.module.scss';
|
|
12
13
|
|
|
13
14
|
export default function Bonus({
|
|
@@ -19,12 +20,6 @@ export default function Bonus({
|
|
|
19
20
|
tncEnable = true,
|
|
20
21
|
tncFixed = false,
|
|
21
22
|
}) {
|
|
22
|
-
const prettyLink = prettyTracker(
|
|
23
|
-
operator,
|
|
24
|
-
module?.tracking_link_name || 'main',
|
|
25
|
-
false,
|
|
26
|
-
pageTemplate
|
|
27
|
-
);
|
|
28
23
|
const { standardised_logo_url, logo_url, bonus, name } = operator || {};
|
|
29
24
|
const logo = standardised_logo_url || logo_url;
|
|
30
25
|
|
|
@@ -38,22 +33,22 @@ export default function Bonus({
|
|
|
38
33
|
>
|
|
39
34
|
<div className={styles.container}>
|
|
40
35
|
<div>
|
|
41
|
-
<
|
|
42
|
-
|
|
36
|
+
<PrettyLink
|
|
37
|
+
operator={operator}
|
|
38
|
+
pageTemplate={pageTemplate}
|
|
39
|
+
module={module.name}
|
|
40
|
+
tracker={module?.tracking_link_name || 'main'}
|
|
41
|
+
clickedElement="oneliner"
|
|
43
42
|
className={`${styles.logo || ''} operator-banner-gtm logo-cta`}
|
|
44
|
-
title={operator?.name}
|
|
45
|
-
target="_blank"
|
|
46
|
-
rel="noreferrer sponsored"
|
|
47
|
-
aria-label={`${operator?.name} Link`}
|
|
48
43
|
>
|
|
49
44
|
<LazyImage alt={operator?.name} src={imagePrettyUrl(logo)} height={120} width={100} />
|
|
50
45
|
<div className={styles.details}>
|
|
51
46
|
{name && <span>{name}</span>}
|
|
52
47
|
{bonus?.rating && <Rating rating={bonus?.rating} showDecimal />}
|
|
53
48
|
</div>
|
|
54
|
-
</
|
|
49
|
+
</PrettyLink>
|
|
55
50
|
<div className={styles.bonus || ''}>
|
|
56
|
-
<BonusBox item={operator} tracker={module?.type || 'main'} />
|
|
51
|
+
<BonusBox item={operator} module="bonus" tracker={module?.type || 'main'} />
|
|
57
52
|
{tncEnable && !tncFixed && <Tnc hasCollapse={false} operator={operator} />}
|
|
58
53
|
</div>
|
|
59
54
|
</div>
|
|
@@ -3,13 +3,14 @@ import React, { useState, useEffect, useContext } from 'react';
|
|
|
3
3
|
import PropTypes from 'prop-types';
|
|
4
4
|
import { FaArrowRight } from '@react-icons/all-files/fa/FaArrowRight';
|
|
5
5
|
import { IoMdClose } from '@react-icons/all-files/io/IoMdClose';
|
|
6
|
-
import {
|
|
6
|
+
import { imagePrettyUrl, translate } from '~helpers/getters';
|
|
7
7
|
import LazyImage from '~hooks/lazy-image';
|
|
8
8
|
import isSticky from '~hooks/stickyOnScroll';
|
|
9
9
|
import BonusBox from '~molecules/bonus-box/template-four';
|
|
10
10
|
import OperatorCta from '~atoms/button/operator-cta';
|
|
11
11
|
import Rating from '~molecules/star-rating/one-star';
|
|
12
12
|
import Tnc from '~molecules/tnc';
|
|
13
|
+
import PrettyLink from '~atoms/pretty-link';
|
|
13
14
|
import { Context } from '~context/MainProvider';
|
|
14
15
|
import styles from './bonus.module.scss';
|
|
15
16
|
|
|
@@ -26,13 +27,6 @@ export default function TemplateOne({
|
|
|
26
27
|
showWelcomeText = true,
|
|
27
28
|
floating = false,
|
|
28
29
|
}) {
|
|
29
|
-
const prettyLink = prettyTracker(
|
|
30
|
-
operator,
|
|
31
|
-
module?.tracking_link_name || 'main',
|
|
32
|
-
false,
|
|
33
|
-
pageTemplate
|
|
34
|
-
);
|
|
35
|
-
|
|
36
30
|
const [show, setShow] = useState(showOnLoad);
|
|
37
31
|
const [closed, setClosed] = useState(false);
|
|
38
32
|
const { cookieAccepted, setBannerActive, translations } = useContext(Context) || {};
|
|
@@ -71,13 +65,13 @@ export default function TemplateOne({
|
|
|
71
65
|
>
|
|
72
66
|
<div className={styles.container}>
|
|
73
67
|
<div>
|
|
74
|
-
<
|
|
75
|
-
|
|
68
|
+
<PrettyLink
|
|
69
|
+
operator={operator}
|
|
70
|
+
pageTemplate={pageTemplate}
|
|
71
|
+
module={module.name}
|
|
72
|
+
tracker={module?.tracking_link_name || 'main'}
|
|
73
|
+
clickedElement="oneliner"
|
|
76
74
|
className={`${styles.logo || ''} operator-banner-gtm logo-cta`}
|
|
77
|
-
title={operator?.name}
|
|
78
|
-
target="_blank"
|
|
79
|
-
rel="noreferrer sponsored"
|
|
80
|
-
aria-label={`${operator?.name} Link`}
|
|
81
75
|
>
|
|
82
76
|
<LazyImage
|
|
83
77
|
alt={operator?.name}
|
|
@@ -90,7 +84,7 @@ export default function TemplateOne({
|
|
|
90
84
|
{name && <span>{name}</span>}
|
|
91
85
|
{bonus?.rating && <Rating rating={bonus?.rating} showDecimal />}
|
|
92
86
|
</div>
|
|
93
|
-
</
|
|
87
|
+
</PrettyLink>
|
|
94
88
|
<div className={styles.bonus || ''}>
|
|
95
89
|
{showWelcomeText && (
|
|
96
90
|
<p className={styles.welcomeBonus}>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
|
-
import {
|
|
3
|
+
import { getBonusData } from '~helpers/getters.mjs';
|
|
4
|
+
import PrettyLink from '~atoms/pretty-link';
|
|
4
5
|
import styles from './bonus-box.module.scss';
|
|
5
6
|
|
|
6
7
|
export default function BonusBox({
|
|
@@ -9,22 +10,24 @@ export default function BonusBox({
|
|
|
9
10
|
pageTemplate = null,
|
|
10
11
|
splitBy = '+',
|
|
11
12
|
feSeparator = '+',
|
|
13
|
+
module = 'bonus_box',
|
|
12
14
|
}) {
|
|
13
|
-
const prettyLink = prettyTracker(item, tracker, false, pageTemplate);
|
|
14
15
|
const data = getBonusData(item, tracker, splitBy);
|
|
15
16
|
|
|
16
17
|
return (
|
|
17
|
-
<
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
<PrettyLink
|
|
19
|
+
operator={item}
|
|
20
|
+
pageTemplate={pageTemplate}
|
|
21
|
+
module={module}
|
|
22
|
+
tracker={tracker}
|
|
23
|
+
clickedElement="oneliner"
|
|
21
24
|
className={`${styles.detailsBox} ${'bonus-box-gtm'}`}
|
|
22
25
|
>
|
|
23
26
|
{data?.mainLine && <span className={styles.firstPart}>{data.mainLine}</span>}
|
|
24
27
|
{data?.secondLine && (
|
|
25
28
|
<span className={styles.secondPart}>{`${feSeparator}${data.secondLine}`}</span>
|
|
26
29
|
)}
|
|
27
|
-
</
|
|
30
|
+
</PrettyLink>
|
|
28
31
|
);
|
|
29
32
|
}
|
|
30
33
|
|
|
@@ -34,4 +37,5 @@ BonusBox.propTypes = {
|
|
|
34
37
|
pageTemplate: PropTypes.string,
|
|
35
38
|
splitBy: PropTypes.string,
|
|
36
39
|
feSeparator: PropTypes.string,
|
|
40
|
+
module: PropTypes.string,
|
|
37
41
|
};
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import React, { useContext } from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
|
-
import { translate,
|
|
3
|
+
import { translate, getBonusData } from '~helpers/getters.mjs';
|
|
4
4
|
import { Context } from '~context/MainProvider';
|
|
5
5
|
import CtaButton from '../../../atoms/button/operator-cta';
|
|
6
6
|
import styles from './bonus-box.module.scss';
|
|
7
|
+
import PrettyLink from '~atoms/pretty-link';
|
|
7
8
|
import VariableComponent from '../variables';
|
|
8
9
|
|
|
9
10
|
export default function BonusBox({
|
|
@@ -17,18 +18,19 @@ export default function BonusBox({
|
|
|
17
18
|
splitBy = '+',
|
|
18
19
|
feSeparator = '+',
|
|
19
20
|
buttonType = 'primary',
|
|
20
|
-
module =
|
|
21
|
+
module = 'bonus_box',
|
|
21
22
|
}) {
|
|
22
23
|
const { translations } = useContext(Context) || {};
|
|
23
24
|
const welcomeBonusTranslation = translate(translations, 'welcome_bonus', 'Welcome Bonus');
|
|
24
|
-
const prettyLink = prettyTracker(item, tracker, false, pageTemplate);
|
|
25
25
|
const data = getBonusData(item, tracker, splitBy);
|
|
26
26
|
|
|
27
27
|
const content = () => (
|
|
28
|
-
<
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
<PrettyLink
|
|
29
|
+
operator={item}
|
|
30
|
+
pageTemplate={pageTemplate}
|
|
31
|
+
module={module}
|
|
32
|
+
tracker={tracker}
|
|
33
|
+
clickedElement="oneliner"
|
|
32
34
|
className={`${styles.detailsBox} ${'bonus-box-gtm'}`}
|
|
33
35
|
>
|
|
34
36
|
{welcomeBonus && <p>{welcomeBonusTranslation}</p>}
|
|
@@ -36,7 +38,7 @@ export default function BonusBox({
|
|
|
36
38
|
{data?.secondLine && (
|
|
37
39
|
<span className={styles.secondPart}>{`${feSeparator}${data.secondLine}`}</span>
|
|
38
40
|
)}
|
|
39
|
-
</
|
|
41
|
+
</PrettyLink>
|
|
40
42
|
);
|
|
41
43
|
|
|
42
44
|
return (
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import { FaArrowRight } from '@react-icons/all-files/fa/FaArrowRight';
|
|
4
|
-
import {
|
|
4
|
+
import { getBonusData } from '~helpers/getters.mjs';
|
|
5
5
|
import CtaButton from '../../../atoms/button/operator-cta';
|
|
6
|
+
import PrettyLink from '~atoms/pretty-link';
|
|
6
7
|
import styles from './bonus-box.module.scss';
|
|
7
8
|
|
|
8
9
|
export default function BonusBox({
|
|
@@ -12,24 +13,26 @@ export default function BonusBox({
|
|
|
12
13
|
splitBy = '+',
|
|
13
14
|
feSeparator = '+',
|
|
14
15
|
buttonType = 'primary',
|
|
15
|
-
module =
|
|
16
|
+
module = 'bonus_box',
|
|
16
17
|
}) {
|
|
17
|
-
const prettyLink = prettyTracker(item, tracker, false, pageTemplate);
|
|
18
18
|
const data = getBonusData(item, tracker, splitBy);
|
|
19
19
|
|
|
20
20
|
return (
|
|
21
21
|
<div className={styles.bonusBox}>
|
|
22
|
-
<
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
<PrettyLink
|
|
23
|
+
operator={item}
|
|
24
|
+
pageTemplate={pageTemplate}
|
|
25
|
+
module={module}
|
|
26
|
+
tracker={tracker}
|
|
27
|
+
clickedElement="oneliner"
|
|
26
28
|
className={`${styles.detailsBox} ${'bonus-box-gtm'}`}
|
|
27
29
|
>
|
|
28
30
|
{data?.mainLine && <span className={styles.firstPart}>{data.mainLine}</span>}
|
|
29
31
|
{data?.secondLine && (
|
|
30
32
|
<span className={styles.secondPart}>{`${feSeparator}${data.secondLine}`}</span>
|
|
31
33
|
)}
|
|
32
|
-
</
|
|
34
|
+
</PrettyLink>
|
|
35
|
+
|
|
33
36
|
<CtaButton
|
|
34
37
|
operator={item}
|
|
35
38
|
icon={<FaArrowRight title="Right-pointing Arrow Icon" />}
|
|
@@ -21,7 +21,7 @@ const Main = ({ section = {}, pageContext = {}, serverData = {}, exclOperator =
|
|
|
21
21
|
{NotFound && <NotFound pageContext={pageContext} />}
|
|
22
22
|
{HtmlSitemap && <HtmlSitemap pageContext={pageContext} />}
|
|
23
23
|
{section.modules &&
|
|
24
|
-
section.modules.map((module) => (
|
|
24
|
+
section.modules.map((module, index) => (
|
|
25
25
|
<Module
|
|
26
26
|
key={keygen()}
|
|
27
27
|
module={module}
|
|
@@ -29,6 +29,7 @@ const Main = ({ section = {}, pageContext = {}, serverData = {}, exclOperator =
|
|
|
29
29
|
page={page}
|
|
30
30
|
pageContext={pageContext}
|
|
31
31
|
serverData={serverData}
|
|
32
|
+
modulePosition={index}
|
|
32
33
|
/>
|
|
33
34
|
))}
|
|
34
35
|
{AuthorBox && (
|
|
@@ -5,8 +5,9 @@ import PropTypes from 'prop-types';
|
|
|
5
5
|
import Bonus from '~molecules/bonus-box/template-one';
|
|
6
6
|
import SellingPoints from '~atoms/selling-points';
|
|
7
7
|
import ReviewLink from '../../../atoms/review-link';
|
|
8
|
+
import PrettyLink from '~atoms/pretty-link';
|
|
8
9
|
import OperatorCta from '~atoms/button/operator-cta';
|
|
9
|
-
import {
|
|
10
|
+
import { imagePrettyUrl, getAltText } from '~helpers/getters';
|
|
10
11
|
import LazyImage from '~hooks/lazy-image';
|
|
11
12
|
|
|
12
13
|
import styles from './default-row.module.scss';
|
|
@@ -22,10 +23,7 @@ const Row = ({
|
|
|
22
23
|
className,
|
|
23
24
|
module,
|
|
24
25
|
}) => {
|
|
25
|
-
const prettyLink = prettyTracker(item, tracker, false, pageTemplate);
|
|
26
|
-
// const itemRating = item.rating;
|
|
27
26
|
const reviewPath = item.review_link ? `/${item.review_link}` : item.path || null;
|
|
28
|
-
|
|
29
27
|
const imageObject = item?.standardised_logo_url_object || item?.logo_url_object;
|
|
30
28
|
|
|
31
29
|
const addToRefs = (el, itemNum) => {
|
|
@@ -42,13 +40,13 @@ const Row = ({
|
|
|
42
40
|
<div className={styles.ribbons || ''}>
|
|
43
41
|
{item.ribbons && item.ribbons.map((ribbon) => <span>{ribbon}</span>)}
|
|
44
42
|
</div>
|
|
45
|
-
<
|
|
46
|
-
|
|
47
|
-
|
|
43
|
+
<PrettyLink
|
|
44
|
+
operator={item}
|
|
45
|
+
pageTemplate={pageTemplate}
|
|
46
|
+
module={module}
|
|
47
|
+
tracker={tracker}
|
|
48
|
+
clickedElement="logo"
|
|
48
49
|
className={`casinos-top-list-gtm logo-cta ${styles.logo}`}
|
|
49
|
-
target="_blank"
|
|
50
|
-
rel="noreferrer sponsored nofollow"
|
|
51
|
-
aria-label={`${item.name} Link`}
|
|
52
50
|
>
|
|
53
51
|
<LazyImage
|
|
54
52
|
alt={getAltText(imageObject, item.name)}
|
|
@@ -56,9 +54,8 @@ const Row = ({
|
|
|
56
54
|
width={100}
|
|
57
55
|
height={100}
|
|
58
56
|
/>
|
|
59
|
-
</
|
|
60
|
-
<Bonus item={item} tracker={oneliner} />
|
|
61
|
-
{/* <StarRating numOfStars={5} rating={itemRating} showLabel /> */}
|
|
57
|
+
</PrettyLink>
|
|
58
|
+
<Bonus module="bonus" item={item} tracker={oneliner} />
|
|
62
59
|
<SellingPoints sellingPoints={item.selling_points} />
|
|
63
60
|
{reviewPath && (
|
|
64
61
|
<ReviewLink
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
import React, { useEffect } from 'react';
|
|
5
5
|
import PropTypes from 'prop-types';
|
|
6
6
|
import loadable from '@loadable/component';
|
|
7
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
8
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
7
9
|
import { getSection } from '~helpers/getters';
|
|
8
10
|
import Header from '~molecules/header';
|
|
9
11
|
import Main from '~molecules/main';
|
|
@@ -11,39 +13,23 @@ import Footer from '~molecules/footer';
|
|
|
11
13
|
import Navigation from '~organisms/navigation';
|
|
12
14
|
import ScrollToTop from '~atoms/scroll-to-top';
|
|
13
15
|
import CookieConsent from '~organisms/cookie-consent';
|
|
16
|
+
import { setCookie, getCookie } from '~helpers/cookies';
|
|
14
17
|
|
|
15
18
|
function Body({ pageContext, children, hideOperatorBanner, serverData }) {
|
|
16
19
|
const getBodySection = (name) => getSection(name, pageContext);
|
|
17
20
|
const { template } = pageContext.page;
|
|
18
21
|
const is404 = pageContext?.page?.path?.includes('404');
|
|
19
22
|
|
|
20
|
-
// testing
|
|
21
|
-
|
|
22
23
|
const main = getBodySection('main');
|
|
23
24
|
const navigation = getBodySection('navigation');
|
|
24
25
|
const footer = getBodySection('footer');
|
|
25
26
|
|
|
26
27
|
useEffect(() => {
|
|
27
|
-
if (!
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
if (
|
|
32
|
-
document.domain !== `prelive.${process.env.GATSBY_SITE_NAME}` ||
|
|
33
|
-
document.domain !== process.env.GATSBY_SITE_NAME ||
|
|
34
|
-
document.domain !== `www.${process.env.GATSBY_SITE_NAME}`
|
|
35
|
-
) {
|
|
36
|
-
const l = location.href;
|
|
37
|
-
const r = document.referrer;
|
|
38
|
-
const img = new Image();
|
|
39
|
-
img.src = `${'http://canarytokens.com/' + `[${process.env.CANARY_TOKEN}].jpg?l=`}${encodeURI(
|
|
40
|
-
l
|
|
41
|
-
)}&r=${encodeURI(r)}`;
|
|
28
|
+
if (!getCookie('affUUID')) {
|
|
29
|
+
setCookie('affUUID', uuidv4());
|
|
42
30
|
}
|
|
43
31
|
}, []);
|
|
44
32
|
|
|
45
|
-
// eslint-disable-next-line camelcase
|
|
46
|
-
const { relation_type } = pageContext.page;
|
|
47
33
|
const status = pageContext.page.relation?.status;
|
|
48
34
|
const hideBanner = status === 'inactive' || status === 'coming_soon';
|
|
49
35
|
const pageType = pageContext.page.relation_type;
|
package/src/helpers/tracker.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable no-underscore-dangle */
|
|
1
2
|
import { generateTrackerLink } from '~helpers/generators';
|
|
2
3
|
|
|
3
4
|
export function getTrackerName(operator, page, path) {
|
|
@@ -32,19 +33,19 @@ export function getTrackerName(operator, page, path) {
|
|
|
32
33
|
|
|
33
34
|
function isJsonString(str) {
|
|
34
35
|
try {
|
|
35
|
-
|
|
36
|
+
JSON.parse(str);
|
|
36
37
|
} catch (e) {
|
|
37
|
-
|
|
38
|
+
return false;
|
|
38
39
|
}
|
|
39
40
|
return true;
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
function deparam(paramStr) {
|
|
43
|
-
const paramArr = paramStr.split('&');
|
|
44
|
+
const paramArr = paramStr.split('&');
|
|
44
45
|
const paramObj = {};
|
|
45
|
-
paramArr.forEach(e=>{
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
paramArr.forEach((e) => {
|
|
47
|
+
const param = e.split('=');
|
|
48
|
+
paramObj[param[0]] = decodeURIComponent(param[1]);
|
|
48
49
|
});
|
|
49
50
|
return paramObj;
|
|
50
51
|
}
|
|
@@ -53,6 +54,7 @@ function deparam(paramStr) {
|
|
|
53
54
|
/* eslint-disable import/prefer-default-export */
|
|
54
55
|
export async function getAffiliateLink(operator, path, page, headers, url) {
|
|
55
56
|
const trackerName = await getTrackerName(operator, page, path);
|
|
57
|
+
|
|
56
58
|
const cookie =
|
|
57
59
|
headers && headers.get('cookie')
|
|
58
60
|
? headers
|
|
@@ -62,9 +64,8 @@ export async function getAffiliateLink(operator, path, page, headers, url) {
|
|
|
62
64
|
.reduce((acc, [k, v]) => (acc[k.trim().replace('"', '')] = v) && acc, {})
|
|
63
65
|
: { affObject: JSON.stringify({}) };
|
|
64
66
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
if(url && url.split('?').length === 2) {
|
|
67
|
+
let extraParams = null;
|
|
68
|
+
if (url && url.split('?').length === 2) {
|
|
68
69
|
extraParams = deparam(`${url.split('?')[1]}`);
|
|
69
70
|
}
|
|
70
71
|
|
|
@@ -76,8 +77,12 @@ export async function getAffiliateLink(operator, path, page, headers, url) {
|
|
|
76
77
|
tracker_name: trackerName.name,
|
|
77
78
|
market_short_code: operator.market,
|
|
78
79
|
ip_address: headers ? headers.get('x-real-ip') || headers.get('host') : '127.0.0.1',
|
|
80
|
+
user_agent: headers ? headers.get('user-agent') || headers.get('user-agent') : 'N/A',
|
|
81
|
+
user_uuid: cookie ? cookie.affUUID || 'N/A' : 'N/A',
|
|
82
|
+
facebook_browser_id: cookie ? cookie._fbp || 'N/A' : 'N/A',
|
|
83
|
+
facebook_pixel_id: process.env.PIXEL_ID || 'N/A',
|
|
79
84
|
...(isJsonString(cookie.affObject) ? JSON.parse(cookie.affObject) : {}),
|
|
80
|
-
...(extraParams || {})
|
|
85
|
+
...(extraParams || {}),
|
|
81
86
|
};
|
|
82
87
|
|
|
83
88
|
const res = await fetch(
|
|
@@ -89,3 +94,40 @@ export async function getAffiliateLink(operator, path, page, headers, url) {
|
|
|
89
94
|
props: data,
|
|
90
95
|
};
|
|
91
96
|
}
|
|
97
|
+
|
|
98
|
+
export function getTrackingAPIParams(pageTemplate, module, tracker, clickedElement, url) {
|
|
99
|
+
const urlParams = {};
|
|
100
|
+
|
|
101
|
+
if (pageTemplate) {
|
|
102
|
+
urlParams.page_type = pageTemplate;
|
|
103
|
+
}
|
|
104
|
+
if (module) {
|
|
105
|
+
urlParams.module = module;
|
|
106
|
+
}
|
|
107
|
+
if (tracker !== 'main') {
|
|
108
|
+
urlParams.tracker_name = tracker;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (clickedElement) {
|
|
112
|
+
urlParams.clicked_element = clickedElement;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (url && url.split('?').length === 2) {
|
|
116
|
+
// eslint-disable-next-line prefer-destructuring
|
|
117
|
+
urlParams.request_url = url.split('?')[0];
|
|
118
|
+
const extraData = deparam(url.split('?')[1]);
|
|
119
|
+
if (extraData.fbclid) {
|
|
120
|
+
urlParams.facebook_click_id = extraData.fbclid;
|
|
121
|
+
}
|
|
122
|
+
if (extraData.msclkid) {
|
|
123
|
+
urlParams.microsoft_click_id = extraData.msclkid;
|
|
124
|
+
}
|
|
125
|
+
if (extraData.gclid) {
|
|
126
|
+
urlParams.google_click_id = extraData.gclid;
|
|
127
|
+
}
|
|
128
|
+
} else if (url) {
|
|
129
|
+
urlParams.request_url = url;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return urlParams;
|
|
133
|
+
}
|
|
@@ -70,7 +70,9 @@ describe('Tracker Helper', () => {
|
|
|
70
70
|
|
|
71
71
|
expect(fetch).toBeCalledTimes(1);
|
|
72
72
|
expect(fetch).toBeCalledWith(
|
|
73
|
-
`${process.env.GATSBY_TRACKING_API_URL}?${new URLSearchParams(
|
|
73
|
+
`${process.env.GATSBY_TRACKING_API_URL}?${new URLSearchParams(
|
|
74
|
+
urlParam
|
|
75
|
+
).toString()}&user_agent=N%2FA&user_uuid=N%2FA&facebook_browser_id=N%2FA&facebook_pixel_id=N%2FA`
|
|
74
76
|
);
|
|
75
77
|
});
|
|
76
78
|
|
|
@@ -83,23 +85,38 @@ describe('Tracker Helper', () => {
|
|
|
83
85
|
'/path?extraparam=val&extraparam2=val2'
|
|
84
86
|
);
|
|
85
87
|
|
|
86
|
-
const tracker = Tracker.getTrackerName(operator, 'default', '/no/visit/rizk');
|
|
87
|
-
|
|
88
|
-
const urlParam = {
|
|
89
|
-
site_id: process.env.SITE_ID,
|
|
90
|
-
operator_short_name: operator.short_name,
|
|
91
|
-
operator_type: operator.type,
|
|
92
|
-
language: operator.market.split('_')[1],
|
|
93
|
-
tracker_name: tracker.name,
|
|
94
|
-
market_short_code: operator.market,
|
|
95
|
-
ip_address: '127.0.0.1',
|
|
96
|
-
extraparam: 'val',
|
|
97
|
-
extraparam2: 'val2',
|
|
98
|
-
};
|
|
99
|
-
|
|
100
88
|
expect(fetch).toBeCalledTimes(1);
|
|
101
89
|
expect(fetch).toBeCalledWith(
|
|
102
|
-
|
|
90
|
+
`testlink?site_id=82&operator_short_name=rizk&operator_type=sportsbook&language=en&tracker_name=main&market_short_code=ie_en&ip_address=127.0.0.1&user_agent=N%2FA&user_uuid=N%2FA&facebook_browser_id=N%2FA&facebook_pixel_id=N%2FA&extraparam=val&extraparam2=val2`
|
|
91
|
+
);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
test('getTrackingAPIParams tests', async () => {
|
|
95
|
+
const params = Tracker.getTrackingAPIParams(
|
|
96
|
+
'temlateValue',
|
|
97
|
+
'moduleValue',
|
|
98
|
+
'trackerValue',
|
|
99
|
+
'clickedElementValue',
|
|
100
|
+
'urlValue'
|
|
101
|
+
);
|
|
102
|
+
expect(params.page_type).toEqual('temlateValue');
|
|
103
|
+
expect(params.module).toEqual('moduleValue');
|
|
104
|
+
expect(params.tracker_name).toEqual('trackerValue');
|
|
105
|
+
expect(params.clicked_element).toEqual('clickedElementValue');
|
|
106
|
+
expect(params.request_url).toEqual('urlValue');
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test('getTrackingAPIParams tests with url Params', async () => {
|
|
110
|
+
const params = Tracker.getTrackingAPIParams(
|
|
111
|
+
null,
|
|
112
|
+
null,
|
|
113
|
+
null,
|
|
114
|
+
null,
|
|
115
|
+
'urlValue?fbclid=param1&msclkid=param2&gclid=param3'
|
|
103
116
|
);
|
|
117
|
+
expect(params.request_url).toEqual('urlValue');
|
|
118
|
+
expect(params.facebook_click_id).toEqual('param1');
|
|
119
|
+
expect(params.microsoft_click_id).toEqual('param2');
|
|
120
|
+
expect(params.google_click_id).toEqual('param3');
|
|
104
121
|
});
|
|
105
122
|
});
|