Skip to content

Commit 9f9dab2

Browse files
author
Sam Grace
committed
fix: track clicks on elements nested inside trackable elements
1 parent 82711a9 commit 9f9dab2

File tree

4 files changed

+37
-3
lines changed

4 files changed

+37
-3
lines changed

cypress/integration/basic_spec.js

+5
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,9 @@ describe('Festicket Analytics', () => {
2828
payload: 'payload',
2929
});
3030
});
31+
32+
it('should track clicks on elements that are children of track-able elements', () => {
33+
cy.get('[data-cy=nested-span]').click();
34+
cy.get('@track').should('be.called');
35+
});
3136
});

src/closest-polyfill.js

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/**
2+
* Element.closest polyfill
3+
* https://developer.mozilla.org/en-US/docs/Web/API/Element/closest
4+
*/
5+
6+
if (!Element.prototype.matches)
7+
Element.prototype.matches =
8+
Element.prototype.msMatchesSelector ||
9+
Element.prototype.webkitMatchesSelector;
10+
11+
if (!Element.prototype.closest) {
12+
Element.prototype.closest = function closest(s) {
13+
let el = this;
14+
if (!document.documentElement.contains(el)) return null;
15+
do {
16+
if (el.matches(s)) return el;
17+
el = el.parentElement || el.parentNode;
18+
} while (el !== null && el.nodeType === 1);
19+
return null;
20+
};
21+
}

src/index.js

+8-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import './closest-polyfill';
12
import loadScript from './load-script';
23

34
// Lower case the first character of any string
@@ -48,12 +49,16 @@ function aliasFactory(key) {
4849
// Handle click events
4950
async function eventHandle(track, key, e) {
5051
// Only track elements with data-analytics=true
51-
if (!e.target.dataset.analytics) {
52+
// Use `Element.closest` because the clicked element may be a child
53+
// of an element with data-analytics=true on it.
54+
const target = e.target.closest('[data-analytics=true]');
55+
56+
if (!target) {
5257
return;
5358
}
5459

5560
// Strip data-analytics=true
56-
const { analytics, analyticsEvent, ...data } = e.target.dataset;
61+
const { analytics, analyticsEvent, ...data } = target.dataset;
5762

5863
// Map through the data props and only use data-analytics-* as the data payload
5964
const payloadData = Object.keys(data).reduce((result, propName) => {
@@ -67,7 +72,7 @@ async function eventHandle(track, key, e) {
6772
}, {});
6873

6974
// construct our event payload with { elementId: element.id }
70-
const elementData = e.target.id ? { elementId: e.target.id } : {};
75+
const elementData = target.id ? { elementId: target.id } : {};
7176

7277
// Actually track our event
7378
await track(analyticsEvent, { ...payloadData, ...elementData });

test/index.html

+3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
>
2323
This should fire analytics with data
2424
</button>
25+
<a data-analytics="true">
26+
<span data-cy="nested-span">Clicking here should fire analytics</span>
27+
</a>
2528
</body>
2629
<script src="http://localhost:8080/runner.js"></script>
2730
</html>

0 commit comments

Comments
 (0)