@c15t/astro 3.0.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +86 -0
- package/SKILL.md +14 -0
- package/dist/api/handlers.js +91 -0
- package/dist/api/index.js +3 -0
- package/dist/api/init.js +10 -0
- package/dist/api/manifest-init.js +103 -0
- package/dist/api/manifest.js +10 -0
- package/dist/browser/iab.js +5 -0
- package/dist/browser/inline-scripts.js +47 -0
- package/dist/client.js +276 -0
- package/dist/index.js +5 -0
- package/dist/integration.js +170 -0
- package/dist/libs/cookies.js +9 -0
- package/dist/middleware-handler.js +31 -0
- package/dist/middleware.js +6 -0
- package/dist/mode.js +50 -0
- package/dist/server.js +291 -0
- package/dist/styles.css +2 -0
- package/dist/types.js +0 -0
- package/dist/ui/adapter.js +37 -0
- package/dist/ui/provider-props.js +12 -0
- package/dist/ui/react.js +34 -0
- package/dist/ui/svelte.js +36 -0
- package/dist/ui/vue.js +38 -0
- package/dist-types/api/handlers.d.ts +85 -0
- package/dist-types/api/index.d.ts +13 -0
- package/dist-types/api/init.d.ts +10 -0
- package/dist-types/api/manifest-init.d.ts +73 -0
- package/dist-types/api/manifest.d.ts +9 -0
- package/dist-types/browser/iab.d.ts +14 -0
- package/dist-types/browser/inline-scripts.d.ts +38 -0
- package/dist-types/client.d.ts +152 -0
- package/dist-types/index.d.ts +33 -0
- package/dist-types/integration.d.ts +53 -0
- package/dist-types/libs/cookies.d.ts +15 -0
- package/dist-types/middleware-handler.d.ts +35 -0
- package/dist-types/middleware.d.ts +20 -0
- package/dist-types/mode.d.ts +75 -0
- package/dist-types/server.d.ts +130 -0
- package/dist-types/types.d.ts +305 -0
- package/dist-types/ui/adapter.d.ts +122 -0
- package/dist-types/ui/provider-props.d.ts +37 -0
- package/dist-types/ui/react.d.ts +19 -0
- package/dist-types/ui/svelte.d.ts +21 -0
- package/dist-types/ui/vue.d.ts +19 -0
- package/docs/README.md +86 -0
- package/docs/assets/v3/brand-bar.png +0 -0
- package/docs/assets/v3/brand-card.png +0 -0
- package/docs/assets/v3/choice-wall.png +0 -0
- package/docs/assets/v3/mobile-card.png +0 -0
- package/docs/assets/v3/preferences.png +0 -0
- package/docs/customization/overview.md +45 -0
- package/docs/customization/recipes.md +79 -0
- package/docs/customization/slots.md +55 -0
- package/docs/customization/tokens.md +76 -0
- package/docs/customization/translations.md +49 -0
- package/docs/frameworks/astro/quickstart.md +186 -0
- package/docs/guides/consent-state.md +60 -0
- package/docs/guides/data-fetching.md +163 -0
- package/docs/guides/deployment-modes.md +63 -0
- package/docs/guides/troubleshooting.md +68 -0
- package/docs/guides/verify-consent.md +62 -0
- package/docs/integrations/adobe-analytics.md +294 -0
- package/docs/integrations/ahrefs-analytics.md +291 -0
- package/docs/integrations/amplitude.md +292 -0
- package/docs/integrations/building-integrations.md +47 -0
- package/docs/integrations/clearbit.md +291 -0
- package/docs/integrations/cloudflare-web-analytics.md +292 -0
- package/docs/integrations/crisp.md +294 -0
- package/docs/integrations/databuddy.md +311 -0
- package/docs/integrations/fathom-analytics.md +293 -0
- package/docs/integrations/google-maps.md +384 -0
- package/docs/integrations/google-tag-manager.md +306 -0
- package/docs/integrations/google-tag.md +305 -0
- package/docs/integrations/heap.md +292 -0
- package/docs/integrations/hightouch.md +293 -0
- package/docs/integrations/hotjar.md +292 -0
- package/docs/integrations/intercom.md +285 -0
- package/docs/integrations/linkedin-insights.md +291 -0
- package/docs/integrations/logrocket.md +293 -0
- package/docs/integrations/matomo-analytics.md +316 -0
- package/docs/integrations/meta-pixel.md +285 -0
- package/docs/integrations/microsoft-clarity.md +292 -0
- package/docs/integrations/microsoft-uet.md +291 -0
- package/docs/integrations/mixpanel-analytics.md +295 -0
- package/docs/integrations/openai-pixel.md +441 -0
- package/docs/integrations/overview.md +111 -0
- package/docs/integrations/pirsch.md +295 -0
- package/docs/integrations/plausible-analytics.md +295 -0
- package/docs/integrations/posthog.md +397 -0
- package/docs/integrations/promptwatch.md +291 -0
- package/docs/integrations/reddit-pixel.md +294 -0
- package/docs/integrations/rudderstack.md +328 -0
- package/docs/integrations/rybbit-analytics.md +296 -0
- package/docs/integrations/segment.md +292 -0
- package/docs/integrations/snapchat-pixel.md +293 -0
- package/docs/integrations/tiktok-pixel.md +291 -0
- package/docs/integrations/umami-analytics.md +295 -0
- package/docs/integrations/vercel-analytics.md +293 -0
- package/docs/integrations/x-pixel.md +291 -0
- package/docs/integrations/youtube.md +405 -0
- package/docs/upgrade-v3.md +334 -0
- package/package.json +184 -0
- package/src/components/branding.astro +152 -0
- package/src/components/consent-script.astro +34 -0
- package/src/components/iab-panel.astro +43 -0
- package/src/components/iab-prompt.astro +316 -0
- package/src/components/islands/iab-dialog-surface.svelte +15 -0
- package/src/components/islands/iab-dialog-surface.tsx +25 -0
- package/src/components/islands/iab-dialog-surface.vue +20 -0
- package/src/components/islands/panel-surface.svelte +57 -0
- package/src/components/islands/panel-surface.tsx +67 -0
- package/src/components/islands/panel-surface.vue +39 -0
- package/src/components/panel-trigger.astro +48 -0
- package/src/components/panel.astro +65 -0
- package/src/components/prompt-deferred.astro +54 -0
- package/src/components/prompt.astro +325 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Svelte dialog surface.
|
|
3
|
+
*
|
|
4
|
+
* Svelte 5 compiles to close to hand-written DOM code, so a Svelte island is
|
|
5
|
+
* the smallest way to get a real preference centre onto an Astro page
|
|
6
|
+
* without shipping a framework runtime to visitors who never open one.
|
|
7
|
+
* Mounting happens on the first open through `mount()`, so the import cost
|
|
8
|
+
* is paid only by people who click "Customize".
|
|
9
|
+
*
|
|
10
|
+
* The island itself is registered by `<ConsentDialog />` rather than
|
|
11
|
+
* imported here: a `.svelte` file can only be compiled by the consuming
|
|
12
|
+
* app's build, and keeping the specifier in the `.astro` component is what
|
|
13
|
+
* lets that build see it.
|
|
14
|
+
*
|
|
15
|
+
* The provider inside the island renders against the page runtime through
|
|
16
|
+
* its `runtime` prop, so there is one kernel per page no matter how many
|
|
17
|
+
* islands, scripts or frameworks read it.
|
|
18
|
+
*/
|
|
19
|
+
import type { ConsentDialogAdapter } from './adapter';
|
|
20
|
+
/** The Svelte 5 dialog surface implementation. */
|
|
21
|
+
export declare const svelteDialogAdapter: ConsentDialogAdapter;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Vue dialog surface.
|
|
3
|
+
*
|
|
4
|
+
* Same trade as the React adapter: a site already running Vue reuses that
|
|
5
|
+
* runtime for the preference centre instead of downloading Svelte for one
|
|
6
|
+
* dialog. Sites on neither should stay on the default.
|
|
7
|
+
*
|
|
8
|
+
* The island is mounted as its own Vue app rather than grafted onto the
|
|
9
|
+
* host app — Astro islands never share an app instance. The consent state
|
|
10
|
+
* lives on the page runtime, which the `c15tVue` plugin borrows: it builds
|
|
11
|
+
* no kernel of its own and disposes nothing.
|
|
12
|
+
*
|
|
13
|
+
* The island itself is registered by the integration rather than imported
|
|
14
|
+
* here: a `.vue` file can only be compiled by the consuming app's build,
|
|
15
|
+
* and only that build knows whether `@astrojs/vue` is present.
|
|
16
|
+
*/
|
|
17
|
+
import type { ConsentDialogAdapter } from './adapter';
|
|
18
|
+
/** The Vue 3 dialog surface implementation. */
|
|
19
|
+
export declare const vueDialogAdapter: ConsentDialogAdapter;
|
package/docs/README.md
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# @c15t/astro
|
|
2
|
+
|
|
3
|
+
> Astro v3 static and server integration, dialog adapters and runtime ownership.
|
|
4
|
+
|
|
5
|
+
These docs ship inside the package so coding agents can read them offline. Open the topic file you need from the list below — paths are relative to this file.
|
|
6
|
+
|
|
7
|
+
## Using these docs
|
|
8
|
+
|
|
9
|
+
These docs describe v3. Start with Inth hosted setup, identify the framework, router and deployment, then read its quickstart. Static sites can use Inth directly. Use page Markdown and package-bundled docs for targeted context. Verify scripts, rejection, reload and preferences; banner visibility alone is insufficient.
|
|
10
|
+
|
|
11
|
+
## Start here
|
|
12
|
+
|
|
13
|
+
- [Astro quickstart](./frameworks/astro/quickstart.md)
|
|
14
|
+
- [Customize your consent interface](./customization/overview.md): Choose presentation, theme tokens, slots or custom markup for the change you need.
|
|
15
|
+
- [Verify consent before shipping](./guides/verify-consent.md): Test requests, policy resolution, persistence, navigation and preference changes in a production build.
|
|
16
|
+
- [Upgrade to v3 policies](./upgrade-v3.md): Migrate policy configuration, consent records, callbacks, and custom transports to the v3 policy system.
|
|
17
|
+
|
|
18
|
+
## More documentation
|
|
19
|
+
|
|
20
|
+
[Documentation index](https://c15t.com/docs/llms.txt) · [Full Markdown context](https://c15t.com/llms-full.txt). Prefer the index and individual pages for focused tasks.
|
|
21
|
+
|
|
22
|
+
## Frameworks
|
|
23
|
+
|
|
24
|
+
- [Quickstart](./frameworks/astro/quickstart.md): Add c15t to static or server-rendered Astro pages and choose the framework used by preference dialogs.
|
|
25
|
+
|
|
26
|
+
## Guides
|
|
27
|
+
|
|
28
|
+
- [Understand consent state](./guides/consent-state.md): Distinguish policy resolution, effective permissions, explicit choices, notices and privacy signals.
|
|
29
|
+
- [Data fetching and transports](./guides/data-fetching.md): Choose cached manifests, backend init or offline policy resolution, and understand where consent records are saved.
|
|
30
|
+
- [Choose a deployment mode](./guides/deployment-modes.md): Choose who runs your consent backend, then select manifest, init or offline resolution for your deployment.
|
|
31
|
+
- [Troubleshoot consent](./guides/troubleshooting.md): Diagnose missing banners, early vendor requests, lost choices and hydration differences.
|
|
32
|
+
- [Verify consent before shipping](./guides/verify-consent.md): Test requests, policy resolution, persistence, navigation and preference changes in a production build.
|
|
33
|
+
|
|
34
|
+
## Customization
|
|
35
|
+
|
|
36
|
+
- [Customize your consent interface](./customization/overview.md): Choose presentation, theme tokens, slots or custom markup for the change you need.
|
|
37
|
+
- [Banner styling recipes](./customization/recipes.md): See real v3 components and reuse the exact theme configuration behind the examples.
|
|
38
|
+
- [Style component slots](./customization/slots.md): Target a specific c15t component part without replacing its markup or behavior.
|
|
39
|
+
- [Theme tokens and CSS](./customization/tokens.md): Style c15t with semantic tokens and use the stylesheet that matches your CSS tooling.
|
|
40
|
+
- [Copy and translations](./customization/translations.md): Change consent wording through i18n and test the complete prompt and preferences flow.
|
|
41
|
+
|
|
42
|
+
## Integrations
|
|
43
|
+
|
|
44
|
+
- [Adobe Analytics](./integrations/adobe-analytics.md): Configure Adobe Analytics with c15t v3, understand measurement permission and verify loading and revocation.
|
|
45
|
+
- [Ahrefs Analytics](./integrations/ahrefs-analytics.md): Configure Ahrefs Analytics with c15t v3, understand measurement permission and verify loading and revocation.
|
|
46
|
+
- [Amplitude](./integrations/amplitude.md): Configure Amplitude with c15t v3, understand measurement permission and verify loading and revocation.
|
|
47
|
+
- [Custom integrations](./integrations/building-integrations.md): Define loading, initialization and consent-change behavior for a vendor without a helper.
|
|
48
|
+
- [Clearbit](./integrations/clearbit.md): Configure Clearbit with c15t v3, understand marketing permission and verify loading and revocation.
|
|
49
|
+
- [Cloudflare Web Analytics](./integrations/cloudflare-web-analytics.md): Configure Cloudflare Web Analytics with c15t v3, understand measurement permission and verify loading and revocation.
|
|
50
|
+
- [Crisp](./integrations/crisp.md): Configure Crisp with c15t v3, understand functionality permission and verify loading and revocation.
|
|
51
|
+
- [Databuddy](./integrations/databuddy.md): Configure Databuddy's initial and updated consent state with c15t v3.
|
|
52
|
+
- [Fathom Analytics](./integrations/fathom-analytics.md): Configure Fathom Analytics with c15t v3, understand measurement permission and verify loading and revocation.
|
|
53
|
+
- [Google Maps](./integrations/google-maps.md): Prevent a map iframe from mounting before the required permission.
|
|
54
|
+
- [Google Tag](./integrations/google-tag.md): Configure gtag with c15t Consent Mode signals and understand its loading behavior.
|
|
55
|
+
- [Google Tag Manager](./integrations/google-tag-manager.md): Load GTM with c15t consent signals and verify the tags inside your container.
|
|
56
|
+
- [Heap](./integrations/heap.md): Configure Heap with c15t v3, understand measurement permission and verify loading and revocation.
|
|
57
|
+
- [Hightouch](./integrations/hightouch.md): Configure Hightouch with c15t v3, understand measurement permission and verify loading and revocation.
|
|
58
|
+
- [Hotjar](./integrations/hotjar.md): Configure Hotjar with c15t v3, understand measurement permission and verify loading and revocation.
|
|
59
|
+
- [Intercom](./integrations/intercom.md): Load the Intercom messenger with functionality permission and configure its region.
|
|
60
|
+
- [LinkedIn Insight Tag](./integrations/linkedin-insights.md): Configure LinkedIn Insight Tag with c15t v3, understand marketing permission and verify loading and revocation.
|
|
61
|
+
- [LogRocket](./integrations/logrocket.md): Configure LogRocket with c15t v3, understand measurement permission and verify loading and revocation.
|
|
62
|
+
- [Matomo Analytics](./integrations/matomo-analytics.md): Choose gated loading or Matomo consent signaling and configure the correct tracker endpoints.
|
|
63
|
+
- [Meta Pixel](./integrations/meta-pixel.md): Register the Meta Pixel under marketing permission and verify event calls after revocation.
|
|
64
|
+
- [Microsoft Clarity](./integrations/microsoft-clarity.md): Configure Microsoft Clarity with c15t v3, understand measurement permission and verify loading and revocation.
|
|
65
|
+
- [Microsoft UET](./integrations/microsoft-uet.md): Configure Microsoft UET with c15t v3, understand marketing permission and verify loading and revocation.
|
|
66
|
+
- [Mixpanel](./integrations/mixpanel-analytics.md): Configure Mixpanel with c15t v3, understand measurement permission and verify loading and revocation.
|
|
67
|
+
- [OpenAI Pixel](./integrations/openai-pixel.md): Configure the OpenAI Measurement Pixel for ChatGPT Ads with c15t v3, manage marketing permission and verify conversion delivery.
|
|
68
|
+
- [Overview](./integrations/overview.md): Find all c15t integrations for analytics, tag managers, advertising, chat and embedded content.
|
|
69
|
+
- [Pirsch](./integrations/pirsch.md): Configure Pirsch with c15t v3, understand measurement permission and verify loading and revocation.
|
|
70
|
+
- [Plausible Analytics](./integrations/plausible-analytics.md): Configure Plausible Analytics with c15t v3, understand measurement permission and verify loading and revocation.
|
|
71
|
+
- [PostHog](./integrations/posthog.md): Choose PostHog loading and cookieless behavior, configure the region, and synchronize v3 permissions.
|
|
72
|
+
- [Promptwatch](./integrations/promptwatch.md): Configure Promptwatch with c15t v3, understand measurement permission and verify loading and revocation.
|
|
73
|
+
- [Reddit Pixel](./integrations/reddit-pixel.md): Configure Reddit Pixel with c15t v3, understand marketing permission and verify loading and revocation.
|
|
74
|
+
- [RudderStack](./integrations/rudderstack.md): Gate the RudderStack browser SDK or map c15t categories to destination consent IDs.
|
|
75
|
+
- [Rybbit Analytics](./integrations/rybbit-analytics.md): Configure Rybbit Analytics with c15t v3, understand measurement permission and verify loading and revocation.
|
|
76
|
+
- [Segment](./integrations/segment.md): Configure Segment with c15t v3, understand measurement permission and verify loading and revocation.
|
|
77
|
+
- [Snapchat Pixel](./integrations/snapchat-pixel.md): Configure Snapchat Pixel with c15t v3, understand marketing permission and verify loading and revocation.
|
|
78
|
+
- [TikTok Pixel](./integrations/tiktok-pixel.md): Configure TikTok Pixel with c15t v3, understand marketing permission and verify loading and revocation.
|
|
79
|
+
- [Umami Analytics](./integrations/umami-analytics.md): Configure Umami Analytics with c15t v3, understand measurement permission and verify loading and revocation.
|
|
80
|
+
- [Vercel Analytics](./integrations/vercel-analytics.md): Configure Vercel Analytics with c15t v3, understand measurement permission and verify loading and revocation.
|
|
81
|
+
- [X Pixel](./integrations/x-pixel.md): Configure X Pixel with c15t v3, understand marketing permission and verify loading and revocation.
|
|
82
|
+
- [YouTube](./integrations/youtube.md): Gate YouTube embeds with c15t v3 in Next.js, TanStack Start, React, Nuxt, Vue, Astro, Svelte, SvelteKit or JavaScript.
|
|
83
|
+
|
|
84
|
+
## Reference
|
|
85
|
+
|
|
86
|
+
- [Upgrade to v3 policies](./upgrade-v3.md): Migrate policy configuration, consent records, callbacks, and custom transports to the v3 policy system.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Customize your consent interface
|
|
3
|
+
description: Choose presentation, theme tokens, slots or custom markup for the
|
|
4
|
+
change you need.
|
|
5
|
+
group: customization
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Start with the change you want
|
|
9
|
+
|
|
10
|
+
| Change | Use | Why |
|
|
11
|
+
| ----------------------------------------- | ----------------------------------- | ------------------------------------------------------------ |
|
|
12
|
+
| Banner shape or location | Presentation or banner props | Keeps policy actions and built-in layout behavior |
|
|
13
|
+
| Brand colors, radius, typography, spacing | Theme tokens | Changes related component parts together |
|
|
14
|
+
| One card, footer, title or button group | Component slots | Targets existing markup |
|
|
15
|
+
| Labels, descriptions or language | i18n configuration | Keeps banner and preferences copy consistent |
|
|
16
|
+
| A different component structure | Compound components where available | Retains the component behavior while changing markup |
|
|
17
|
+
| Your own interaction and markup | Headless APIs | You own rendering, focus behavior and policy action coverage |
|
|
18
|
+
|
|
19
|
+
Most brand changes need tokens and a few slots. Start there before opting out
|
|
20
|
+
of the stock styles. The [recipes](./recipes.md) show how each
|
|
21
|
+
choice affects a real banner.
|
|
22
|
+
|
|
23
|
+
## Keep behavior and appearance separate
|
|
24
|
+
|
|
25
|
+
Presentation controls the prompt's shape, position and blocking behavior.
|
|
26
|
+
Policy controls which actions and rights are required. Changing colors or button
|
|
27
|
+
order does not change a saved choice or policy scope.
|
|
28
|
+
|
|
29
|
+
A choice wall always blocks. Notices never block and cannot become a wall merely
|
|
30
|
+
because `variant: 'wall'` was requested. Preference dialogs remain centered;
|
|
31
|
+
prompt positioning does not move them. Required actions omitted from a custom
|
|
32
|
+
layout can be restored by the policy renderer.
|
|
33
|
+
|
|
34
|
+
## Use the adapter's configuration shape
|
|
35
|
+
|
|
36
|
+
React and Next.js accept provider `theme`, `presentation` and `components`
|
|
37
|
+
options. Vue and Nuxt expose their own shared configuration, including CSS
|
|
38
|
+
`tokens` and component slots. Svelte accepts its provider options and theme
|
|
39
|
+
contract. Astro serializes integration options and uses the selected adapter for
|
|
40
|
+
dialogs. Do not move a configuration object between frameworks without checking
|
|
41
|
+
the target types.
|
|
42
|
+
|
|
43
|
+
Read [tokens and CSS](./tokens.md),
|
|
44
|
+
[slots](./slots.md) or
|
|
45
|
+
[copy and translations](./translations.md) for the next step.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Banner styling recipes
|
|
3
|
+
description: See real v3 components and reuse the exact theme configuration
|
|
4
|
+
behind the examples.
|
|
5
|
+
group: customization
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## A branded floating card
|
|
9
|
+
|
|
10
|
+
This theme uses a green primary action and a four-pixel large radius. Accept and
|
|
11
|
+
Reject keep matching treatment. The component's required action behavior stays
|
|
12
|
+
intact.
|
|
13
|
+
|
|
14
|
+

|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
import { defineTheme } from '@c15t/ui/theme';
|
|
18
|
+
|
|
19
|
+
export const brandTheme = defineTheme({
|
|
20
|
+
colors: { primary: '#2f6f4e' },
|
|
21
|
+
consentActions: {
|
|
22
|
+
primary: { mode: 'filled', variant: 'primary' },
|
|
23
|
+
},
|
|
24
|
+
radius: { lg: '4px' },
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Install `@c15t/ui` to use `defineTheme` directly. Pass `brandTheme` as `theme` in
|
|
30
|
+
your existing React or Next.js provider options. Keep your Inth mode and script
|
|
31
|
+
configuration. The theme source above is also imported by the runnable example,
|
|
32
|
+
so the rendered result and the documentation use the same values.
|
|
33
|
+
|
|
34
|
+
## Change the shape without rebuilding the banner
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
<ConsentBanner variant="bar" />
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+

|
|
41
|
+
|
|
42
|
+
A bar changes the prompt's footprint. It does not change policy, grant categories
|
|
43
|
+
or require a headless implementation.
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
<ConsentBanner variant="wall" />
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+

|
|
50
|
+
|
|
51
|
+
A choice wall blocks interaction with the page. A notice never blocks; requesting
|
|
52
|
+
a wall for a notice falls back to a non-blocking presentation.
|
|
53
|
+
|
|
54
|
+
## Carry the theme into preferences
|
|
55
|
+
|
|
56
|
+

|
|
57
|
+
|
|
58
|
+
Keep a preferences link after the banner closes. Test a reject action, reopen
|
|
59
|
+
the dialog, change one category and save. A branded prompt is only part of the
|
|
60
|
+
consent flow.
|
|
61
|
+
|
|
62
|
+
## Check narrow screens
|
|
63
|
+
|
|
64
|
+

|
|
65
|
+
|
|
66
|
+
This example fits a 375-pixel viewport without horizontal overflow. Test your
|
|
67
|
+
own longest translations and font settings before adopting the same sizing.
|
|
68
|
+
|
|
69
|
+
## Run the examples
|
|
70
|
+
|
|
71
|
+
The source repository contains resettable Storybook examples under
|
|
72
|
+
`Docs / Customization`: Brand Card, Brand Bar and Choice Wall. Each demo uses
|
|
73
|
+
in-memory consent and no analytics; Reset example returns it to a fresh choice.
|
|
74
|
+
The screenshots above come from these v3 examples.
|
|
75
|
+
|
|
76
|
+
The stories are suitable for isolated iframe previews on a version-matched
|
|
77
|
+
Storybook deployment. Keep source code and the explanation on this page when
|
|
78
|
+
embedding them, so the recipe remains usable in Markdown and offline package
|
|
79
|
+
docs. A live preview must use the same v3 revision as the documentation.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Style component slots
|
|
3
|
+
description: Target a specific c15t component part without replacing its markup or behavior.
|
|
4
|
+
group: customization
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Use slots for local changes
|
|
8
|
+
|
|
9
|
+
In React and Next.js, put per-part attributes in `options.components`. This
|
|
10
|
+
fragment belongs in an existing provider's options:
|
|
11
|
+
|
|
12
|
+
```tsx
|
|
13
|
+
components: {
|
|
14
|
+
banner: {
|
|
15
|
+
card: { className: 'rounded-none shadow-none' },
|
|
16
|
+
title: { className: 'font-semibold' },
|
|
17
|
+
footer: { className: 'border-t' },
|
|
18
|
+
},
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
The class names above assume Tailwind. A slot can also receive `style` and other
|
|
23
|
+
supported element attributes. Keep shared colors and radius scales in tokens;
|
|
24
|
+
use slots when only one component part should change.
|
|
25
|
+
|
|
26
|
+
## Read attributes on the right element
|
|
27
|
+
|
|
28
|
+
The banner root carries `data-prompt`, `data-model`, `data-variant`,
|
|
29
|
+
`data-position` and `data-blocking`. Its child card does not inherit those HTML
|
|
30
|
+
attributes. In Tailwind, give the root `className: 'group'` and use
|
|
31
|
+
`group-data-[variant=bar]:...` on a child slot.
|
|
32
|
+
|
|
33
|
+
| React banner slot | Use |
|
|
34
|
+
| ---------------------------------- | ------------------------------------- |
|
|
35
|
+
| `root` | Position wrapper and state attributes |
|
|
36
|
+
| `cardShell` | Card sizing and branding container |
|
|
37
|
+
| `card` | Visible card |
|
|
38
|
+
| `header`, `title`, `description` | Heading and explanatory copy |
|
|
39
|
+
| `footer`, `actions`, `actionGroup` | Action layout |
|
|
40
|
+
| `rights`, `rightLink` | Preferences access controls |
|
|
41
|
+
| `overlay` | Backdrop for blocking presentation |
|
|
42
|
+
|
|
43
|
+
Buttons expose `data-action` for action-specific CSS. Test notices as well as
|
|
44
|
+
choice prompts; a notice uses acknowledgement rather than accept/reject.
|
|
45
|
+
|
|
46
|
+
## When to remove styles
|
|
47
|
+
|
|
48
|
+
`noStyle` removes the built-in component styling. It does not supply replacement
|
|
49
|
+
layout, spacing, focus indicators or responsive behavior. Use it when you intend
|
|
50
|
+
to own all of that work, not as the first response to a token that appears to do
|
|
51
|
+
nothing.
|
|
52
|
+
|
|
53
|
+
If the markup itself must change, use the adapter's compound components or
|
|
54
|
+
headless API. The slot objects above are the React contract; check Vue and Svelte
|
|
55
|
+
slot types before reusing them.
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Theme tokens and CSS
|
|
3
|
+
description: Style c15t with semantic tokens and use the stylesheet that matches
|
|
4
|
+
your CSS tooling.
|
|
5
|
+
group: customization
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Load the stock stylesheet once
|
|
9
|
+
|
|
10
|
+
React, Next.js and Svelte provide `styles.css`. Import the adapter's stylesheet
|
|
11
|
+
at the app's global entry point. Vue includes styles in its components; Astro
|
|
12
|
+
adds styles through its integration.
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
import 'c15t/react/styles.css';
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
The standard stylesheet places rules in `@layer components`. For Tailwind 3,
|
|
19
|
+
use the `styles.tw3.css` entry instead of the standard stylesheet, between the
|
|
20
|
+
components and utilities directives in your Tailwind entry:
|
|
21
|
+
|
|
22
|
+
```css
|
|
23
|
+
@tailwind base;
|
|
24
|
+
@tailwind components;
|
|
25
|
+
@import 'c15t/react/styles.tw3.css';
|
|
26
|
+
@tailwind utilities;
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Do not load both c15t stylesheet variants. For Tailwind 4 or unlayered CSS,
|
|
30
|
+
inspect layer order before reaching for `!important`.
|
|
31
|
+
|
|
32
|
+
## Set semantic values together
|
|
33
|
+
|
|
34
|
+
This React theme changes the brand color and large corner radius. Include
|
|
35
|
+
hover and foreground colors when overriding raw variables so the button remains
|
|
36
|
+
readable in each state.
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
import { defineTheme } from '@c15t/ui/theme';
|
|
40
|
+
|
|
41
|
+
export const theme = defineTheme({
|
|
42
|
+
colors: { primary: '#2f6f4e' },
|
|
43
|
+
radius: { lg: '4px' },
|
|
44
|
+
consentActions: {
|
|
45
|
+
primary: { variant: 'primary', mode: 'filled' },
|
|
46
|
+
dismiss: { variant: 'neutral', mode: 'stroke' },
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Install `@c15t/ui` if importing its theme helper directly. Pass `theme` in your
|
|
52
|
+
provider options. `consentActions` selects styling by action role. A per-action
|
|
53
|
+
entry overrides `primary`, which overrides `default`.
|
|
54
|
+
|
|
55
|
+
## Target a prompt with CSS
|
|
56
|
+
|
|
57
|
+
```css
|
|
58
|
+
[data-prompt][data-model='opt-in'] {
|
|
59
|
+
--c15t-primary: #2f6f4e;
|
|
60
|
+
--c15t-primary-hover: #24563c;
|
|
61
|
+
--c15t-text-on-primary: #fff;
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Use attributes exposed by the rendered component, not guessed class names.
|
|
66
|
+
Test the prompt and the preferences dialog separately because tokens scoped to
|
|
67
|
+
one prompt do not automatically reach a portaled dialog.
|
|
68
|
+
|
|
69
|
+
| Size variable | Default | Target |
|
|
70
|
+
| ----------------------------------- | ------- | ------------- |
|
|
71
|
+
| `--consent-banner-max-width` | `440px` | Floating card |
|
|
72
|
+
| `--consent-banner-widget-max-width` | `20rem` | Widget |
|
|
73
|
+
| `--consent-banner-wall-max-width` | `30rem` | Choice wall |
|
|
74
|
+
|
|
75
|
+
Test long translations and small screens after changing width or typography.
|
|
76
|
+
A compact banner must still fit the required actions.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Copy and translations
|
|
3
|
+
description: Change consent wording through i18n and test the complete prompt
|
|
4
|
+
and preferences flow.
|
|
5
|
+
group: customization
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Configure shared messages
|
|
9
|
+
|
|
10
|
+
Use provider `i18n` for wording that should stay consistent across components.
|
|
11
|
+
For React, this fragment belongs in `ConsentProvider` options:
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
i18n: {
|
|
15
|
+
messages: {
|
|
16
|
+
en: {
|
|
17
|
+
common: {
|
|
18
|
+
acceptAll: 'Accept all',
|
|
19
|
+
rejectAll: 'Reject optional',
|
|
20
|
+
customize: 'Choose cookies',
|
|
21
|
+
acknowledge: 'Got it',
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Supply the same message keys in each supported locale. A one-off component prop
|
|
29
|
+
such as `dismissButtonText` is useful for one banner; use translations for a
|
|
30
|
+
site-wide change. Astro's serializable integration options and Vue's module
|
|
31
|
+
configuration have their own types, so verify those shapes before copying a
|
|
32
|
+
React object.
|
|
33
|
+
|
|
34
|
+
## Write labels that describe the action
|
|
35
|
+
|
|
36
|
+
Accept and Reject record a choice. Customize opens preferences. Acknowledge
|
|
37
|
+
dismisses a notice and does not record a grant. Do not label a notice dismissal
|
|
38
|
+
"Accept all" or make a preferences link sound like it submits an opt-out.
|
|
39
|
+
|
|
40
|
+
The notice acknowledgement uses `common.acknowledge`, with `common.dismiss` as
|
|
41
|
+
a fallback for older translation bundles. Keep the displayed label and the
|
|
42
|
+
command's effect aligned.
|
|
43
|
+
|
|
44
|
+
## Test more than English
|
|
45
|
+
|
|
46
|
+
Try the longest labels you support at a narrow width, with browser zoom and
|
|
47
|
+
right-to-left text where relevant. Check banner actions, category descriptions,
|
|
48
|
+
legal links and the preferences save action. Translate explanations as well as
|
|
49
|
+
buttons so a visitor can make an informed choice.
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Quickstart
|
|
3
|
+
description: Add c15t to static or server-rendered Astro pages and choose the
|
|
4
|
+
framework used by preference dialogs.
|
|
5
|
+
group: frameworks
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
[Create an Inth project](https://inth.com) and use its backend endpoint in
|
|
9
|
+
this guide. Configure the project's policy rules and allowed app origins first.
|
|
10
|
+
|
|
11
|
+
## Choose the dialog framework
|
|
12
|
+
|
|
13
|
+
Astro renders the banner with native `.astro` components. Preference dialogs use
|
|
14
|
+
an on-demand Svelte, React or Vue island. Choose the framework your site already
|
|
15
|
+
uses; set `ui` explicitly. This example uses Svelte.
|
|
16
|
+
|
|
17
|
+
| Package manager | Command |
|
|
18
|
+
| :-------------- | :-------------------------------------------------------------------------- |
|
|
19
|
+
| npm | `npm install @c15t/astro @c15t/svelte @astrojs/svelte svelte @c15t/scripts` |
|
|
20
|
+
| pnpm | `pnpm add @c15t/astro @c15t/svelte @astrojs/svelte svelte @c15t/scripts` |
|
|
21
|
+
| yarn | `yarn add @c15t/astro @c15t/svelte @astrojs/svelte svelte @c15t/scripts` |
|
|
22
|
+
| bun | `bun add @c15t/astro @c15t/svelte @astrojs/svelte svelte @c15t/scripts` |
|
|
23
|
+
|
|
24
|
+
## Register consent-gated scripts
|
|
25
|
+
|
|
26
|
+
Include measurement and marketing categories in your policy for these vendors.
|
|
27
|
+
Remove any existing loaders for them so each script loads once.
|
|
28
|
+
|
|
29
|
+
Add your PostHog project key and X Pixel ID to `.env`:
|
|
30
|
+
|
|
31
|
+
```dotenv title=".env"
|
|
32
|
+
PUBLIC_POSTHOG_KEY=
|
|
33
|
+
PUBLIC_X_PIXEL_ID=
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Astro exposes these public values to the client through `import.meta.env`.
|
|
37
|
+
Restart development or rebuild for deployment after changing them.
|
|
38
|
+
An empty ID disables that integration. Create `src/example-scripts.ts`
|
|
39
|
+
using the helper below. It selects PostHog's EU region; change `region` to `'us'`
|
|
40
|
+
for a US project. PostHog waits for measurement permission and disables
|
|
41
|
+
cookieless capture. X Pixel waits for marketing permission.
|
|
42
|
+
|
|
43
|
+
```ts title="src/example-scripts.ts"
|
|
44
|
+
import { posthog } from '@c15t/scripts/posthog';
|
|
45
|
+
import { xPixel } from '@c15t/scripts/x-pixel';
|
|
46
|
+
|
|
47
|
+
export const createExampleScripts = (
|
|
48
|
+
posthogKey?: string,
|
|
49
|
+
xPixelId?: string
|
|
50
|
+
) => [
|
|
51
|
+
...(posthogKey
|
|
52
|
+
? [
|
|
53
|
+
posthog({
|
|
54
|
+
id: posthogKey,
|
|
55
|
+
initOptions: { cookieless_mode: 'never' },
|
|
56
|
+
loadMode: 'after-consent',
|
|
57
|
+
region: 'eu',
|
|
58
|
+
}),
|
|
59
|
+
]
|
|
60
|
+
: []),
|
|
61
|
+
...(xPixelId ? [xPixel({ pixelId: xPixelId })] : []),
|
|
62
|
+
];
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Create the client extension so script callbacks stay out of serialized server
|
|
66
|
+
configuration:
|
|
67
|
+
|
|
68
|
+
```ts title="src/consent-client.ts"
|
|
69
|
+
import type { C15tClientOptionsExtension } from '@c15t/astro';
|
|
70
|
+
import { createExampleScripts } from './example-scripts';
|
|
71
|
+
|
|
72
|
+
export default {
|
|
73
|
+
scripts: createExampleScripts(
|
|
74
|
+
import.meta.env.PUBLIC_POSTHOG_KEY,
|
|
75
|
+
import.meta.env.PUBLIC_X_PIXEL_ID,
|
|
76
|
+
),
|
|
77
|
+
} satisfies C15tClientOptionsExtension;
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Configure the integration
|
|
81
|
+
|
|
82
|
+
```js title="astro.config.mjs"
|
|
83
|
+
import { fileURLToPath } from 'node:url';
|
|
84
|
+
import { defineConfig } from 'astro/config';
|
|
85
|
+
import svelte from '@astrojs/svelte';
|
|
86
|
+
import c15t, { hosted } from '@c15t/astro';
|
|
87
|
+
|
|
88
|
+
const backendURL = process.env.C15T_BACKEND_URL;
|
|
89
|
+
if (!backendURL) throw new Error('Set C15T_BACKEND_URL');
|
|
90
|
+
|
|
91
|
+
export default defineConfig({
|
|
92
|
+
integrations: [
|
|
93
|
+
svelte(),
|
|
94
|
+
c15t({
|
|
95
|
+
mode: hosted({ url: backendURL }),
|
|
96
|
+
ui: 'svelte',
|
|
97
|
+
clientEntrypoint: fileURLToPath(new URL('./src/consent-client.ts', import.meta.url)),
|
|
98
|
+
}),
|
|
99
|
+
],
|
|
100
|
+
});
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Set `C15T_BACKEND_URL` to your backend's absolute URL, with policy rules and the
|
|
104
|
+
app origin configured. The integration serializes its options into browser
|
|
105
|
+
configuration. Keep secrets and callbacks out of this configuration.
|
|
106
|
+
|
|
107
|
+
For IAB policies in hosted mode, the browser fetches the vendor list from the
|
|
108
|
+
configured backend's `/init` endpoint after server rendering. That endpoint must
|
|
109
|
+
be publicly reachable from the app origin and allow its CORS requests without
|
|
110
|
+
server-only credentials. A private hosted backend needs a public same-origin
|
|
111
|
+
proxy that keeps authentication on the server.
|
|
112
|
+
|
|
113
|
+
In manifest mode, Astro injects a local init route and the browser fetches the
|
|
114
|
+
vendor list through that same-origin route. The backend does not need to allow
|
|
115
|
+
browser access or CORS requests from the app.
|
|
116
|
+
|
|
117
|
+
Past the manifest's `s-maxage` the injected routes and the middleware serve it
|
|
118
|
+
stale and refresh it in the background. On adapters that expose
|
|
119
|
+
`locals.runtime.ctx.waitUntil` (Cloudflare) the refresh is handed to it so it
|
|
120
|
+
is not cut short when the response is sent; nothing is needed from you. For
|
|
121
|
+
another lifetime API, pass `onBackgroundRevalidate` to
|
|
122
|
+
`createConsentRouteHandlers` or `resolveConsentContext`.
|
|
123
|
+
|
|
124
|
+
The framework integration must appear before `c15t()`. For React or Vue, install
|
|
125
|
+
that framework's Astro integration and c15t adapter, register the matching
|
|
126
|
+
integration, and set `ui: 'react'` or `ui: 'vue'`.
|
|
127
|
+
|
|
128
|
+
## Add the shared layout
|
|
129
|
+
|
|
130
|
+
```astro title="src/layouts/Base.astro"
|
|
131
|
+
---
|
|
132
|
+
import ConsentScript from '@c15t/astro/components/consent-script.astro';
|
|
133
|
+
import ConsentBanner from '@c15t/astro/components/consent-banner.astro';
|
|
134
|
+
import ConsentDialog from '@c15t/astro/components/consent-dialog.astro';
|
|
135
|
+
import ConsentDialogTrigger from '@c15t/astro/components/consent-dialog-trigger.astro';
|
|
136
|
+
---
|
|
137
|
+
<html lang="en">
|
|
138
|
+
<head>
|
|
139
|
+
<meta charset="utf-8" />
|
|
140
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
141
|
+
<title>My site</title>
|
|
142
|
+
<ConsentScript />
|
|
143
|
+
</head>
|
|
144
|
+
<body>
|
|
145
|
+
<slot />
|
|
146
|
+
<ConsentBanner />
|
|
147
|
+
<ConsentDialog />
|
|
148
|
+
<footer>
|
|
149
|
+
<ConsentDialogTrigger>Privacy settings</ConsentDialogTrigger>
|
|
150
|
+
</footer>
|
|
151
|
+
</body>
|
|
152
|
+
</html>
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Use this layout around each page. The integration supplies styles and the
|
|
156
|
+
shared browser runtime. `ConsentScript` prepares the client configuration and
|
|
157
|
+
color scheme. Do not create separate runtimes for each consent island.
|
|
158
|
+
|
|
159
|
+
## Static pages and request SSR
|
|
160
|
+
|
|
161
|
+
For prerendered pages, the middleware skips request prefetch. The browser
|
|
162
|
+
resolves consent against the external backend. This avoids treating the build
|
|
163
|
+
machine's cookies or geography as visitor state.
|
|
164
|
+
|
|
165
|
+
For server-rendered pages, keep your Astro server adapter and output settings.
|
|
166
|
+
The middleware can resolve request-specific state into `Astro.locals.c15t`.
|
|
167
|
+
Pass the prepared state through the supplied components instead of constructing
|
|
168
|
+
records from permission booleans.
|
|
169
|
+
|
|
170
|
+
`manifest()` mode can inject init and manifest endpoints and therefore needs a
|
|
171
|
+
server for those endpoints. Do not choose that setup for a purely static host
|
|
172
|
+
without providing the routes elsewhere. Nonserializable extensions belong in
|
|
173
|
+
the module selected by `clientEntrypoint`, not in `astro.config.mjs`.
|
|
174
|
+
|
|
175
|
+
## Verify navigation and loading
|
|
176
|
+
|
|
177
|
+
Test the built output, including a full page load and any navigation through
|
|
178
|
+
Astro's `ClientRouter`. Open preferences twice and check the runtime retains the
|
|
179
|
+
current choice. The dialog should reuse the selected framework, not load a
|
|
180
|
+
second adapter. Follow [verification](../../guides/verify-consent.md) for rejection,
|
|
181
|
+
reload and script requests.
|
|
182
|
+
|
|
183
|
+
## Run the complete example
|
|
184
|
+
|
|
185
|
+
Try the [runnable example](https://c15t.com/docs/examples) with PostHog, X Pixel, a consent-gated
|
|
186
|
+
YouTube video and a persistent preferences control. Use it to test rejection, permission changes and reloads.
|