diff --git a/gulp-tasks/test.js b/gulp-tasks/test.js index 4caeb11bfc0..8ae29a5d36b 100644 --- a/gulp-tasks/test.js +++ b/gulp-tasks/test.js @@ -215,7 +215,7 @@ function parseJSON(filename, contents) { try { return JSON.parse(contents); } catch (ex) { - let msg = `Unable to parse JSON: ${ex.message}`; + const msg = `Unable to parse JSON: ${ex.message}`; logError(filename, null, msg, ex); } return null; @@ -573,6 +573,7 @@ gulp.task('test', ['test:travis-init'], function() { gutil.log(' ', chalk.cyan('--ignorePermissions'), 'Skips permission check'); gutil.log(' ', chalk.cyan('--ignoreLastUpdated'), 'Skips wf_updated_on'); gutil.log(' ', chalk.cyan('--ignoreCommentWidget'), 'Skips comment widget'); + gutil.log(' ', chalk.cyan('--ignoreHelpfulWidget'), 'Skips helpful widget'); gutil.log(' ', chalk.cyan('--ignoreTemplateTags'), 'Skips template tag check ({{)'); gutil.log(' ', chalk.cyan('--ignoreMissingFeedWidget'), @@ -591,6 +592,7 @@ gulp.task('test', ['test:travis-init'], function() { global.WF.options.ignoreLastUpdated = true; global.WF.options.ignoreTemplateTags = true; global.WF.options.ignoreCommentWidget = true; + global.WF.options.ignoreHelpfulWidget = true; global.WF.options.ignoreMissingFeedWidget = true; global.WF.options.hideIgnored = true; global.WF.options.skipTypos = true; @@ -607,13 +609,13 @@ gulp.task('test', ['test:travis-init'], function() { // Test master if (global.WF.options.testMaster) { - let msg = `${chalk.cyan('--testMaster')} was used.`; + const msg = `${chalk.cyan('--testMaster')} was used.`; gutil.log(chalk.bold.blue(' Option:'), msg); } // Test all files if (global.WF.options.testAll) { - let msg = `${chalk.cyan('--testAll')} was used.`; + const msg = `${chalk.cyan('--testAll')} was used.`; gutil.log(chalk.bold.blue(' Option:'), msg); } @@ -625,7 +627,7 @@ gulp.task('test', ['test:travis-init'], function() { // Supress ESLinter if (global.WF.options.ignoreESLint) { - let msg = `${chalk.cyan('--ignoreESLint')} was used.`; + const msg = `${chalk.cyan('--ignoreESLint')} was used.`; gutil.log(chalk.bold.blue(' Option:'), msg); } else { esLintConfig = parseJSON(ESLINT_RC_FILE, readFile(ESLINT_RC_FILE)); @@ -633,7 +635,7 @@ gulp.task('test', ['test:travis-init'], function() { // Supress wf_blink_components warnings if (global.WF.options.ignoreBlink) { - let msg = `${chalk.cyan('--ignoreBlink')} was used.`; + const msg = `${chalk.cyan('--ignoreBlink')} was used.`; gutil.log(chalk.bold.blue(' Option:'), msg); } else { opts.blinkComponents = parseJSON(BLINK_COMPONENTS_FILE, @@ -642,21 +644,21 @@ gulp.task('test', ['test:travis-init'], function() { // Supress max line length warnings if (global.WF.options.ignoreMaxLen) { - let msg = `${chalk.cyan('--ignoreMaxLen')} was used.`; + const msg = `${chalk.cyan('--ignoreMaxLen')} was used.`; gutil.log(chalk.bold.blue(' Option:'), msg); opts.enforceLineLengths = false; } // Supress markdown script warnings if (global.WF.options.ignoreScript) { - let msg = `${chalk.cyan('--ignoreScript')} was used.`; + const msg = `${chalk.cyan('--ignoreScript')} was used.`; gutil.log(chalk.bold.blue(' Option:'), msg); opts.ignoreScriptTags = true; } // Supress file size warnings if (global.WF.options.ignoreFileSize) { - let msg = `${chalk.cyan('--ignoreFileSize')} was used.`; + const msg = `${chalk.cyan('--ignoreFileSize')} was used.`; gutil.log(chalk.bold.blue(' Option:'), msg); opts.ignoreFileSize = true; } @@ -671,11 +673,18 @@ gulp.task('test', ['test:travis-init'], function() { // Supress missing comment widget warnings if (global.WF.options.ignoreCommentWidget) { - let msg = `${chalk.cyan('--ignoreCommentWidget')} was used.`; + const msg = `${chalk.cyan('--ignoreCommentWidget')} was used.`; gutil.log(chalk.bold.blue(' Option:'), msg); opts.ignoreMissingCommentWidget = true; } + // Supress missing helpful widget warnings + if (global.WF.options.ignoreHelpfulWidget) { + const msg = `${chalk.cyan('--ignoreHelpfulWidget')} was used.`; + gutil.log(chalk.bold.blue(' Option:'), msg); + opts.ignoreMissingHelpfulWidget = true; + } + // Supress missing feed widget checks if (global.WF.options.ignoreMissingFeedWidget) { const msg = `${chalk.cyan('--ignoreMissingFeedWidget')} was used.`; @@ -685,21 +694,21 @@ gulp.task('test', ['test:travis-init'], function() { // Supress last updated warnings if (global.WF.options.ignoreLastUpdated) { - let msg = `${chalk.cyan('--ignoreLastUpdated')} was used.`; + const msg = `${chalk.cyan('--ignoreLastUpdated')} was used.`; gutil.log(chalk.bold.blue(' Option:'), msg); opts.lastUpdateMaxDays = false; } // Supress template tag ({{}}) checks if (global.WF.options.ignoreTemplateTags) { - let msg = `${chalk.cyan('--ignoreTemplateTags')} was used.`; + const msg = `${chalk.cyan('--ignoreTemplateTags')} was used.`; gutil.log(chalk.bold.blue(' Option:'), msg); opts.ignoreTemplateTags = true; } // Hide ignored file warning if (global.WF.options.hideIgnored) { - let msg = `${chalk.cyan('--hideIgnored')} was used.`; + const msg = `${chalk.cyan('--hideIgnored')} was used.`; gutil.log(chalk.bold.blue(' Option:'), msg); opts.hideIgnored = true; } @@ -735,7 +744,7 @@ gulp.task('test', ['test:travis-init'], function() { })); }) .catch(function(ex) { - let msg = `A critical gulp task exception occurred: ${ex.message}`; + const msg = `A critical gulp task exception occurred: ${ex.message}`; logError('gulp-tasks/test.js', null, msg, ex); }) .then(printSummary) diff --git a/gulp-tasks/tests/validateContent.js b/gulp-tasks/tests/validateContent.js index ee040723db0..56dc2044bce 100644 --- a/gulp-tasks/tests/validateContent.js +++ b/gulp-tasks/tests/validateContent.js @@ -259,6 +259,21 @@ function test(filename, contents, options) { }); } + // Warn on missing "was this page helpful?" widget + if (!options.ignoreHelpfulWidget) { + const reHelpful = /^{%\s?include "web\/_shared\/helpful\.html"\s?%}/m; + const rePath = /src\/content\/.+?\//; + if (rePath.test(filename)) { + if (!reHelpful.test(contents)) { + const position = {line: getLineNumber(contents, contents.length - 1)}; + const msg = + 'Consider adding a "was this page helpful?" widget to your page: ' + + 'https://developers.google.com/web/resources/widgets#helpful'; + logWarning(msg, position); + } + } + } + // Warn on missing comment widgets if (!options.ignoreMissingCommentWidget) { const reComment = /^{%\s?include "comment-widget\.html"\s?%}/m; diff --git a/src/content/en/resources/images/helpfuldata.png b/src/content/en/resources/images/helpfuldata.png new file mode 100644 index 00000000000..33270d40b36 Binary files /dev/null and b/src/content/en/resources/images/helpfuldata.png differ diff --git a/src/content/en/resources/images/red.png b/src/content/en/resources/images/red.png new file mode 100644 index 00000000000..c09cea3960d Binary files /dev/null and b/src/content/en/resources/images/red.png differ diff --git a/src/content/en/resources/widgets.md b/src/content/en/resources/widgets.md index 0b66e6c5f89..f237718a693 100644 --- a/src/content/en/resources/widgets.md +++ b/src/content/en/resources/widgets.md @@ -2,7 +2,7 @@ project_path: /web/_project.yaml book_path: /web/resources/_book.yaml description: Widgets you can use to simplify your writing and development -{# wf_updated_on: 2018-02-05 #} +{# wf_updated_on: 2018-09-25 #} {# wf_published_on: 2016-09-13 #} {# wf_blink_components: N/A #} @@ -216,52 +216,58 @@ automatically maintain a 16:9 ratio. [common-links]: https://github.com/google/WebFundamentals/blob/master/src/content/en/_common-links.md -## Inline Feedback {: #inline-feedback } +## Add the "was this page helpful?" widget to your docs {: #helpful } -Gain more feedback on your doc by asking your readers yes / no questions. +Note: This widget is intended for the Google Web DevRel team. -### Example +Want to find out if readers actually find your docs useful? Add the "was this page helpful?" +widget to your docs. -See [Get Started Debugging JS][inline feedback example] for examples. Each of -the questions at the bottom of the sections use the Inline Feedback widget. +![The "was this page helpful?" widget](images/red.png) -[inline feedback example]: /web/tools/chrome-devtools/javascript/ +### Step 1: Add the widget to your page {: #helpful1 } -### Usage +1. Open your doc in a code editor. +1. Put the following code at the bottom of your page. -1. Make a directory called `_feedback` near the doc that'll include the feedback. -2. If you want to include a question before your buttons, then copy - `/src/content/en/tools/chrome-devtools/javascript/_feedback/7.html` into - your `_feedback` directory. Else, copy `.../1.html`. -2. Copy `/src/content/en/tools/chrome-devtools/javascript/_feedback/1.html` - into your `_feedback` directory. -3. Modify all of the variables to suit your question. All variables except - `question` are required. -4. Include `_feedback/1.html` into your doc, like this: +
## Feedback {: #feedback .hide-from-toc }
 
-
-{% include "web/path/to/_feedback/1.html" %}
-
+ \{% include "web/_shared/helpful.html" %\}
+ +The widget reports your data to Google Analytics as an [event][event]{:.external}. +The category of the event is `Helpful`. The label is the page's absolute path. The value +is `0` if the user clicks **No** (the doc was not helpful) or `1` if the user clicks +**Yes** (the doc was helpful). + +[event]: https://developers.google.com/analytics/devguides/collection/analyticsjs/events + +### Step 2: Wait {: #helpful2 } + +Once the widget is live on your page, you'll probably need to wait a while before you can derive +any meaning from the data. The more responses you get, the more confident you can be that the +data actually represents the sentiment of your users. + +### Step 3: Access the data {: #helpful3 } + +1. Request access to the **Web Fundamentals** site data on Google Analytics. +1. Open [Google Analytics](https://analytics.google.com). +1. Go to Behavior > Events > Overview. +1. Under **Events Category** select **Helpful**. If you can't see **Helpful**, click **view full report** and find it there. +1. For **Primary Dimension** select **Label**. -Path must always start with relative reference to `web/`. This -is just how the `include` tag works. +The **Total Events** column represents the total number of times that someone clicked **Yes** or **No**. +The **Avg. Value** column represents the average sentiment. For example, if 100 people responded, and +the average value is `0.75`, that means that 75 out of 100 people clicked **Yes** (the page is helpful). -Other stuff: +!["Was this page helpful?" data in Google Analytics](images/helpfuldata.png) -* The widget is hard-coded (and styled) to expect a success / - fail scenario. It won't make sense in other contexts. -* Can be used more than once on a doc! -* Doesn't work on Web Fundamentals' local development - server, because that server is just an approximation of - DevSite's real capabilities. You'll see all of the variables - printed on the page. +### Step 4: Interpret and act on the data {: #helpful4 } -### Viewing data +* If your page is getting low ratings, take a look at it and think about how you can improve it. + Make that change, and then check back after a while to see if your rating improved. +* If your page is getting high ratings and you think you know why, share this knowledge with the + rest of the team. We can conduct experiments to see if this change reproducibly improves page ratings. -Note: only relevant to users who have access to Web Fundamentals' -analytics data. +## Feedback {: #feedback .hide-from-toc } -See Google Analytics > Behavior > Events. When the user clicks "fail", -a value of 0 is sent for this label. When user clicks "success", a value -of 1 is sent. So, a value of 1 means that users are always clicking your -"success" button. +{% include "web/_shared/helpful.html" %}