Skip to content

Commit

Permalink
Add ability to enable only form_change, or form_submit, focus_form or…
Browse files Browse the repository at this point in the history
… any combination (close #371)

PR #1065
  • Loading branch information
matus-tomlein committed Mar 23, 2022
1 parent 1d7f993 commit 71eb444
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 38 deletions.
Original file line number Diff line number Diff line change
@@ -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"
}
Original file line number Diff line number Diff line change
@@ -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"
}
53 changes: 40 additions & 13 deletions plugins/browser-plugin-form-tracking/src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<FormTrackingEvent>;
const defaultFormTrackingEvents = [
FormTrackingEvent.CHANGE_FORM,
FormTrackingEvent.FOCUS_FORM,
FormTrackingEvent.SUBMIT_FORM,
];

export interface FormTrackingOptions {
forms?: FilterCriterion<HTMLElement>;
fields?: FilterCriterion<TrackedHTMLElement> & { transform: transformFn };
events?: FormTrackingEvents;
}

export interface TrackedHTMLElementTagNameMap {
Expand Down Expand Up @@ -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;
}
}
Expand All @@ -139,12 +164,14 @@ function getConfigurationForOptions(options?: FormTrackingOptions) {
formFilter: getFilterByClass(options.forms),
fieldFilter: getFilterByName<TrackedHTMLElement>(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,
};
}
}
Expand Down
91 changes: 66 additions & 25 deletions trackers/javascript-tracker/test/integration/autoTracking.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
});
});
3 changes: 3 additions & 0 deletions trackers/javascript-tracker/test/pages/form-tracking.html
Original file line number Diff line number Diff line change
Expand Up @@ -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: [
Expand Down

0 comments on commit 71eb444

Please sign in to comment.