Repository navigation
Keep page feedback from readers who decline cookies - #480
eugenia-scandit wants to merge 4 commits into
Conversation
|
| ): Promise<boolean> { | ||
| if (!endpoint) return false; | ||
| try { | ||
| await fetch(endpoint, { |
There was a problem hiding this comment.
This needs a privacy/consent review: the disclosure no longer matches where the data goes. For a reader who declined cookies, this sends the comment, page URL and title to script.google.com, and the request carries their IP and user agent. That's a different processor and different storage (a spreadsheet) than the consent banner covers. The widget's note (index.tsx:376) still says the comment is "sent to our analytics tool with this page's address", which is no longer accurate on this path.
There was a problem hiding this comment.
Partly addressed, still open: this needs a privacy/consent sign-off.
The disclosure now matches the destination (7c8da0b, 5507dce): on the fallback path, the note says the comment, the vote and the page's address and title go to a Google Apps Script form that adds them to a spreadsheet, and that the request carries the browser's IP address and user agent. On the analytics path, the note is unchanged.
What code can't settle: a reader who declines the cookie banner is exactly who the fallback sends to. That's the point of this PR, so someone responsible for privacy and consent needs to confirm it's acceptable before this ships.
| // Set from the environment so a redeploy of the Web App (which changes the | ||
| // URL) needs no code change, and so a fork or a preview build does not | ||
| // silently post into the production sheet. | ||
| feedbackEndpoint: process.env.DOCS_FEEDBACK_ENDPOINT ?? "", |
There was a problem hiding this comment.
No build sets DOCS_FEEDBACK_ENDPOINT or DOCS_FEEDBACK_TOKEN. build-docs.yml (line 61) and docs-preview.yml run yarn build with no env block, so in production this is '', sendDirectFeedback returns false, and the fallback ships turned off. Please add the variables (as secrets or vars) to the deploy workflow, or this PR has no effect.
There was a problem hiding this comment.
Still open: the variables don't reach production yet.
I added DOCS_FEEDBACK_ENDPOINT (repo variable) and DOCS_FEEDBACK_TOKEN (repo secret) to the build step of build-docs.yml, for main only, and previews never get them (docs-preview.yml, and docusaurus.config.ts forces both to empty when preview_build is set). But build-docs.yml only builds and tests; nothing in this repo deploys the live site. So the pipeline that builds production must set these two variables too, or the fallback stays off. Who owns that pipeline? Until it's configured, merging this changes nothing for readers.
There was a problem hiding this comment.
Thanks, and sorry: my original comment pointed you at the wrong workflow. docs.scandit.com is built and published by generate-docusaurus-documentation-production in the data-capture-sdk GitLab project, on an hourly schedule. It clones main here and runs npm run build.
I opened a GitLab MR that passes the two variables to that job only: https://gitlab.scandit.com/mobile/data-capture-sdk/-/merge_requests/39858
- It maps
DOCS_FEEDBACK_ENDPOINT_PRODandDOCS_FEEDBACK_TOKEN_PRODto the namesdocusaurus.config.tsreads. The staging job runs the same script, so it doesn't get them and can't post into the production sheet. - A GitLab maintainer still has to create those two CI/CD variables. Ideally do that before this PR merges: the production job skips the build while the docs commit is unchanged, so variables added later only take effect with the next commit to
main. - The
env:block inbuild-docs.ymldoesn't affect production. Keeping it is fine, but the comment above it shouldn't suggest it's what turns the fallback on. Dropping it would also let you remove the GitHub repo variable and secret.
I'll leave this thread open until the GitLab side is configured.
The feedback widget sends votes and comments to PostHog, which only loads after a reader accepts cookies. A reader who declines and then writes a comment currently leaves no trace of it. When PostHog refuses the capture, the comment is now posted to a configurable endpoint instead (an Apps Script Web App that appends it to a spreadsheet). It is sent only when PostHog refused, never alongside a successful capture, so nothing is recorded twice. The payload is the four fields the widget already sends (URL, title, vote, comment), with no identifier. The vote stays three-valued: a missing vote is sent as null, not as "not helpful". The endpoint and token come from DOCS_FEEDBACK_ENDPOINT and DOCS_FEEDBACK_TOKEN at build time. Both default to empty, which disables the fallback and leaves the widget behaving exactly as before. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The analytics helper now reports why a capture did not happen: PostHog not loaded, the reader opted out, or PostHog threw. The boolean helper other components use keeps its exact behaviour. The feedback widget posts a comment to the fallback endpoint only when PostHog is not loaded; an opted-out reader's comment is never sent anywhere. The note under the comment box now says where a comment will go before the reader sends it. When the fallback applies, it names the Google Apps Script form and spreadsheet, the page address and title, and that the request carries the browser's IP address and user agent. Submitting is guarded against a second send while one is in flight, and Send is marked disabled meanwhile. After the request settles, the current outcome is read from a ref, and nothing updates the widget if it has unmounted. Failure and success copy follow the path taken: a PostHog refusal keeps the "analytics is turned off or blocked" text; a failed fallback request says the connection failed or was blocked. Because the fallback uses no-cors and cannot see the response, its thanks says only that the note was sent. The endpoint and token are passed to the build of the main branch only. Pull-request builds get empty values, and preview builds force the fallback off in the config. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Otherwise the vote could also reach PostHog if the reader accepted cookies a few seconds later, and be recorded twice. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
9c8795e to
20aa16d
Compare
The page feedback widget ("Was this page helpful?") sends votes and comments to PostHog, which only loads after a reader accepts cookies. A reader who declines and then writes a comment currently leaves no trace of it.
What
null, never as "not helpful".no-corswith atext/plainbody, because an Apps Script Web App doesn't answer a CORS preflight. The response is opaque, so this reports that the request was sent, not that it arrived. The widget's copy already promises only "sent".DOCS_FEEDBACK_ENDPOINTandDOCS_FEEDBACK_TOKENat build time (customFieldsindocusaurus.config.ts). Both default to empty, which disables the fallback; with them unset, the widget behaves exactly as today. The token ships in the client bundle, so it only deters drive-by scanners; the receiving script must validate and rate-limit.Before this does anything in production
DOCS_FEEDBACK_ENDPOINTandDOCS_FEEDBACK_TOKENmust be set in the production build environment.Checks
npm run buildpasses;tscis clean.🤖 Generated with Claude Code