diff --git a/extensions/amp-form/0.1/amp-form.js b/extensions/amp-form/0.1/amp-form.js index 7115de5064d3..81335c44999a 100644 --- a/extensions/amp-form/0.1/amp-form.js +++ b/extensions/amp-form/0.1/amp-form.js @@ -295,9 +295,10 @@ export class AmpForm { * Triggers 'amp-form-submit' event in 'amp-analytics' and * generates variables for form fields to be accessible in analytics * + * @param {string} eventType * @private */ - triggerFormSubmitInAnalytics_() { + triggerFormSubmitInAnalytics_(eventType) { const formDataForAnalytics = {}; const formObject = this.getFormAsObject_(); @@ -309,7 +310,7 @@ export class AmpForm { } formDataForAnalytics['formId'] = this.form_.id; - this.analyticsEvent_('amp-form-submit', formDataForAnalytics); + this.analyticsEvent_(eventType, formDataForAnalytics); } /** @@ -438,7 +439,7 @@ export class AmpForm { const p = this.doVarSubs_(varSubsFields) .then(() => { - this.triggerFormSubmitInAnalytics_(); + this.triggerFormSubmitInAnalytics_('amp-form-submit'); this.actions_.trigger( this.form_, 'submit', /* event */ null, trust); // After variable substitution @@ -536,7 +537,7 @@ export class AmpForm { handleXhrSubmitSuccess_(response) { return response.json().then(json => { this.triggerAction_(/* success */ true, json); - this.analyticsEvent_('amp-form-submit-success'); + this.triggerFormSubmitInAnalytics_('amp-form-submit-success'); this.setState_(FormState_.SUBMIT_SUCCESS); this.renderTemplate_(json || {}); this.maybeHandleRedirect_(response); @@ -559,7 +560,7 @@ export class AmpForm { } return promise.then(responseJson => { this.triggerAction_(/* success */ false, responseJson); - this.analyticsEvent_('amp-form-submit-error'); + this.triggerFormSubmitInAnalytics_('amp-form-submit-error'); this.setState_(FormState_.SUBMIT_ERROR); this.renderTemplate_(responseJson || {}); this.maybeHandleRedirect_(error.response); @@ -587,7 +588,7 @@ export class AmpForm { for (let i = 0; i < varSubsFields.length; i++) { this.urlReplacement_.expandInputValueSync(varSubsFields[i]); } - this.triggerFormSubmitInAnalytics_(); + this.triggerFormSubmitInAnalytics_('amp-form-submit'); } /** diff --git a/extensions/amp-form/0.1/test/test-amp-form.js b/extensions/amp-form/0.1/test/test-amp-form.js index ae03161ec788..3e6727349ed5 100644 --- a/extensions/amp-form/0.1/test/test-amp-form.js +++ b/extensions/amp-form/0.1/test/test-amp-form.js @@ -1814,6 +1814,105 @@ describes.repeated('', { }); }); + it('should trigger submit-success analytics event with form data', () => { + return getAmpForm(getForm()).then(ampForm => { + const form = ampForm.form_; + form.id = 'registration'; + + const emailInput = createElement('input'); + emailInput.setAttribute('name', 'email'); + emailInput.setAttribute('type', 'email'); + emailInput.setAttribute('value', 'j@hnmiller.com'); + form.appendChild(emailInput); + + const unnamedInput = createElement('input'); + unnamedInput.setAttribute('type', 'text'); + unnamedInput.setAttribute('value', 'unnamed'); + form.appendChild(unnamedInput); + + let fetchResolver; + sandbox.stub(ampForm.xhr_, 'fetch').returns(new Promise(resolve => { + fetchResolver = resolve; + })); + sandbox.stub(ampForm, 'analyticsEvent_'); + const event = { + stopImmediatePropagation: sandbox.spy(), + target: form, + preventDefault: sandbox.spy(), + }; + ampForm.handleSubmitEvent_(event); + expect(ampForm.state_).to.equal('submitting'); + fetchResolver({json: () => Promise.resolve()}); + + const expectedFormData = { + 'formId': 'registration', + 'formFields[name]': 'John Miller', + 'formFields[email]': 'j@hnmiller.com', + }; + + return ampForm.xhrSubmitPromiseForTesting().then(() => { + expect(ampForm.state_).to.equal('submit-success'); + expect(ampForm.analyticsEvent_).to.be.calledWith( + 'amp-form-submit-success', + expectedFormData + ); + }, () => { + assert.fail('Submit should have succeeded.'); + }); + + }); + }); + + it('should trigger submit-error analytics event with form data', () => { + return getAmpForm(getForm()).then(ampForm => { + const form = ampForm.form_; + form.id = 'registration'; + + const emailInput = createElement('input'); + emailInput.setAttribute('name', 'email'); + emailInput.setAttribute('type', 'email'); + emailInput.setAttribute('value', 'j@hnmiller.com'); + form.appendChild(emailInput); + + const unnamedInput = createElement('input'); + unnamedInput.setAttribute('type', 'text'); + unnamedInput.setAttribute('value', 'unnamed'); + form.appendChild(unnamedInput); + + let fetchRejecter; + sandbox.stub(ampForm.xhr_, 'fetch') + .returns(new Promise((unusedResolve, reject) => { + fetchRejecter = reject; + })); + sandbox.stub(ampForm, 'analyticsEvent_'); + const event = { + stopImmediatePropagation: sandbox.spy(), + target: form, + preventDefault: sandbox.spy(), + }; + ampForm.handleSubmitEvent_(event); + expect(ampForm.state_).to.equal('submitting'); + fetchRejecter(); + + const expectedFormData = { + 'formId': 'registration', + 'formFields[name]': 'John Miller', + 'formFields[email]': 'j@hnmiller.com', + }; + + return ampForm.xhrSubmitPromiseForTesting().then(() => { + assert.fail('Submit should have failed.'); + }, () => { + expect(ampForm.state_).to.equal('submit-error'); + expect(ampForm.analyticsEvent_).to.be.calledWith( + 'amp-form-submit-error', + expectedFormData + ); + }); + + }); + }); + it('should trigger amp-form-submit after variables substitution', () => { return getAmpForm(getForm()).then(ampForm => { const form = ampForm.form_; diff --git a/extensions/amp-form/amp-form.md b/extensions/amp-form/amp-form.md index cb4f5a24ed65..90dd8b79cc0f 100644 --- a/extensions/amp-form/amp-form.md +++ b/extensions/amp-form/amp-form.md @@ -200,7 +200,10 @@ You can configure your analytics to send these events as in the example below. ``` -The `amp-form-submit` event fires when a form request is initiated. The `amp-form-submit` event generates a set of variables that correspond to the specific form and the fields in the form. These variables can be used for analytics. +The `amp-form-submit` event fires when a form request is initiated. +The `amp-form-submit-success` event fires when a successful response is received, that is when the response has a status of `2XX`. Any other status triggers the `amp-form-submit-error` event. + +All three events generate a set of variables that correspond to the specific form and the fields in the form. These variables can be used for analytics. For example, the following form has one field: @@ -210,7 +213,7 @@ For example, the following form has one field: ``` -When the `amp-form-submit` event fires, it generates the following variables containing the values that were specified in the form: +When the `amp-form-submit`, `amp-form-submit-success`, or `amp-form-submit-error` event fires, it generates the following variables containing the values that were specified in the form: * `formId` * `formFields[comment]`