From 5e21d565feda2cd0f7f8fc1b93552aa85f123180 Mon Sep 17 00:00:00 2001 From: Roman Seidelsohn Date: Fri, 10 Nov 2023 09:01:46 +0100 Subject: [PATCH 01/13] Add line breaks and add userJourneys and additionalInfo to survey link - Wrap long lines - Add userJourneys and additionalInfo parameters and their values to the survey link, so that they can be combined with the survey input users provide for us --- .../js/customer-satisfaction-input.js | 102 ++++++++++++++---- 1 file changed, 84 insertions(+), 18 deletions(-) diff --git a/toolkits/global/packages/global-customer-satisfaction-input/js/customer-satisfaction-input.js b/toolkits/global/packages/global-customer-satisfaction-input/js/customer-satisfaction-input.js index 9d79a2e5e..cfd9055de 100644 --- a/toolkits/global/packages/global-customer-satisfaction-input/js/customer-satisfaction-input.js +++ b/toolkits/global/packages/global-customer-satisfaction-input/js/customer-satisfaction-input.js @@ -3,12 +3,32 @@ class CustomerSatisfactionInput { this._aside = aside; this._form = this._aside.querySelector('form'); this._formRadioFieldset = this._form.querySelector('fieldset'); - this._formRadios = Array.from(this._form.querySelectorAll('[data-customer-satisfaction-input="radio"]')); - this._surveyLink = this._form.querySelector('[data-customer-satisfaction-input="survey-link"]'); + this._formRadios = Array.from( + this._form.querySelectorAll('[data-customer-satisfaction-input="radio"]') + ); + this._surveyLink = this._form.querySelector( + '[data-customer-satisfaction-input="survey-link"]' + ); this._setSurveyLinkHref(); this._submitButton = this._form.querySelector('button[type="submit"]'); - this._submitMessage = this._form.querySelector('[data-customer-satisfaction-input="submit-message"]'); - this._permissibleUserJourneys = ['get prepared to publish', 'get published', 'discover relevant scholarly content', 'manage my editorial work', 'manage my peer reviews', 'promote my work', 'evaluate the performance of scholarly work', 'manage an apc', 'buy something', 'access what i am entitled to', 'librarian get the information i need', 'librarian assess the performance and use of my portfolio', 'librarian buy something']; + this._submitMessage = this._form.querySelector( + '[data-customer-satisfaction-input="submit-message"]' + ); + this._permissibleUserJourneys = [ + 'get prepared to publish', + 'get published', + 'discover relevant scholarly content', + 'manage my editorial work', + 'manage my peer reviews', + 'promote my work', + 'evaluate the performance of scholarly work', + 'manage an apc', + 'buy something', + 'access what i am entitled to', + 'librarian get the information i need', + 'librarian assess the performance and use of my portfolio', + 'librarian buy something' + ]; this._bindEvents(); } @@ -28,7 +48,10 @@ class CustomerSatisfactionInput { _setSurveyLinkHref() { if (this._surveyLink) { - this._surveyLink.href = this._surveyLink.href + '?location=' + window.location.href.split('?')[0]; + this._surveyLink.href = + this._surveyLink.href + + '?location=' + + window.location.href.split('?')[0]; } } @@ -36,28 +59,57 @@ class CustomerSatisfactionInput { this._updateSurveyLinkQueryString('responseRating', rating); } + _setSurveyLinkUserJourneys(userJourneys) { + if (userJourneys) { + this._updateSurveyLinkQueryString('userJourneys', userJourneys); + } + } + + _setSurveyLinkAdditionalInfo(additionalInfo) { + if (additionalInfo) { + this._updateSurveyLinkQueryString('additionalInfo', additionalInfo); + } + } + _getUserJourneys() { if (!this._aside.dataset.customerSatisfactionInputUserJourneys) { - console.error('Attempt to send Global Customer Satisfaction Input event failed. Value not found for User Journeys.'); + console.error( + 'Attempt to send Global Customer Satisfaction Input event failed. Value not found for User Journeys.' + ); return; } - const userJourneyStrings = this._aside.dataset.customerSatisfactionInputUserJourneys.split(','); - const sanitisedUserJourneyStrings = userJourneyStrings.map(string => string.trim().toLowerCase()); - const containsPermissibleUserJourneys = sanitisedUserJourneyStrings.every(string => { - return this._permissibleUserJourneys.includes(string); - }); + + const userJourneyStrings = + this._aside.dataset.customerSatisfactionInputUserJourneys.split(','); + const sanitisedUserJourneyStrings = userJourneyStrings.map(string => + string.trim().toLowerCase() + ); + const containsPermissibleUserJourneys = sanitisedUserJourneyStrings.every( + string => { + return this._permissibleUserJourneys.includes(string); + } + ); + if (containsPermissibleUserJourneys) { return sanitisedUserJourneyStrings.join(','); } - console.error('Attempt to send Global Customer Satisfaction Input event failed. One or more of the user journeys provided are not permissible values.'); + + console.error( + 'Attempt to send Global Customer Satisfaction Input event failed. One or more of the user journeys provided are not permissible values.' + ); + return false; } _dispatchDataLayerEvent(radioValue) { if (!window.dataLayer) { - console.error('Attempt to send Global Customer Satisfaction Input event failed. window.dataLayer does not exist.'); + console.error( + 'Attempt to send Global Customer Satisfaction Input event failed. window.dataLayer does not exist.' + ); + return; } + const userJourneys = this._getUserJourneys(); if (userJourneys && radioValue) { window.dataLayer.push({ @@ -65,7 +117,8 @@ class CustomerSatisfactionInput { event: 'survey.track', userJourneys: userJourneys, radioValue: radioValue, - additionalInfo: this._aside.dataset.customerSatisfactionInputAdditionalInfo || null + additionalInfo: + this._aside.dataset.customerSatisfactionInputAdditionalInfo || null }); } } @@ -81,22 +134,33 @@ class CustomerSatisfactionInput { event.preventDefault(); event.stopPropagation(); }); - ['click', 'keydown'].forEach(eventType => { + + const eventTypes = ['click', 'keydown']; + + // ['click', 'keydown'].forEach((eventType) => { + for (const eventType of eventTypes) { this._submitButton.addEventListener(eventType, event => { if (/Enter|Space/.test(event.key) || event.type === 'click') { event.preventDefault(); event.stopPropagation(); const validForm = this._validateForm(); + if (validForm) { - this._setSurveyLinkResponseRating((this._getCheckedRadioValue())); + this._setSurveyLinkResponseRating(this._getCheckedRadioValue()); + this._setSurveyLinkUserJourneys(this._getUserJourneys()); + this._setSurveyLinkAdditionalInfo( + this._aside.dataset.customerSatisfactionInputAdditionalInfo + ); this._dispatchDataLayerEvent(this._getCheckedRadioValue()); this._displayMessage(); + return; } + this._displayError(); } }); - }); + } } _validateForm() { @@ -106,7 +170,9 @@ class CustomerSatisfactionInput { } _displayError() { - if (this._form.classList.contains('c-customer-satisfaction-input--show-error')) { + if ( + this._form.classList.contains('c-customer-satisfaction-input--show-error') + ) { return; } this._form.classList.add('c-customer-satisfaction-input--show-error'); From daca8aedf72cb50230aecfff31018fe3d7f37ba4 Mon Sep 17 00:00:00 2001 From: Roman Seidelsohn Date: Fri, 10 Nov 2023 09:40:24 +0100 Subject: [PATCH 02/13] Add description of the new feature to the README --- .../packages/global-customer-satisfaction-input/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/toolkits/global/packages/global-customer-satisfaction-input/README.md b/toolkits/global/packages/global-customer-satisfaction-input/README.md index f8e4c5de4..133ee5df0 100644 --- a/toolkits/global/packages/global-customer-satisfaction-input/README.md +++ b/toolkits/global/packages/global-customer-satisfaction-input/README.md @@ -117,6 +117,10 @@ This is the url of the page the user is on. This is the rating that the user chose when they submitted the form. +**userJourneys** and **additionalInfo** + +These parameters will each be appended only if you set them when using the Handlebars template or the HTML generated by this component. They will contain the values you provide for each. + These data can be used in your reporting system to filter your survey responses. For example, in Survey Monkey you can configure custom variables with your survey so that these can be used in reporting analysis and queries. ### Projects that do not use Elements From 868ae47015e5270f46dfe9b9a76730656070ec65 Mon Sep 17 00:00:00 2001 From: Roman Seidelsohn Date: Fri, 10 Nov 2023 09:40:57 +0100 Subject: [PATCH 03/13] Delete duplicated section from the README and remove trailing spaces --- .../global-customer-satisfaction-input/README.md | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/toolkits/global/packages/global-customer-satisfaction-input/README.md b/toolkits/global/packages/global-customer-satisfaction-input/README.md index 133ee5df0..88a8c30ef 100644 --- a/toolkits/global/packages/global-customer-satisfaction-input/README.md +++ b/toolkits/global/packages/global-customer-satisfaction-input/README.md @@ -4,7 +4,7 @@ The Global Customer Satisfaction Input component is the frontend for an overall The component comprises a set of 5 pictographic radio inputs used to collect a satisfaction score from our customers. The user is able to submit one of the following scores: Awful, Bad, OK, Good, Great. -It is a JavaScript dependent component. When a user interacts with the component an event is dispatched to `window.dataLayer` allowing customer satisfaction score data and context data scraped from the page to be sent to Google Tag Manager and Google Cloud Big Query. +It is a JavaScript dependent component. When a user interacts with the component an event is dispatched to `window.dataLayer` allowing customer satisfaction score data and context data scraped from the page to be sent to Google Tag Manager and Google Cloud Big Query. ## Usage This documents how to implement this component on your website. If your project does not use Elements you can still use this component, see refer to the `Projects that do not use Elements` section below. @@ -42,7 +42,7 @@ Consume the component's Handlebars view template found in the `/view/` directory If you are unable to consume view templates in your project you can still use this component. Use the component demo to generate the HTML. This can be done as follows: -1. Edit the JSON data file found at `/demo/context.json` and define the data you need for your instance (see below Data section) +1. Edit the JSON data file found at `/demo/context.json` and define the data you need for your instance (see below Data section) 2. Run `npm run demo -- -p global-customer-satisfaction-input` 3. Copy the `