Repository navigation
fix: gate Fullstory capture on Osano Analytics consent - #7062
Merged
Merged
Conversation
Osano blocks fs.js on page load when a visitor has declined Analytics,
but it can't stop a script that's already running. A visitor who declined
mid-session kept being recorded until the next page load, and a visitor
who accepted mid-session wasn't recorded until then either. Capture also
depended on Osano recognizing Fullstory's script URL.
- Queue FS('init', { env: { captureOnStartup: false } }) right after the
snippet, so Fullstory never starts capture on its own.
- Read Osano's consent on load and on every osano-cm-consent-saved event:
start capture when Analytics is accepted, shut it down when it's
withdrawn, and restart it if it's granted again.
- Never start capture when osano.js is blocked, since there's no consent
to read.
- Add plugins/fullstory.test.js and run it from npm run test:plugins.
US visitors still get Osano's default of accepting Analytics on load, so
this doesn't change when their capture starts. That default is an Osano
dashboard setting.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WUv8r1UmXksNKFmsHaYoTF
cypress-documentation
|
||||||||||||||||||||||||||||||||||||||||
| Project |
cypress-documentation
|
| Branch Review |
osano/gate-fullstory-on-consent
|
| Run status |
|
| Run duration | 02m 02s |
| Commit |
|
| Committer | Jennifer Shehane |
| View all properties for this run ↗︎ | |
| Test results | |
|---|---|
|
|
0
|
|
|
0
|
|
|
0
|
|
|
0
|
|
|
427
|
| View all changes introduced in this branch ↗︎ | |
UI Coverage
32.82%
|
|
|---|---|
|
|
739
|
|
|
25
|
Accessibility
98.9%
|
|
|---|---|
|
|
2 critical
5 serious
4 moderate
1 minor
|
|
|
74
|
cypress-documentation
|
||||||||||||||||||||||||||||||||||||||||
| Project |
cypress-documentation
|
| Branch Review |
main
|
| Run status |
|
| Run duration | 02m 15s |
| Commit |
|
| Committer | Jennifer Shehane |
| View all properties for this run ↗︎ | |
| Test results | |
|---|---|
|
|
0
|
|
|
0
|
|
|
0
|
|
|
0
|
|
|
427
|
| View all changes introduced in this branch ↗︎ | |
UI Coverage
32.82%
|
|
|---|---|
|
|
738
|
|
|
25
|
Accessibility
98.91%
|
|
|---|---|
|
|
2 critical
6 serious
4 moderate
1 minor
|
|
|
152
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fullstory now starts capture only when Osano reports Analytics consent. It shuts down the moment a visitor withdraws consent and restarts if they grant it again, all without a page reload.
Why
Follow-up to #7061. While checking that Osano still blocks the new snippet's
fs.js?org=…address, we found:fs.jsloading after a decline (confirmed), but it can't stop a script that's already running. A visitor who declined through Cookie Preferences kept being recorded until the next page load.What changed
plugins/fullstory.js: a second head script runs right after the verbatim 2.1 snippet. It:FS('init', { env: { captureOnStartup: false } }), so Fullstory never starts on its own. The snippet's owninitcall merges with this one, per Fullstory's Configure Capture docs.Osano.cm.getConsent()on load and listens forosano-cm-consent-saved. When Analytics is accepted, it callsFS('start')(orFS('restart')after a shutdown). When Analytics is withdrawn, it callsFS('shutdown').osano.jsis blocked (by an ad blocker, for example), since there's no consent to read.FSbelongs to another script. The snippet backs off in that case and never sets_v.plugins/fullstory.test.js: 9 vitest tests: the gate's state changes, the no-Osano case, the foreignFSglobal case, and the plugin's org ID and production checks.package.json: addstest:fullstory-plugintotest:plugins.plugins/AGENTS.md: lists the new test.How this was tested
npm run test:plugins: all suites pass, including the 9 new tests. As a check that the tests can fail, removing theshutdowncall fails the withdraw/restart test.End to end with the real Osano script (
FULLSTORY_ORG_ID=test-org npm run build,npm run serve, headless Chromium,fs.jsstubbed), checking the calls queued onFS:initinit {captureOnStartup:false},startshutdownrestartinit {captureOnStartup:false}only, nostartcmp.osano.comblockedinit {captureOnStartup:false}only, nostartLint:
npm run lint:fixand Prettier are clean.Not tested: the real
fs.jsprocessing the queued calls. The test org isn't real, and the session's network doesn't reachedge.fullstory.com. The calls used are Fullstory's documented 2.1 API. After deploy, check that sessions still arrive in Fullstory, and that a session stops when you decline in Cookie Preferences.Notes for reviewers
osano.jsbut not Fullstory, that visitor used to be recorded and now isn't. That's deliberate: no consent signal means no capture.FULLSTORY_ORG_ID, andcypress.configblocks*fullstory.com, so the e2e suite never loads Fullstory. The unit tests cover the gate instead.Generated by Claude Code
Note
Medium Risk
Changes production analytics behavior (when Fullstory records) and injects new client-side consent logic; mistakes could under- or over-record sessions relative to policy.
Overview
Summary
Production Fullstory injection now runs a second head script after the 2.1 snippet that disables startup capture, reads Osano
cmconsent, and callsFS('start')/FS('restart')/FS('shutdown')when Analytics is accepted, re-accepted, or withdrawn—so consent changes apply without a full reload. If Osano is missing orFSis not the Fullstory snippet global, the gate does not start capture.Why
Osano only blocks
fs.json the next navigation, so visitors who declined in Cookie Preferences could keep recording until reload; accepting mid-session did not start capture until reload either. This follows up on work in #7061 by driving capture directly from Osano consent events instead of relying on script blocking alone.Notes for reviewers
plugins/fullstory.test.jscovers gate state transitions, no-Osano and foreign-FScases, and plugin head-tag behavior;npm run test:pluginsincludestest:fullstory-plugin.plugins/AGENTS.mddocuments the new test. Intentional product change: ifosano.jsis blocked (e.g. ad blocker) there is no consent signal, so capture does not start.Reviewed by Cursor Bugbot for commit 9696acc. Bugbot is set up for automated code reviews on this repo. Configure here.