Commit 65444a95 authored by Mark Florian's avatar Mark Florian

Merge branch '337350-only-dispatch-auto-tracked-render-events-once-per-page-load' into 'master'

Only dispatch auto-tracked "render" events once per page load

See merge request gitlab-org/gitlab!67275
parents 36495806 fdedce83
...@@ -18,3 +18,9 @@ export const DEFAULT_SNOWPLOW_OPTIONS = { ...@@ -18,3 +18,9 @@ export const DEFAULT_SNOWPLOW_OPTIONS = {
fields: { allow: [] }, fields: { allow: [] },
}, },
}; };
export const ACTION_ATTR_SELECTOR = '[data-track-action]';
export const LOAD_ACTION_ATTR_SELECTOR = '[data-track-action="render"]';
export const DEPRECATED_EVENT_ATTR_SELECTOR = '[data-track-event]';
export const DEPRECATED_LOAD_EVENT_ATTR_SELECTOR = '[data-track-event="render"]';
import { LOAD_ACTION_ATTR_SELECTOR, DEPRECATED_LOAD_EVENT_ATTR_SELECTOR } from './constants';
import { dispatchSnowplowEvent } from './dispatch_snowplow_event'; import { dispatchSnowplowEvent } from './dispatch_snowplow_event';
import getStandardContext from './get_standard_context'; import getStandardContext from './get_standard_context';
import { getEventHandlers, createEventPayload, renameKey, addExperimentContext } from './utils'; import { getEventHandlers, createEventPayload, renameKey, addExperimentContext } from './utils';
...@@ -98,7 +99,7 @@ export default class Tracking { ...@@ -98,7 +99,7 @@ export default class Tracking {
} }
const loadEvents = parent.querySelectorAll( const loadEvents = parent.querySelectorAll(
'[data-track-action="render"], [data-track-event="render"]', `${LOAD_ACTION_ATTR_SELECTOR}, ${DEPRECATED_LOAD_EVENT_ATTR_SELECTOR}`,
); );
loadEvents.forEach((element) => { loadEvents.forEach((element) => {
......
import { omitBy, isUndefined } from 'lodash'; import { omitBy, isUndefined } from 'lodash';
import { TRACKING_CONTEXT_SCHEMA } from '~/experimentation/constants'; import { TRACKING_CONTEXT_SCHEMA } from '~/experimentation/constants';
import { getExperimentData } from '~/experimentation/utils'; import { getExperimentData } from '~/experimentation/utils';
import {
ACTION_ATTR_SELECTOR,
LOAD_ACTION_ATTR_SELECTOR,
DEPRECATED_EVENT_ATTR_SELECTOR,
DEPRECATED_LOAD_EVENT_ATTR_SELECTOR,
} from './constants';
export const addExperimentContext = (opts) => { export const addExperimentContext = (opts) => {
const { experiment, ...options } = opts; const { experiment, ...options } = opts;
...@@ -65,7 +71,9 @@ export const createEventPayload = (el, { suffix = '' } = {}) => { ...@@ -65,7 +71,9 @@ export const createEventPayload = (el, { suffix = '' } = {}) => {
}; };
export const eventHandler = (e, func, opts = {}) => { export const eventHandler = (e, func, opts = {}) => {
const el = e.target.closest('[data-track-event], [data-track-action]'); const actionSelector = `${ACTION_ATTR_SELECTOR}:not(${LOAD_ACTION_ATTR_SELECTOR})`;
const deprecatedEventSelector = `${DEPRECATED_EVENT_ATTR_SELECTOR}:not(${DEPRECATED_LOAD_EVENT_ATTR_SELECTOR})`;
const el = e.target.closest(`${actionSelector}, ${deprecatedEventSelector}`);
if (!el) { if (!el) {
return; return;
......
...@@ -387,11 +387,13 @@ describe('Tracking', () => { ...@@ -387,11 +387,13 @@ describe('Tracking', () => {
beforeEach(() => { beforeEach(() => {
eventSpy = jest.spyOn(Tracking, 'event'); eventSpy = jest.spyOn(Tracking, 'event');
setHTMLFixture(` setHTMLFixture(`
<input data-track-${term}="render" data-track-label="label1" value=1 data-track-property="_property_"/> <div data-track-${term}="click_link" data-track-label="all_nested_links">
<span data-track-${term}="render" data-track-label="label2" data-track-value=1> <input data-track-${term}="render" data-track-label="label1" value=1 data-track-property="_property_"/>
Something <span data-track-${term}="render" data-track-label="label2" data-track-value=1>
</span> <a href="#" id="link">Something</a>
<input data-track-${term}="_render_bogus_" data-track-label="label3" value="_value_" data-track-property="_property_"/> </span>
<input data-track-${term}="_render_bogus_" data-track-label="label3" value="_value_" data-track-property="_property_"/>
</div>
`); `);
Tracking.trackLoadEvents('_category_'); // only happens once Tracking.trackLoadEvents('_category_'); // only happens once
}); });
...@@ -417,6 +419,35 @@ describe('Tracking', () => { ...@@ -417,6 +419,35 @@ describe('Tracking', () => {
], ],
]); ]);
}); });
describe.each`
event | actionSuffix
${'click'} | ${''}
${'show.bs.dropdown'} | ${'_show'}
${'hide.bs.dropdown'} | ${'_hide'}
`(`auto-tracking $event events on nested elements`, ({ event, actionSuffix }) => {
let link;
beforeEach(() => {
link = document.querySelector('#link');
eventSpy.mockClear();
});
it(`avoids using ancestor [data-track-${term}="render"] tracking configurations`, () => {
link.dispatchEvent(new Event(event, { bubbles: true }));
expect(eventSpy).not.toHaveBeenCalledWith(
'_category_',
`render${actionSuffix}`,
expect.any(Object),
);
expect(eventSpy).toHaveBeenCalledWith(
'_category_',
`click_link${actionSuffix}`,
expect.objectContaining({ label: 'all_nested_links' }),
);
});
});
}); });
describe('tracking mixin', () => { describe('tracking mixin', () => {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment