@laioutr/app-onetrust
v1.4.0
Published
Laioutr integration with OneTrust consent management
Readme
OneTrust
Laioutr App integrating OneTrust consent management using Nuxt.
See laioutr.com for more information about Laioutr.
Features
- Feeds OneTrust consent into Laioutr's consent store as an SSR-correct
ConsentAdapter - One OneTrust script per market, resolved per request from the host
- Reads the
OptanonConsentcookie during SSR, so returning visitors get a correct first paint - Catches consent changes that fire before hydration via an inline
<head>bootstrap - Build-time validation of the per-market configuration
- Stays out of the Studio editor: no SDK or banner loads there, and every purpose reads as granted
Configuration
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@laioutr/app-onetrust'],
'@laioutr/app-onetrust': {
// A string applies to every market; a record maps `RcMarket.id` to its script.
scriptId: {
d6b03ihh228s8e4i35og: '10378097-4355-4435-be22-e07c5874eac9', // germany
d7c14jii339t9f5j46ph: '78ce031e-aa89-4c18-9b0a-315b795b7ab9', // france
},
},
});| Option | Default | Purpose |
| --- | --- | --- |
| scriptId | — | OneTrust script ID. String or RcMarket.id → ID record. Required. |
| cdnHost | cdn.cookielaw.org | OneTrust CDN host, without scheme. Check CDNLocation in your domain JSON. |
| documentLanguage | true | Emit data-document-language="true" so the banner follows <html lang>. |
| groupMapping | see below | OneTrust group ID → consent purpose, merged over the defaults. |
OneTrust issues one script per website domain you register with them, and calls
it a "domain script" — that is the UUID you copy out of their admin, and it
renders into data-domain-script. This app keys those IDs by market rather
than by domain, because Laioutr resolves the market from the request host.
Keys are RcMarket.id, not slug — slugs are editable in Cockpit, and a rename
would silently detach a market from its script. A market with no entry gets no
consent banner at all; there is no fallback to another market's script, because
OneTrust scripts are domain-bound.
A market serving more than one host needs one OneTrust script per host, which this option cannot express — configure the market's additional hosts as their own markets, or raise it if you hit the case.
Local development
A production script ID is bound to the domain it is registered for, and OneTrust scopes its
consent cookies to that domain. On localhost the browser rejects those writes, so
OptanonAlertBoxClosed never lands: hasDecision() stays false and the banner never dismisses,
whatever the visitor clicks. Every answer reads as "has not answered".
Append -test to the script ID for local work. OneTrust serves a TEST variant of the same script,
carrying the same geolocation rules and group configuration without the domain binding:
scriptId: '019aa652-28d4-7cb8-928e-29e4a2e8f099-test',Ship the ID without the suffix. Confirm which variant is loaded by reading
data-domain-script in the rendered HTML, or ScriptType in
https://cdn.cookielaw.org/consent/<id>/<id>.json.
Group mapping
| OneTrust group | Consent purpose |
| --- | --- |
| C0001 Strictly Necessary | necessary |
| C0002 Performance | analytics |
| C0003 Functional | functional |
| C0004 Targeting | advertising, personalization |
| C0005 Social Media | — |
| anything else | — |
The defaults reproduce what OneTrust's own Google Consent Mode integration
signals. Read your domain JSON to confirm: GCAnalyticsStorage is C0002, and
GCAdStorage, GCAdUserData and GCAdPersonalization are all C0004. That is
why C0004 grants two purposes — @laioutr-app/gtm derives ad_personalization
from personalization, so granting only advertising would deny ad
personalization to a visitor OneTrust considers to have allowed it.
The two ad purposes cannot diverge under the stock groups. OneTrust models a
single Targeting group, so no visitor state grants advertising while denying
personalization. Separating them takes a tenant-side group mapped explicitly:
groupMapping: {
C0004: 'advertising',
C0007: 'personalization', // a custom group your OneTrust tenant defines
},C0005 grants nothing, which is also what OneTrust does — it maps Social Media
to no Google signal. Accepting social-media cookies alone therefore reports
exactly as accepting nothing, on both paths.
A group absent from the mapping grants nothing and warns in dev. Map it to an empty array to say that is deliberate and silence the warning.
Tenants that rename or add groups override by ID. An array value grants several purposes from one group:
'@laioutr/app-onetrust': {
scriptId: '…',
groupMapping: {
C0002: ['analytics', 'functional'], // a group that straddles both
C0006: [], // known, and deliberately gates nothing
C0007: 'advertising', // a custom group
},
},Check the group names in your tenant before trusting the defaults: a group
called "Analytics & Functional" needs the array form, because the default maps
C0002 to analytics alone.
Google Consent Mode
This app never signals Google. It reports purposes to the consent store, and
@laioutr-app/gtm turns those into gtag('consent','update') — advertising
drives ad_storage and ad_user_data, personalization drives
ad_personalization and personalization_storage, analytics drives
analytics_storage, and functional drives functionality_storage.
If OneTrust's own Consent Mode integration is enabled for your domain script
(GCEnable in the domain JSON), set consentUpdates: 'external' on
@laioutr-app/gtm so the two do not both push gtag('consent','update'). The
inline Consent Mode default stays with the GTM app either way.
If OneTrust's Consent Mode is off, leave the GTM app on its 'store' default.
Note that the two paths are not identical even with matching group mappings:
OneTrust leaves any signal mapped to DNAC unsent, where the GTM app always
emits a complete update. personalization_storage is the usual case — DNAC in
most tenants, and granted by C0004 here.
Auto-blocking
This app does not emit otAutoBlock.js and offers no option to. OneTrust's
auto-blocker rewrites <script> tags to type="text/plain", which rewrites
Nuxt's own bundle and breaks hydration. Gate third-party scripts through the
consent store instead.
Quick Setup
Follow the Laioutr NPM Guide for connecting to npm.laioutr.cloud.
pnpm installnpx @laioutr/cli project fetch-rc --project <organization slug>/<project slug> --secret <project secret key>- This will load thelaioutrrc.jsonfile with the current remote project configuration.pnpm dev:prepare
That's it! You can now use OneTrust in your Laioutr Frontend ✨
You can find a thorough guide on getting started with Laioutr development in our developer guide.
Linting and Formatting
We use ESLint and Prettier to lint and format the code. This repository contains opinionated configurations for both tools. You can, of course, replace them with your own configurations.
Publishing
To publish a new version, run pnpm release. This will:
- Run the tests
- Update the changelog
- Publish the package to npmjs.org
- Push the changes to the repository
Contribution
Follow the setup guide to get started.
