From 71eb444379465141f3134cc58b13cf9dd46f5b51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=BA=C5=A1=20Tomlein?= Date: Wed, 23 Mar 2022 15:16:43 +0100 Subject: [PATCH] Add ability to enable only form_change, or form_submit, focus_form or any combination (close #371) PR #1065 --- ...acking_configuration_2022-03-15-08-57.json | 10 ++ ...acking_configuration_2022-03-15-08-57.json | 10 ++ .../src/helpers.ts | 53 ++++++++--- .../test/integration/autoTracking.test.ts | 91 ++++++++++++++----- .../test/pages/form-tracking.html | 3 + 5 files changed, 129 insertions(+), 38 deletions(-) create mode 100644 common/changes/@snowplow/browser-plugin-form-tracking/issue-371-form_tracking_configuration_2022-03-15-08-57.json create mode 100644 common/changes/@snowplow/javascript-tracker/issue-371-form_tracking_configuration_2022-03-15-08-57.json diff --git a/common/changes/@snowplow/browser-plugin-form-tracking/issue-371-form_tracking_configuration_2022-03-15-08-57.json b/common/changes/@snowplow/browser-plugin-form-tracking/issue-371-form_tracking_configuration_2022-03-15-08-57.json new file mode 100644 index 000000000..30a5c3cf3 --- /dev/null +++ b/common/changes/@snowplow/browser-plugin-form-tracking/issue-371-form_tracking_configuration_2022-03-15-08-57.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@snowplow/browser-plugin-form-tracking", + "comment": "Add ability to enable only form_change, or form_submit, focus_form or any combination (#371)", + "type": "none" + } + ], + "packageName": "@snowplow/browser-plugin-form-tracking" +} \ No newline at end of file diff --git a/common/changes/@snowplow/javascript-tracker/issue-371-form_tracking_configuration_2022-03-15-08-57.json b/common/changes/@snowplow/javascript-tracker/issue-371-form_tracking_configuration_2022-03-15-08-57.json new file mode 100644 index 000000000..6b34a2649 --- /dev/null +++ b/common/changes/@snowplow/javascript-tracker/issue-371-form_tracking_configuration_2022-03-15-08-57.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@snowplow/javascript-tracker", + "comment": "Add ability to enable only form_change, or form_submit, focus_form or any combination (#371)", + "type": "none" + } + ], + "packageName": "@snowplow/javascript-tracker" +} \ No newline at end of file diff --git a/plugins/browser-plugin-form-tracking/src/helpers.ts b/plugins/browser-plugin-form-tracking/src/helpers.ts index 39c9373fe..22d667521 100644 --- a/plugins/browser-plugin-form-tracking/src/helpers.ts +++ b/plugins/browser-plugin-form-tracking/src/helpers.ts @@ -51,9 +51,28 @@ export interface FormTrackingConfiguration { context?: DynamicContext | null; } +/** Events to capture in form tracking */ +export enum FormTrackingEvent { + /** Form field changed event */ + CHANGE_FORM = 'change_form', + /** Form field focused event */ + FOCUS_FORM = 'focus_form', + /** Form submitted event */ + SUBMIT_FORM = 'submit_form', +} + +/** List of form tracking events to capture */ +export type FormTrackingEvents = Array; +const defaultFormTrackingEvents = [ + FormTrackingEvent.CHANGE_FORM, + FormTrackingEvent.FOCUS_FORM, + FormTrackingEvent.SUBMIT_FORM, +]; + export interface FormTrackingOptions { forms?: FilterCriterion; fields?: FilterCriterion & { transform: transformFn }; + events?: FormTrackingEvents; } export interface TrackedHTMLElementTagNameMap { @@ -105,25 +124,31 @@ export function addFormListeners(tracker: BrowserTracker, configuration: FormTra !innerElement[trackingMarker] && innerElement.type.toLowerCase() !== 'password' ) { - addEventListener( - innerElement, - 'focus', - getFormChangeListener(tracker, config, 'focus_form', context), - false - ); - addEventListener( - innerElement, - 'change', - getFormChangeListener(tracker, config, 'change_form', context), - false - ); + if (config.eventFilter(FormTrackingEvent.FOCUS_FORM)) { + addEventListener( + innerElement, + 'focus', + getFormChangeListener(tracker, config, 'focus_form', context), + false + ); + } + if (config.eventFilter(FormTrackingEvent.CHANGE_FORM)) { + addEventListener( + innerElement, + 'change', + getFormChangeListener(tracker, config, 'change_form', context), + false + ); + } innerElement[trackingMarker] = true; } }); }); if (!form[trackingMarker]) { - addEventListener(form, 'submit', getFormSubmissionListener(tracker, config, trackingMarker, context)); + if (config.eventFilter(FormTrackingEvent.SUBMIT_FORM)) { + addEventListener(form, 'submit', getFormSubmissionListener(tracker, config, trackingMarker, context)); + } form[trackingMarker] = true; } } @@ -139,12 +164,14 @@ function getConfigurationForOptions(options?: FormTrackingOptions) { formFilter: getFilterByClass(options.forms), fieldFilter: getFilterByName(options.fields), fieldTransform: getTransform(options.fields), + eventFilter: (event: FormTrackingEvent) => (options.events ?? defaultFormTrackingEvents).indexOf(event) > -1, }; } else { return { formFilter: () => true, fieldFilter: () => true, fieldTransform: defaultTransformFn, + eventFilter: () => true, }; } } diff --git a/trackers/javascript-tracker/test/integration/autoTracking.test.ts b/trackers/javascript-tracker/test/integration/autoTracking.test.ts index d8898d7fb..eb4c5dd82 100755 --- a/trackers/javascript-tracker/test/integration/autoTracking.test.ts +++ b/trackers/javascript-tracker/test/integration/autoTracking.test.ts @@ -243,41 +243,45 @@ describe('Auto tracking', () => { }); it('should send form events', async () => { - await loadUrlAndWait('/form-tracking.html'); - await $('#fname').click(); + async function formInteraction() { + await $('#fname').click(); - // Safari 12.1 doesn't fire onchange events when clearing - // However some browsers don't support setValue - if (F.isMatch({ browserName: 'Safari', browserVersion: '12.1.1' }, browser.capabilities)) { - await $('#fname').setValue(SAFARI_EXPECTED_FIRST_NAME); - } else { - await $('#fname').clearValue(); - } + // Safari 12.1 doesn't fire onchange events when clearing + // However some browsers don't support setValue + if (F.isMatch({ browserName: 'Safari', browserVersion: '12.1.1' }, browser.capabilities)) { + await $('#fname').setValue(SAFARI_EXPECTED_FIRST_NAME); + } else { + await $('#fname').clearValue(); + } - await $('#lname').click(); + await $('#lname').click(); - await browser.pause(250); + await browser.pause(250); - await $('#bike').click(); + await $('#bike').click(); - await browser.pause(250); + await browser.pause(250); - await $('#cars').click(); - await $('#cars').selectByAttribute('value', 'saab'); - await $('#cars').click(); + await $('#cars').click(); + await $('#cars').selectByAttribute('value', 'saab'); + await $('#cars').click(); - await browser.pause(250); + await browser.pause(250); - await $('#message').click(); + await $('#message').click(); - // Safari 12.1 doesn't fire onchange events when clearing - // However some browsers don't support setValue - if (F.isMatch({ browserName: 'Safari', browserVersion: '12.1.1' }, browser.capabilities)) { - await $('#message').setValue(SAFARI_EXPECTED_MESSAGE); - } else { - await $('#message').clearValue(); + // Safari 12.1 doesn't fire onchange events when clearing + // However some browsers don't support setValue + if (F.isMatch({ browserName: 'Safari', browserVersion: '12.1.1' }, browser.capabilities)) { + await $('#message').setValue(SAFARI_EXPECTED_MESSAGE); + } else { + await $('#message').clearValue(); + } } + await loadUrlAndWait('/form-tracking.html'); + await formInteraction(); + await browser.pause(250); await $('#terms').click(); @@ -319,7 +323,12 @@ describe('Auto tracking', () => { await loadUrlAndWait('/form-tracking.html?filter=excludedForm'); await $('#excluded-fname').click(); - $('#excluded-submit').click(); + await $('#excluded-submit').click(); + + await browser.pause(1000); + + await loadUrlAndWait('/form-tracking.html?filter=onlyFocus'); + await formInteraction(); // time for activity to register and request to arrive await browser.pause(2500); @@ -781,4 +790,36 @@ describe('Auto tracking', () => { }) ).toBe(false); }); + + it('should only track focus_form and not change_form events when focus_form events are filtered', () => { + expect( + logContains({ + event: { + event: 'unstruct', + app_id: 'autotracking', + page_url: 'http://snowplow-js-tracker.local:8080/form-tracking.html?filter=onlyFocus', + unstruct_event: { + data: { + schema: 'iglu:com.snowplowanalytics.snowplow/focus_form/jsonschema/1-0-0', + }, + }, + }, + }) + ).toBe(true); + + expect( + logContains({ + event: { + event: 'unstruct', + app_id: 'autotracking', + page_url: 'http://snowplow-js-tracker.local:8080/form-tracking.html?filter=onlyFocus', + unstruct_event: { + data: { + schema: 'iglu:com.snowplowanalytics.snowplow/change_form/jsonschema/1-0-0', + }, + }, + }, + }) + ).toBe(false); + }); }); diff --git a/trackers/javascript-tracker/test/pages/form-tracking.html b/trackers/javascript-tracker/test/pages/form-tracking.html index ac8767378..7f27c659a 100644 --- a/trackers/javascript-tracker/test/pages/form-tracking.html +++ b/trackers/javascript-tracker/test/pages/form-tracking.html @@ -115,6 +115,9 @@ case 'excludedForm': snowplow('enableFormTracking', { options: { forms: { denylist: ['excluded-form'] } } }); break; + case 'onlyFocus': + snowplow('enableFormTracking', { options: { events: ['focus_form'] } }); + break; default: snowplow('enableFormTracking', { context: [