@reform-digital/cookie-flow 1.3.7 → 2.0.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/README.md +798 -729
- package/package.json +22 -14
- package/prod/index.js +1 -1
package/README.md
CHANGED
|
@@ -1,1047 +1,1116 @@
|
|
|
1
|
-
|
|
1
|
+
# CookieFlow™
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
***
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
<figure><img src="https://3948747524-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyWDd0BQVjmRUYm47Xnrj%2Fuploads%2F3h17Hj5ZAxhUMFE6oHmg%2FThumb.png?alt=media&token=a7d697e2-d4cc-4310-a224-5f49fa4f3654" alt=""><figcaption></figcaption></figure>
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
***
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
## Overview
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
CookieFlow™ is a comprehensive cookie consent management solution developed by [Reform Digital®](https://reform.digital) specifically for Webflow websites. It provides a compliant, customizable framework for handling user consent preferences across different geographical regions, automatically adapting to privacy regulations like GDPR, CCPA, and others.
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
- [Included Tools](#included-tools)
|
|
15
|
-
- [Prerequisites](#prerequisites)
|
|
16
|
-
- [Installation](#installation)
|
|
17
|
-
- [Step 1: Setup Template](#step-1-setup-template)
|
|
18
|
-
- [Step 2: Setup Public SSH Key](#step-2-setup-public-ssh-key-first-time-only)
|
|
19
|
-
- [Step 3: Setup Private SSH Key](#step-3-setup-private-ssh-key-for-every-new-project)
|
|
20
|
-
- [Step 4: Setup NPM](#step-4-setup-npm)
|
|
21
|
-
- [Step 5: Setup Your Project](#step-5-setup-your-project)
|
|
22
|
-
- [How to use DevKit](#how-to-use-devkit)
|
|
23
|
-
- [Project Folders](#project-folders)
|
|
24
|
-
- [Building & Testing in Development](#building-testing-in-development)
|
|
25
|
-
- [Importing Scripts in Webflow](#importing-scripts-in-webflow)
|
|
26
|
-
- [Building & Testing in Production](#building-testing-in-production)
|
|
27
|
-
- [Shipping to NPM](#shipping-to-npm)
|
|
28
|
-
- [Addressing Version Caching](#addressing-version-caching)
|
|
29
|
-
- [Working with Branches & Contributing](#working-with-branches)
|
|
30
|
-
- [Condensed Guide (for Existing DevKit Users)](#condensed-guide-for-existing-devkit-users)
|
|
13
|
+
**What CookieFlow™ Does**
|
|
31
14
|
|
|
32
|
-
|
|
15
|
+
* **Automatically detects user location** and displays the appropriate consent banner
|
|
16
|
+
* **Manages cookie consent** across multiple categories (marketing, analytics, personalization)
|
|
17
|
+
* **Complies with regional regulations** (GDPR, CCPA, etc.)
|
|
18
|
+
* **Stores consent records** in your Supabase database for audit trails
|
|
19
|
+
* **Integrates seamlessly** with Google Tag Manager and Webflow Analytics
|
|
20
|
+
* **Respects privacy signals** like Do Not Track (DNT) and Global Privacy Control (GPC)
|
|
33
21
|
|
|
34
|
-
|
|
22
|
+
***
|
|
35
23
|
|
|
36
|
-
|
|
24
|
+
### Features
|
|
37
25
|
|
|
38
|
-
|
|
26
|
+
#### 🔍 Automatic Geolocation
|
|
39
27
|
|
|
40
|
-
|
|
28
|
+
CookieFlow™ automatically detects your visitors' location using IP-based geolocation and displays the appropriate consent banner based on their region. If geolocation fails, it intelligently falls back to timezone-based detection.
|
|
41
29
|
|
|
42
|
-
|
|
30
|
+
**How It Works:**
|
|
43
31
|
|
|
44
|
-
|
|
32
|
+
1. CookieFlow™ checks the visitor's IP address
|
|
33
|
+
2. Determines their country code
|
|
34
|
+
3. Matches the country to the appropriate zone (ZONE\_1, ZONE\_2, or ZONE\_3)
|
|
35
|
+
4. Shows the correct banner for that region
|
|
36
|
+
5. Hides banners for other regions
|
|
45
37
|
|
|
46
|
-
|
|
38
|
+
**Privacy-Conscious:**
|
|
47
39
|
|
|
48
|
-
|
|
40
|
+
* IP addresses are anonymized before storage (last octet set to 0)
|
|
41
|
+
* Geolocation data is used only to determine compliance zone
|
|
42
|
+
* No personally identifiable information is collected during detection
|
|
49
43
|
|
|
50
|
-
|
|
44
|
+
#### 📍 Regional Compliance (3 Zones)
|
|
51
45
|
|
|
52
|
-
|
|
46
|
+
* **ZONE\_1 (Basic Notice)**: Simple notice-only approach for 130 countries with minimal compliance requirements
|
|
47
|
+
* **ZONE\_2 (Opt-Out/CCPA)**: For 6 CCPA-affected regions (US, PR, GU, AS, MP, VI) with "Do Not Sell" option
|
|
48
|
+
* **ZONE\_3 (Opt-In/GDPR)**: For 50 GDPR-affected regions (EU, UK, Canada, Brazil, Japan, etc.) with detailed consent options
|
|
49
|
+
* **Customizable**: Override defaults with script attributes if privacy regulations change
|
|
53
50
|
|
|
54
|
-
|
|
51
|
+
#### ⏰ Configurable Cookie Expiry
|
|
55
52
|
|
|
56
|
-
|
|
53
|
+
Set how long consent cookies should last (default is 6 months). Users can be prompted to renew their consent when it expires.
|
|
57
54
|
|
|
58
|
-
|
|
55
|
+
#### 📊 Consent Record Storage
|
|
59
56
|
|
|
60
|
-
|
|
57
|
+
GDPR and other privacy regulations require consent records to be stored and maintained for audit trails. CookieFlow™ is built to work seamlessly with Supabase due to its ease of setup and free tier availability. Once configured, all consent records are automatically stored in your Supabase database, providing a complete compliance audit trail without additional maintenance.
|
|
61
58
|
|
|
62
|
-
|
|
59
|
+
#### 🔒 Privacy Signal Respect
|
|
63
60
|
|
|
64
|
-
|
|
65
|
-
- **[eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier):** Runs Prettier as an ESLint rule.
|
|
61
|
+
CookieFlow™ automatically respects and responds to:
|
|
66
62
|
|
|
67
|
-
|
|
63
|
+
* Do Not Track (DNT) browser signals
|
|
64
|
+
* Global Privacy Control (GPC) signals
|
|
65
|
+
* Automatically opts users out if these signals are detected
|
|
68
66
|
|
|
69
|
-
|
|
67
|
+
#### 🤖 Bot Detection
|
|
70
68
|
|
|
71
|
-
|
|
69
|
+
Crawlers and bots won't see consent banners, keeping your site's SEO intact.
|
|
72
70
|
|
|
73
|
-
|
|
71
|
+
#### 🔄 Consent ID Tracking
|
|
74
72
|
|
|
75
|
-
|
|
73
|
+
Tracks and displays a unique consent ID to users (GDPR requirement for EU visitors).
|
|
76
74
|
|
|
77
|
-
|
|
75
|
+
#### 🎨 Fully Customizable
|
|
78
76
|
|
|
79
|
-
|
|
77
|
+
Complete control over styling and layout using Webflow's native design tools.
|
|
80
78
|
|
|
81
|
-
|
|
79
|
+
***
|
|
82
80
|
|
|
83
|
-
|
|
84
|
-
- **[Node.js](https://nodejs.org/):** A JavaScript runtime to build and run your applications.
|
|
85
|
-
- **[GitHub Desktop](https://desktop.github.com/):** (Optional, but recommended) A graphical interface that enables you to interact with GitHub without using the command line.
|
|
86
|
-
- **[Google Chrome](https://www.google.com/chrome/):** A Chromium-based browser such as Google Chrome or Arc is required. Please note that this template is not compatible with Safari or some other browsers and may not function as intended if used with them.
|
|
81
|
+
### Compliance
|
|
87
82
|
|
|
88
|
-
|
|
83
|
+
✔ **Equal Prominence**: "Accept" and "Reject" buttons are identical in design.\
|
|
84
|
+
✔ **No Pre-Checked Boxes**: Users must actively opt in to non-essential cookies.\
|
|
85
|
+
✔ **Plain Language**: Simple, clear wording without legal jargon.\
|
|
86
|
+
✔ **No Implied Consent**: Actions like scrolling or navigating do not count as consent.\
|
|
87
|
+
✔ **No Cookie Walls**: Full access to the website is provided, even if cookies are rejected.\
|
|
88
|
+
✔ **Granular Control**: Users can opt in to different cookie categories.\
|
|
89
|
+
✔ **Close Button**: Clearly explains that no cookies will be set if closed.\
|
|
90
|
+
✔ **Privacy & Cookie Policy Link**: Easily accessible for transparency.\
|
|
91
|
+
✔ **Publisher Identification**: The website publisher's name is explicitly stated.\
|
|
92
|
+
✔ **Stored Consent Choices**: Users' selections are remembered for a minimum of 6 months (per France & Italy).\
|
|
93
|
+
✔ **Consent Expiry**: Re-consent required every 6–24 months, per country regulations.\
|
|
94
|
+
✔ **Easy Consent Review**: Users can modify settings anytime via a widget or link.\
|
|
95
|
+
✔ **Third-Party Cookies Disclosure**: Third-party providers are listed in the policy.\
|
|
96
|
+
✔ **Cross-Site Tracking Compliance**: Explicit opt-in required for tracking across sites.\
|
|
97
|
+
✔ **No Nudging**: Rejecting cookies is just as easy as accepting them.\
|
|
98
|
+
✔ **Dismissal Transparency (Italy)**: Users are informed that rejecting cookies will not affect access to content.
|
|
89
99
|
|
|
90
|
-
|
|
100
|
+
CookieFlow™ has been built with these regulations in mind, for full compliance implement it according to the documentation, do not change its functionality and only edit and style it considering the above rules.
|
|
91
101
|
|
|
92
|
-
|
|
102
|
+
### Considerations
|
|
93
103
|
|
|
94
|
-
|
|
104
|
+
While CookieFlow™ provides comprehensive cookie consent management, there are several Webflow-specific features that require additional attention to ensure full GDPR compliance:
|
|
95
105
|
|
|
96
|
-
|
|
106
|
+
#### Webflow E-Commerce is not GDPR compliant
|
|
97
107
|
|
|
98
|
-
|
|
99
|
-
- If you haven’t done so, [create a GitHub account](https://github.com/join).
|
|
100
|
-
2. **Clone this template**:
|
|
101
|
-
- Navigate to the [main page](https://github.com/reform-digital/webflow-devkit) of the template repository.
|
|
102
|
-
- Click on `Use this template` at the top of the repository and choose `Create a new repository`.
|
|
103
|
-
- Ensure the "Owner" is your GitHub username, and give your repository a unique name relevant to the project (e.g., `client-project-name`).
|
|
104
|
-
- Choose `Private` as the repository visibility.
|
|
105
|
-
- Click on `Create repository` to generate your new repository.
|
|
106
|
-
3. **Download the Repository Locally Using GitHub Desktop**:
|
|
107
|
-
- Navigate to your newly created GitHub repository (if not redirected there already upon creation).
|
|
108
|
-
- Click on the `Code` button, and then choose `Open with GitHub Desktop`.
|
|
109
|
-
- Follow the steps in GitHub Desktop to choose a folder on your local machine where the repository files will be downloaded and synchronized, and press `clone`.
|
|
110
|
-
4. **Launch Your Development Environment**:
|
|
111
|
-
- In GitHub Desktop, check that your new repository is now listed under `Current Repository` and if not make sure to select it.
|
|
112
|
-
- Click on the `Repository` tab in the top menu, and choose `Open in Visual Studio Code` or use the quick button link.
|
|
113
|
-
- Visual Studio Code should launch, opening your project repository locally, ready for development.
|
|
108
|
+
Webflow's native e-commerce solution is not fully GDPR compliant by default, as it uses cookies that may track users without explicit consent. Since these cookies are managed directly by Webflow, our cookie consent solution, CookieFlow, cannot control or block them. If you are using Webflow e-commerce, we recommend consulting a legal expert and exploring additional compliance measures to ensure your store meets GDPR requirements.
|
|
114
109
|
|
|
115
|
-
|
|
110
|
+
#### Webflow's native video element for YouTube
|
|
116
111
|
|
|
117
|
-
|
|
112
|
+
YouTube videos do not comply with GDPR regulations by default. To ensure users have control over their data, it's best to use embedded iFrames. If you add YouTube videos to your Webflow site using the native video element, personal data is automatically shared with YouTube and its parent company, Google, as soon as the page loads. To avoid this, consider using a custom code embed instead.
|
|
118
113
|
|
|
119
|
-
|
|
114
|
+
#### Webflow's map is not GDPR compliant
|
|
120
115
|
|
|
121
|
-
|
|
116
|
+
Webflow's native map element does not comply with GDPR regulations, as it automatically shares personal data with third parties like Google without user consent. To prioritize user privacy and provide better control over data sharing, it's advisable to use an embedded Google Map instead.
|
|
122
117
|
|
|
123
|
-
|
|
118
|
+
#### Webflow's reCaptcha is not GDPR compliant
|
|
124
119
|
|
|
125
|
-
|
|
120
|
+
Webflow's built-in reCaptcha does not fully comply with GDPR, as it collects user data (such as IP addresses and behavior) without explicit consent. To maintain compliance and safeguard user privacy, it's best to integrate reCaptcha manually into your forms.
|
|
126
121
|
|
|
127
|
-
|
|
122
|
+
#### Remove `<noscript>` tags for compliance
|
|
128
123
|
|
|
129
|
-
|
|
124
|
+
`<noscript>` tags are not compliant with cookie consent regulations and should be removed. These tags execute even when JavaScript is disabled, which can bypass cookie consent mechanisms and potentially collect user data without proper authorization. To ensure GDPR compliance, it is essential to eliminate all `<noscript>` tags from your website.
|
|
130
125
|
|
|
131
|
-
|
|
126
|
+
***
|
|
132
127
|
|
|
133
|
-
|
|
128
|
+
### Support
|
|
134
129
|
|
|
135
|
-
|
|
136
|
-
- Open your terminal and execute the following command to see if existing SSH keys are present:
|
|
130
|
+
#### Getting Help
|
|
137
131
|
|
|
138
|
-
|
|
139
|
-
ls -al ~/.ssh
|
|
140
|
-
```
|
|
132
|
+
Need assistance with CookieFlow™? Try these steps:
|
|
141
133
|
|
|
142
|
-
|
|
134
|
+
1. **Review the documentation** - Most common issues are covered in this guide
|
|
135
|
+
2. **Check the browser console** - Look for error messages that may indicate configuration issues
|
|
136
|
+
3. **Verify your configuration** - Ensure all attributes are spelled correctly and properly formatted
|
|
137
|
+
4. **Validate Supabase credentials** - Confirm your Supabase URL and API key are correct and have proper permissions
|
|
138
|
+
5. **Still stuck?** - Join our [Slack community](https://join.slack.com/t/rdcommunity/shared_invite/zt-2zser6sir-3CnFYB6gP4lvQsV2rY3wGw) for direct support from our team
|
|
143
139
|
|
|
144
|
-
|
|
140
|
+
#### Feature Requests & Bugs
|
|
145
141
|
|
|
146
|
-
|
|
142
|
+
CookieFlow™ is actively maintained and continuously improved. We welcome your feedback:
|
|
147
143
|
|
|
148
|
-
|
|
144
|
+
* **Feature requests** - Share ideas to make CookieFlow™ even better
|
|
145
|
+
* **Bug reports** - Help us identify and fix issues
|
|
146
|
+
* **General feedback** - Tell us about your experience
|
|
149
147
|
|
|
150
|
-
|
|
151
|
-
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
|
|
152
|
-
```
|
|
148
|
+
Join our [Slack community](https://join.slack.com/t/rdcommunity/shared_invite/zt-2zser6sir-3CnFYB6gP4lvQsV2rY3wGw) to contribute!
|
|
153
149
|
|
|
154
|
-
|
|
150
|
+
***
|
|
155
151
|
|
|
156
|
-
|
|
152
|
+
## Recommended Setup
|
|
157
153
|
|
|
158
|
-
|
|
154
|
+
### Quick Start
|
|
159
155
|
|
|
160
|
-
|
|
161
|
-
eval "$(ssh-agent -s)"
|
|
162
|
-
ssh-add ~/.ssh/id_rsa
|
|
163
|
-
```
|
|
156
|
+
We provide a ready-to-use Webflow component that includes all necessary elements, attributes, and scripts out of the box. Simply copy the component from our demonstration website and paste it into your Webflow project.
|
|
164
157
|
|
|
165
|
-
|
|
158
|
+
#### What's Included
|
|
166
159
|
|
|
167
|
-
|
|
160
|
+
The prebuilt component comes with:
|
|
168
161
|
|
|
169
|
-
|
|
162
|
+
* **All required HTML elements** with proper attributes
|
|
163
|
+
* **The CookieFlow™ script** already integrated
|
|
164
|
+
* **Three banner variations** (for different compliance zones)
|
|
165
|
+
* **Settings/preferences modal** with consent toggles
|
|
166
|
+
* **Manager button** for reopening the consent interface
|
|
167
|
+
* **GDPR consent info banner**
|
|
170
168
|
|
|
171
|
-
|
|
169
|
+
#### Important: Script Configuration
|
|
172
170
|
|
|
173
|
-
|
|
174
|
-
```sh
|
|
175
|
-
cat ~/.ssh/id_rsa.pub | pbcopy
|
|
176
|
-
```
|
|
177
|
-
If you are using an existing key, replace id_rsa with the name of your existing public key file if it's different.
|
|
178
|
-
- **Manual Copying** (make sure to copy all contents after running command):
|
|
179
|
-
```sh
|
|
180
|
-
cat ~/.ssh/id_rsa.pub
|
|
181
|
-
```
|
|
171
|
+
The prebuilt component includes the CookieFlow™ script already. You just need to:
|
|
182
172
|
|
|
183
|
-
|
|
184
|
-
|
|
173
|
+
1. Copy the component from our demo site
|
|
174
|
+
2. Paste it into your Webflow project
|
|
175
|
+
3. Update the script attributes in the component with your Supabase credentials (see the Supabase Setup section below)
|
|
176
|
+
4. Customize the styling to match your brand
|
|
185
177
|
|
|
186
|
-
|
|
178
|
+
***
|
|
179
|
+
|
|
180
|
+
### Supabase Setup
|
|
181
|
+
|
|
182
|
+
CookieFlow™ requires a Supabase database to store consent records for compliance and audit purposes. If you don't already have a Supabase account and database set up:
|
|
183
|
+
|
|
184
|
+
1. **Sign up at** [**https://supabase.com**](https://supabase.com)
|
|
185
|
+
2. **Create a new project** (wait for provisioning to complete)
|
|
186
|
+
3. **Open the SQL Editor** in your Supabase dashboard
|
|
187
|
+
4. **Paste & run the following SQL code** to create the necessary tables and security policies:
|
|
187
188
|
|
|
188
|
-
|
|
189
|
+
```sql
|
|
190
|
+
/* ============================================================
|
|
191
|
+
1️⃣ CREATE TABLES
|
|
192
|
+
============================================================ */
|
|
189
193
|
|
|
190
|
-
|
|
194
|
+
-- Create the main consents table (idempotent)
|
|
195
|
+
create table if not exists public.consents (
|
|
196
|
+
id serial primary key,
|
|
197
|
+
consent_id text not null,
|
|
198
|
+
anonymized_ip text,
|
|
199
|
+
action_date timestamptz default now(),
|
|
200
|
+
page_url text not null,
|
|
201
|
+
user_agent text,
|
|
202
|
+
consent_method text,
|
|
203
|
+
modal_text text,
|
|
204
|
+
button_clicked text,
|
|
205
|
+
consents jsonb not null,
|
|
206
|
+
geo_region text
|
|
207
|
+
);
|
|
191
208
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
cat ~/.ssh/id_rsa | pbcopy
|
|
196
|
-
```
|
|
197
|
-
- **Manual Copying** (make sure to copy all contents including the **BEGIN** and **END** tags):
|
|
198
|
-
```sh
|
|
199
|
-
cat ~/.ssh/id_rsa
|
|
200
|
-
```
|
|
201
|
-
- Navigate to your new project repository on GitHub (the one where you cloned this template).
|
|
202
|
-
- Go to the project `Settings`. Make sure you are in the project settings and not the global account settings accessed via your profile image.
|
|
203
|
-
- In the sidebar menu under the `Security` section, click on the `Secrets and variables` dropdown, then choose `Actions`.
|
|
204
|
-
- Click `New repository secret`.
|
|
205
|
-
- Name it **`SSH_TOKEN`** (name must match this exactly) and paste the SSH private key content into the value field.
|
|
206
|
-
- Click `Add secret` to finalize.
|
|
209
|
+
/* ============================================================
|
|
210
|
+
2️⃣ ROW-LEVEL SECURITY (RLS)
|
|
211
|
+
============================================================ */
|
|
207
212
|
|
|
208
|
-
|
|
213
|
+
-- Enable RLS on the consents table
|
|
214
|
+
alter table public.consents enable row level security;
|
|
209
215
|
|
|
210
|
-
|
|
216
|
+
-- Allow anonymous INSERTs only (no SELECT/UPDATE/DELETE)
|
|
217
|
+
do
|
|
218
|
+
$$
|
|
219
|
+
begin
|
|
220
|
+
if not exists (
|
|
221
|
+
select 1
|
|
222
|
+
from pg_policies
|
|
223
|
+
where schemaname = 'public'
|
|
224
|
+
and tablename = 'consents'
|
|
225
|
+
and policyname = 'Allow public inserts'
|
|
226
|
+
) then
|
|
227
|
+
create policy "Allow public inserts"
|
|
228
|
+
on public.consents
|
|
229
|
+
for insert
|
|
230
|
+
with check (true);
|
|
231
|
+
end if;
|
|
232
|
+
end
|
|
233
|
+
$$;
|
|
211
234
|
|
|
212
|
-
|
|
235
|
+
/* ============================================================
|
|
236
|
+
3️⃣ QUERY HELPER FUNCTION
|
|
237
|
+
============================================================ */
|
|
213
238
|
|
|
214
|
-
|
|
239
|
+
-- Use a wrapper so clients can only read whitelisted columns
|
|
240
|
+
create or replace function public.get_consent_by_id (p_consent_id text)
|
|
241
|
+
returns table (
|
|
242
|
+
consent_id text,
|
|
243
|
+
action_date timestamptz,
|
|
244
|
+
consents jsonb
|
|
245
|
+
)
|
|
246
|
+
language sql
|
|
247
|
+
stable
|
|
248
|
+
security definer
|
|
249
|
+
set search_path = public
|
|
250
|
+
as
|
|
251
|
+
$$
|
|
252
|
+
select consent_id, action_date, consents
|
|
253
|
+
from public.consents
|
|
254
|
+
where consent_id = p_consent_id
|
|
255
|
+
order by action_date desc
|
|
256
|
+
limit 1;
|
|
257
|
+
$$;
|
|
215
258
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
- Grant your client permission to this organization whenever needed.
|
|
259
|
+
-- Revoke direct table SELECT, grant function EXECUTE
|
|
260
|
+
revoke select on public.consents from public;
|
|
261
|
+
grant execute on function public.get_consent_by_id(text) to public;
|
|
220
262
|
|
|
221
|
-
|
|
263
|
+
/* ============================================================
|
|
264
|
+
4️⃣ HEARTBEAT FUNCTION (keep-alive for Supabase Free plan)
|
|
265
|
+
============================================================ */
|
|
222
266
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
267
|
+
create or replace function public.heartbeat ()
|
|
268
|
+
returns void
|
|
269
|
+
language sql
|
|
270
|
+
stable
|
|
271
|
+
set search_path = public
|
|
272
|
+
as
|
|
273
|
+
$$
|
|
274
|
+
select 1;
|
|
275
|
+
$$;
|
|
227
276
|
|
|
228
|
-
|
|
277
|
+
-- Grant execution to the anonymous role so an external cron
|
|
278
|
+
-- can ping /rest/v1/rpc/heartbeat using only the anon key
|
|
279
|
+
grant execute on function public.heartbeat() to anon;
|
|
229
280
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
5. **Add the NPM Token as a GitHub Secret:**
|
|
233
|
-
- Navigate to your new project repository on GitHub (the one you created by cloning this template).
|
|
234
|
-
- Go to the project `Settings`, ensuring you are accessing project-specific settings (which are accessed via a link on the project toolbar), not global account settings (which are accessed via your profile icon).
|
|
235
|
-
- In the sidebar menu under the `Security` section, select the `Secrets and variables` dropdown, then choose `Actions`.
|
|
236
|
-
- Click `New repository secret`.
|
|
237
|
-
- Name it **`NPM_TOKEN`** (name must match this exactly) and paste the NPM token into the value field.
|
|
238
|
-
- Click `Add secret` to finalize.
|
|
239
|
-
|
|
240
|
-
## Step 5: Setup Your Project
|
|
241
|
-
|
|
242
|
-
This section guides you through setting up your project package in Visual Studio Code, which involves installing a package manager, managing dependencies, and initial setup. Make sure you have the correct project and directory loaded in Visual Studio Code – you can always use GitHub desktop to load the correct repository (as you did in [Step 1.4](#step-1-setup-template)).
|
|
243
|
-
|
|
244
|
-
1. **Install pnpm (First-Time Only):**
|
|
245
|
-
|
|
246
|
-
- pnpm is a fast, disk space efficient package manager. If it's your first time using pnpm, install it globally with the following command:
|
|
247
|
-
```sh
|
|
248
|
-
npm install -g pnpm
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
2. **Install VS Code Extensions (First-Time Only):**
|
|
252
|
-
|
|
253
|
-
- Install and activate [Prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) and [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) extensions in Visual Studio Code.
|
|
254
|
-
|
|
255
|
-
3. **Install Dependencies:**
|
|
256
|
-
|
|
257
|
-
- Execute the following command to install the project dependencies:
|
|
258
|
-
```sh
|
|
259
|
-
pnpm install
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
### ✅ Installation Complete!
|
|
263
|
-
|
|
264
|
-
---
|
|
265
|
-
|
|
266
|
-
<a name="how-to-use-devkit"></a>
|
|
267
|
-
|
|
268
|
-
# 🚀 How to use DevKit
|
|
269
|
-
|
|
270
|
-
Understanding the structure of the Webflow DevKit template is crucial for a seamless development experience.
|
|
271
|
-
|
|
272
|
-
<a name="project-folders"></a>
|
|
273
|
-
|
|
274
|
-
## 📂 Project Folders
|
|
275
|
-
|
|
276
|
-
Here’s a guide to help you navigate through the key directories and utilize them effectively:
|
|
277
|
-
|
|
278
|
-
### Source Directory
|
|
279
|
-
|
|
280
|
-
The `src` folder serves as the primary workspace for your project, housing all the JavaScript files, CSS files, and modules necessary for your Webflow site.
|
|
281
|
-
|
|
282
|
-
### Files Folder
|
|
283
|
-
|
|
284
|
-
Located within the src directory, the `files` folder is your primary working area designated for housing all your main JavaScript and CSS files for the project. For example `home.js`, `home.css`, `about.js`, `contact.js`, and so forth.
|
|
285
|
-
|
|
286
|
-
Additionally, you can create any global files such as `global.js`, `global.css`, `analytics.js`, etc. in the same Files folder, if you wish to execute certain scripts or invoke specific modules across all pages of your website. The actual scope of each file (i.e. page-specific versus global) will depend on where it is imported in Webflow (see [Importing Scripts in Webflow](#importing-scripts-in-webflow)).
|
|
287
|
-
|
|
288
|
-
### Modules Folder
|
|
289
|
-
|
|
290
|
-
Adjacent to the files folder, the `modules` directory is intended for smaller, reusable script segments. Examples of files you might store here include:
|
|
291
|
-
|
|
292
|
-
- `greet.js`: A simple module to greet users.
|
|
293
|
-
- `mirror-click.js`: A helper function to mirror click events in Webflow, useful across various sections and pages.
|
|
294
|
-
- `animations.js`: A collection of animation functions to enhance your site's interactivity.
|
|
295
|
-
|
|
296
|
-
These modular script files can be effortlessly imported into any of your page-specific script files. This practice not only keeps your codebase tidy but also fosters a modular development approach, making your code more maintainable and scalable.
|
|
297
|
-
|
|
298
|
-
By adhering to this structure, you ensure a well-organized and efficient development environment, paving the way for a smoother integration of JavaScript functionalities and CSS styles into your Webflow projects.
|
|
299
|
-
|
|
300
|
-
<a name="building-testing-in-development"></a>
|
|
301
|
-
|
|
302
|
-
## 🧑💻 Building & Testing in Development
|
|
303
|
-
|
|
304
|
-
As you embark on the journey of developing JavaScript and CSS functionality within the "files" and "modules" directories, integrating testing into your workflow is paramount. Conducting tests in a development setting is imperative and should proceed hand-in-hand with the coding phase. To facilitate this, run a local development server and integrate your scripts into your Webflow staging domain. Stay alert for any anomalies or errors, utilizing the available debugging tools to rectify issues as they arise. This continuous loop of coding, testing, and debugging is crucial for cultivating a stable and trustworthy codebase.
|
|
305
|
-
|
|
306
|
-
### Running the Development Server
|
|
307
|
-
|
|
308
|
-
To build and initiate the development server, execute:
|
|
309
|
-
|
|
310
|
-
```sh
|
|
311
|
-
pnpm dev
|
|
281
|
+
/* Optional: Lock down visibility of heartbeat to everyone else */
|
|
282
|
+
revoke all on function public.heartbeat() from public;
|
|
312
283
|
```
|
|
313
284
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
If your project incorporates **multiple DevKit templates** and you intend to run several local servers simultaneously, it’s necessary to assign unique port numbers to each. To configure this:
|
|
285
|
+
5. **Copy your Supabase URL and API Key** from your Supabase dashboard:
|
|
286
|
+
* **Project URL**: Found in **Settings → Data API** tab (e.g., `https://xxxxxxxxxxxxx.supabase.co`)
|
|
287
|
+
* **anon key**: Found in **Settings → API Keys** tab (copy the `anon` `public` key)
|
|
319
288
|
|
|
320
|
-
|
|
321
|
-
- Locate the line `const PORT = 3000;`.
|
|
322
|
-
- Modify the port number (3000) to an alternative number (e.g., 3001) to distinguish each template’s local server.
|
|
289
|
+
***
|
|
323
290
|
|
|
324
|
-
|
|
291
|
+
### Script Configuration
|
|
325
292
|
|
|
326
|
-
|
|
293
|
+
The prebuilt component includes an embed element called "Component Scripts" with the required CookieFlow™ script already configured. To get started with the default configuration, simply update the script's attributes with your Supabase credentials (see [Supabase Setup](#-supabase-setup) above).
|
|
327
294
|
|
|
328
|
-
|
|
295
|
+
#### Basic Configuration
|
|
329
296
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
### 1️⃣ Traditional Method
|
|
333
|
-
|
|
334
|
-
During the operation of a local server (via `pnpm dev` or `pnpm prod` mentioned later), DevKit conveniently logs the script tags for all JavaScript and CSS files situated in the src folder. These scripts, along with their imported modules and source maps, are subsequently exported to the dev folder and served directly from this location.
|
|
335
|
-
|
|
336
|
-
**Logged script tags example:**
|
|
297
|
+
The script requires these two essential attributes to function:
|
|
337
298
|
|
|
299
|
+
```html
|
|
300
|
+
<script
|
|
301
|
+
src="https://cdn.jsdelivr.net/npm/@reform-digital/cookie-flow@LATEST_VERSION/prod/index.js"
|
|
302
|
+
rd-consent-storage-url="https://your-project.supabase.co"
|
|
303
|
+
rd-consent-storage-api="your-api-key-here"
|
|
304
|
+
></script>
|
|
338
305
|
```
|
|
339
|
-
=== JS Scripts: === (Before </body> tag)
|
|
340
306
|
|
|
341
|
-
|
|
307
|
+
#### Advanced Configuration (Optional)
|
|
342
308
|
|
|
343
|
-
|
|
309
|
+
Beyond the basic setup, CookieFlow™ supports additional customizations to meet your specific compliance needs and preferences.
|
|
344
310
|
|
|
345
|
-
|
|
311
|
+
**Cookie Expiration Configuration**
|
|
346
312
|
|
|
347
|
-
|
|
313
|
+
**Default Behavior**: By default, the consent cookie expires after **6 months**. This setting works well for most countries and aligns with common GDPR requirements.
|
|
348
314
|
|
|
349
|
-
|
|
350
|
-
```
|
|
315
|
+
**How It Works**: CookieFlow™ stores a consent cookie called `cookieconsent_status` that remembers the user's choices. The expiration of this cookie is controlled by the `rd-consent-expiry` attribute in your script tag.
|
|
351
316
|
|
|
352
|
-
|
|
317
|
+
**Setting a Custom Expiration**: If you need to set a different expiration period based on your specific country's GDPR regulations, you can override the default by adding the `rd-consent-expiry` attribute to your script tag along with a value in **months**. For example, if your country states that consents should expire after 3 months instead of six, then you would update the attribute as follows:
|
|
353
318
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
### 2️⃣ Automated Method (Recommended)
|
|
362
|
-
|
|
363
|
-
- Jump to [condensed version](#importing-scripts-in-webflow2) (experienced DevKit users)
|
|
364
|
-
|
|
365
|
-
DevKit offers a custom script import mechanism designed to streamline and automate the process of integrating JavaScript and CSS into your Webflow project. This approach eliminates the need for manual switching between script tags when moving from a development to a production environment, providing a smoother and more efficient workflow.
|
|
366
|
-
|
|
367
|
-
### Setup
|
|
368
|
-
|
|
369
|
-
**`Step 1` Main Settings:**
|
|
370
|
-
|
|
371
|
-
Add this script to your site’s **global** settings in the **`<head>`** tag. The script is designed to configure essential variables for your project: the path to your npm package, the development mode toggle, and the local port number. These variables are crucial for script loader functions and other development processes across your site.
|
|
372
|
-
|
|
373
|
-
```
|
|
374
|
-
<!-- RD® Webflow DevKit / Main Settings -->
|
|
375
|
-
<script>
|
|
376
|
-
window.npmPath = "@reform-digital/sample-project@1.0.0"; // Update this once you have shipped to npm.
|
|
377
|
-
window.devMode = true; // Change to false in production
|
|
378
|
-
window.classViewer = true; // Helper to display classes and ids in DevMode
|
|
379
|
-
window.localPort = 3000; // Also change in bin/localport.js in VS Code
|
|
380
|
-
</script>
|
|
319
|
+
```html
|
|
320
|
+
<script
|
|
321
|
+
src="https://cdn.jsdelivr.net/npm/@reform-digital/cookie-flow@LATEST_VERSION/prod/index.js"
|
|
322
|
+
rd-consent-storage-url="https://your-project.supabase.co"
|
|
323
|
+
rd-consent-storage-api="your-api-key-here"
|
|
324
|
+
rd-consent-expiry="3"
|
|
325
|
+
></script>
|
|
381
326
|
```
|
|
382
327
|
|
|
383
|
-
**
|
|
328
|
+
**What Happens on Expiry**: When the consent cookie expires:
|
|
384
329
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
330
|
+
1. User returns to your site
|
|
331
|
+
2. CookieFlow™ detects the expired cookie
|
|
332
|
+
3. The appropriate consent banner is shown again
|
|
333
|
+
4. User can reconfirm or change their preferences
|
|
389
334
|
|
|
390
|
-
|
|
335
|
+
**Displaying Expiry Date to Users (Optional)**: To inform users when their consent expires, add this attribute to any text element:
|
|
391
336
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
<!-- RD® Webflow DevKit / Style Loader -->
|
|
396
|
-
<script src="https://cdn.jsdelivr.net/npm/@reform-digital/webflow-devkit-utils@1.1.0/prod/style-loader.js"></script>
|
|
337
|
+
```html
|
|
338
|
+
<!-- Will render as "6 months" (based on your configuration) -->
|
|
339
|
+
<p><span rd-cookieflow="consent-expiry">{0}</span> months</p>
|
|
397
340
|
```
|
|
398
341
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
Add this script to your site’s **global** settings before the **`</body>`** closing tag. It enables the dynamic loading of scripts based on the development server’s status.
|
|
342
|
+
CookieFlow™ will automatically replace `{0}` with the expiry period from your script configuration.
|
|
402
343
|
|
|
403
|
-
|
|
404
|
-
<!-- RD® Webflow DevKit / Script Loader -->
|
|
405
|
-
<script src="https://cdn.jsdelivr.net/npm/@reform-digital/webflow-devkit-utils@1.1.0/prod/script-loader.js"></script>
|
|
406
|
-
```
|
|
344
|
+
**Regional Compliance Overview**
|
|
407
345
|
|
|
408
|
-
|
|
346
|
+
CookieFlow™ automatically adapts to your visitors' location, showing the appropriate compliance interface. The system uses three compliance zones:
|
|
409
347
|
|
|
410
|
-
|
|
348
|
+
**ZONE\_1: Basic Notice (Default)**
|
|
411
349
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
<script>
|
|
417
|
-
const globalStyles = ["global.css", "animation.css"];
|
|
418
|
-
loadWebflowStylesheets(globalStyles, npmPath);
|
|
419
|
-
</script>
|
|
420
|
-
```
|
|
350
|
+
**Countries**: Most countries worldwide\
|
|
351
|
+
**Behavior**: Simple notice informing users about cookie usage\
|
|
352
|
+
**User Actions**: Accept or dismiss the notice\
|
|
353
|
+
**Use Case**: Minimal compliance requirements
|
|
421
354
|
|
|
422
|
-
|
|
355
|
+
**Default Country Assignment** (130 countries): AF, AX, AL, DZ, AD, AO, AI, AQ, AG, AM, AW, AU, AZ, BS, BD, BB, BY, BZ, BJ, BM, BT, BO, BQ, BA, BW, BV, IO, BN, BF, BI, CV, KH, CM, KY, CF, TD, CL, CN, CX, CC, CO, KM, CG, CD, CK, CR, CI, CU, CW, DJ, DM, DO, EC, EG, SV, GQ, ER, SZ, ET, FK, FO, FJ, GF, PF, TF, GA, GM, GE, GH, GI, GL, GD, GP, GT, GG, GN, GW, GY, HT, HM, VA, HN, HK, IN, ID, IR, IQ, IM, JM, JE, JO, KZ, KI, KP, KW, KG, LA, LB, LS, LR, LY, MO, MG, MW, MY, MV, ML, MH, MQ, MR, YT, MX, FM, MD, MC, MN, ME, MS, MA, MZ, MM, NA, NR, NP, NC, NI, NE, NU, NF, MK, OM, PK, PW, PS, PA, PG, PY, PE, PH, PN, RE, RU, RW, BL, SH, KN, LC, MF, PM, VC, WS, SM, ST, SA, SN, RS, SC, SL, SG, SX, SB, SO, GS, SS, LK, SD, SR, SJ, SY, TW, TJ, TZ, TH, TL, TG, TK, TO, TT, TN, TM, TC, TV, UZ, UA, AE, VU, VE, VN, VG, WF, UM, EH, YE, ZM, ZW
|
|
423
356
|
|
|
424
|
-
|
|
357
|
+
**ZONE\_2: Opt-Out (CCPA)**
|
|
425
358
|
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
const globalScripts = ["global.js", "analytics.js"];
|
|
430
|
-
loadWebflowScripts(globalScripts, npmPath);
|
|
431
|
-
</script>
|
|
432
|
-
```
|
|
359
|
+
**Countries**: United States and other CCPA-affected regions\
|
|
360
|
+
**Behavior**: Users must opt-out if they don't want their data sold\
|
|
361
|
+
**User Actions**:
|
|
433
362
|
|
|
434
|
-
|
|
363
|
+
* Accept All
|
|
364
|
+
* Reject All (opt-out)
|
|
365
|
+
* Manage Preferences (opens settings) **Use Case**: California Consumer Privacy Act (CCPA) compliance
|
|
435
366
|
|
|
436
|
-
|
|
367
|
+
**Default Country Assignment** (6 countries): AS, GU, MP, PR, US, VI
|
|
437
368
|
|
|
438
|
-
|
|
439
|
-
<!-- RD® Webflow DevKit / Page Styles -->
|
|
440
|
-
<script>
|
|
441
|
-
const pageStyles = ["home.css"];
|
|
442
|
-
loadWebflowStylesheets(pageStyles, npmPath);
|
|
443
|
-
</script>
|
|
444
|
-
```
|
|
369
|
+
**Special Features**:
|
|
445
370
|
|
|
446
|
-
|
|
371
|
+
* "Do Not Sell My Personal Information" option
|
|
447
372
|
|
|
448
|
-
|
|
373
|
+
**ZONE\_3: Opt-In (GDPR)**
|
|
449
374
|
|
|
450
|
-
|
|
375
|
+
**Countries**: European Union and other GDPR-affected regions\
|
|
376
|
+
**Behavior**: Granular consent required for each cookie category\
|
|
377
|
+
**User Actions**:
|
|
451
378
|
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
loadWebflowScripts(pageScripts, npmPath);
|
|
457
|
-
</script>
|
|
458
|
-
```
|
|
379
|
+
* Accept All
|
|
380
|
+
* Reject All
|
|
381
|
+
* Accept Selected (only enable desired categories)
|
|
382
|
+
* Open detailed preferences **Use Case**: General Data Protection Regulation (GDPR) compliance
|
|
459
383
|
|
|
460
|
-
|
|
384
|
+
**Default Country Assignment** (50 countries): AR, AT, BH, BE, BR, BG, CA, HR, CY, CZ, DK, EE, FI, FR, DE, GR, HU, IS, IE, IL, IT, JP, KE, KR, LV, LI, LT, LU, MT, MU, NL, NZ, NG, NO, PL, PT, QA, RO, SK, SI, ZA, ES, SE, CH, TR, UG, GB, UY
|
|
461
385
|
|
|
462
|
-
|
|
386
|
+
**Special Features**:
|
|
463
387
|
|
|
464
|
-
|
|
388
|
+
* Detailed cookie category descriptions
|
|
389
|
+
* Consent ID display for audit trails
|
|
390
|
+
* Granular consent management
|
|
465
391
|
|
|
466
|
-
|
|
392
|
+
**Automatic Detection**
|
|
467
393
|
|
|
468
|
-
|
|
394
|
+
CookieFlow™ uses a two-step detection process:
|
|
469
395
|
|
|
470
|
-
|
|
396
|
+
1. **Primary**: IP-based geolocation (via ipapi.co)
|
|
397
|
+
2. **Fallback**: Timezone-based detection if IP lookup fails
|
|
471
398
|
|
|
472
|
-
|
|
399
|
+
You don't need to configure anything for this to work—it's automatic.
|
|
473
400
|
|
|
474
|
-
|
|
401
|
+
**Regional Configuration Override**
|
|
475
402
|
|
|
476
|
-
|
|
403
|
+
By default, CookieFlow™ uses predefined country assignments based on current privacy regulations (see the [Regional Compliance Overview](#regional-compliance-overview) above). However, you can override these defaults if:
|
|
477
404
|
|
|
478
|
-
|
|
405
|
+
1. A country's privacy regulations change
|
|
406
|
+
2. You need to customize the regional assignments for your specific use case
|
|
407
|
+
3. You want to test different compliance zones
|
|
479
408
|
|
|
480
|
-
To
|
|
409
|
+
To customize country assignments, add these attributes to your script tag:
|
|
481
410
|
|
|
482
|
-
```
|
|
483
|
-
|
|
411
|
+
```html
|
|
412
|
+
<script
|
|
413
|
+
src="https://cdn.jsdelivr.net/npm/@reform-digital/cookie-flow@LATEST_VERSION/prod/index.js"
|
|
414
|
+
rd-consent-storage-url="https://your-project.supabase.co"
|
|
415
|
+
rd-consent-storage-api="your-api-key-here"
|
|
416
|
+
rd-zone-1="US,CA,MX"
|
|
417
|
+
rd-zone-2="UK,AU,BR"
|
|
418
|
+
rd-zone-3="DE,FR,IT,ES"
|
|
419
|
+
></script>
|
|
484
420
|
```
|
|
485
421
|
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
### Building Without Running a Server
|
|
422
|
+
**How to Override**: Simply provide a comma-separated list of 2-letter ISO country codes to reassign any country to a different zone.
|
|
489
423
|
|
|
490
|
-
|
|
424
|
+
**Example**: If Canada moves from ZONE\_3 to ZONE\_2 due to a regulation change:
|
|
491
425
|
|
|
492
|
-
```
|
|
493
|
-
|
|
426
|
+
```html
|
|
427
|
+
<script
|
|
428
|
+
...
|
|
429
|
+
rd-zone-2="CA"
|
|
430
|
+
></script>
|
|
494
431
|
```
|
|
495
432
|
|
|
496
|
-
|
|
433
|
+
**Configuration Attribute Reference**
|
|
497
434
|
|
|
498
|
-
|
|
435
|
+
**`rd-consent-storage-url` (Required)**
|
|
499
436
|
|
|
500
|
-
|
|
437
|
+
* Your Supabase project URL
|
|
438
|
+
* Format: `https://xxxxxxxxxxxxx.supabase.co`
|
|
439
|
+
* Found in: Settings → Data API
|
|
501
440
|
|
|
502
|
-
|
|
441
|
+
**`rd-consent-storage-api` (Required)**
|
|
503
442
|
|
|
504
|
-
|
|
443
|
+
* Your Supabase anonymous/public API key
|
|
444
|
+
* Format: Long string of characters
|
|
445
|
+
* Found in: Settings → API Keys (use the `anon` `public` key)
|
|
505
446
|
|
|
506
|
-
|
|
447
|
+
**`rd-consent-expiry` (Optional)**
|
|
507
448
|
|
|
508
|
-
|
|
449
|
+
* Cookie expiration duration in months
|
|
450
|
+
* Default: `6` (6 months)
|
|
451
|
+
* Can be any number (e.g., `3`, `12`, `24`)
|
|
509
452
|
|
|
510
|
-
|
|
453
|
+
**`rd-zone-1`, `rd-zone-2`, `rd-zone-3` (Optional)**
|
|
511
454
|
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
Note: If you are using the GitHub extension for VS Code, you might receive the message "GitHub for VS Code is requesting additional permissions”. If so, review the permissions requested by the app and grant the necessary permissions.
|
|
455
|
+
* Comma-separated list of country codes (2-letter ISO format)
|
|
456
|
+
* Used to override default regional assignments
|
|
457
|
+
* Format: `"US,CA,MX"`
|
|
517
458
|
|
|
518
|
-
|
|
459
|
+
***
|
|
519
460
|
|
|
520
|
-
|
|
461
|
+
### Store Consents
|
|
521
462
|
|
|
522
|
-
|
|
463
|
+
CookieFlow™ automatically stores comprehensive consent records in your Supabase database for compliance and audit purposes. Each time a user interacts with the consent banner, a detailed record is created that includes both technical metadata and the user's specific consent choices.
|
|
523
464
|
|
|
524
|
-
|
|
525
|
-
- Confirming the package description. Again, you can edit this if required.
|
|
526
|
-
- Confirming the author. Similarly, you can edit this if required.
|
|
527
|
-
- Confirming the package keywords. Again, you can edit or omit this if required.
|
|
528
|
-
- Confirming the license type. Similarly, you can edit this if required.
|
|
529
|
-
- Choosing the type of version update (patch, minor, major). For initial shipments, the version will be set to 1.0.0.
|
|
530
|
-
- Describing the changes in this version, which will be appended to the CHANGELOG.md file.
|
|
531
|
-
- Confirming that the README.md file has been updated.
|
|
532
|
-
- Final confirmation before proceeding.
|
|
465
|
+
#### What Information is Stored
|
|
533
466
|
|
|
534
|
-
|
|
467
|
+
Every consent record contains the following information:
|
|
535
468
|
|
|
536
|
-
|
|
537
|
-
- Check if the version tag exists locally or remotely and handle it.
|
|
538
|
-
- Commit the changes and tag the commit with the new version.
|
|
539
|
-
- Trigger the CI/CD Pipeline.
|
|
469
|
+
**Consent Identification**
|
|
540
470
|
|
|
541
|
-
|
|
471
|
+
* **`consent_id`**: Unique identifier generated from timestamp and anonymized IP (28-character base36 string)
|
|
472
|
+
* **`action_date`**: Precise timestamp when consent was given (automatically set by database)
|
|
542
473
|
|
|
543
|
-
|
|
544
|
-
- **GitHub Push:** The code, along with its shipment settings and the updated version number, is then pushed to your GitHub repository.
|
|
545
|
-
- **GitHub Action - Ship to NPM:** After the push to GitHub, a predefined GitHub Action is triggered. This action ensures your package is correctly published under your NPM account. It handles tasks like authentication with NPM and publishing.
|
|
474
|
+
**User Consent Choices**
|
|
546
475
|
|
|
547
|
-
|
|
476
|
+
* **`consents`**: JSON object containing the user's specific consent decisions:
|
|
548
477
|
|
|
549
|
-
|
|
478
|
+
```json
|
|
479
|
+
{
|
|
480
|
+
"marketing": true/false,
|
|
481
|
+
"analytics": true/false,
|
|
482
|
+
"personalization": true/false,
|
|
483
|
+
"essential": true
|
|
484
|
+
}
|
|
485
|
+
```
|
|
550
486
|
|
|
551
|
-
|
|
487
|
+
**Technical Metadata**
|
|
552
488
|
|
|
553
|
-
|
|
489
|
+
* **`anonymized_ip`**: User's IP address with the last octet set to "0" for privacy
|
|
490
|
+
* **`user_agent`**: Browser and device information for technical support
|
|
491
|
+
* **`page_url`**: The website domain where consent was given
|
|
492
|
+
* **`geo_region`**: User's compliance zone (ZONE\_1, ZONE\_2, or ZONE\_3)
|
|
554
493
|
|
|
555
|
-
|
|
556
|
-
const npmPath = "@your-npm-username/your-package-name@version";
|
|
557
|
-
```
|
|
494
|
+
**User Interaction Details**
|
|
558
495
|
|
|
559
|
-
|
|
496
|
+
* **`consent_method`**: How consent was given ("accept\_all", "reject\_all", "accept\_selected")
|
|
497
|
+
* **`button_clicked`**: Text content of the specific button the user clicked
|
|
498
|
+
* **`modal_text`**: The full text content of the consent banner/modal
|
|
560
499
|
|
|
561
|
-
####
|
|
500
|
+
#### Consent Record Examples
|
|
562
501
|
|
|
563
|
-
|
|
502
|
+
**Example 1: Accept All (GDPR Region)**
|
|
564
503
|
|
|
565
|
-
```
|
|
566
|
-
|
|
504
|
+
```json
|
|
505
|
+
{
|
|
506
|
+
"consent_id": "A1B2C3D4E5F6G7H8I9J0K1L2M3N4",
|
|
507
|
+
"action_date": "2024-01-15T14:30:25.123Z",
|
|
508
|
+
"anonymized_ip": "192.168.1.0",
|
|
509
|
+
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
|
|
510
|
+
"page_url": "https://example.com",
|
|
511
|
+
"consent_method": "accept_all",
|
|
512
|
+
"button_clicked": "Accept All",
|
|
513
|
+
"modal_text": "We use cookies to enhance your experience...",
|
|
514
|
+
"geo_region": "ZONE_3",
|
|
515
|
+
"consents": {
|
|
516
|
+
"marketing": true,
|
|
517
|
+
"analytics": true,
|
|
518
|
+
"personalization": true,
|
|
519
|
+
"essential": true
|
|
520
|
+
}
|
|
521
|
+
}
|
|
567
522
|
```
|
|
568
523
|
|
|
569
|
-
|
|
524
|
+
**Example 2: Selective Consent (GDPR Region)**
|
|
570
525
|
|
|
526
|
+
```json
|
|
527
|
+
{
|
|
528
|
+
"consent_id": "B2C3D4E5F6G7H8I9J0K1L2M3N4O5",
|
|
529
|
+
"action_date": "2024-01-15T14:35:10.456Z",
|
|
530
|
+
"anonymized_ip": "203.45.67.0",
|
|
531
|
+
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36",
|
|
532
|
+
"page_url": "https://example.com",
|
|
533
|
+
"consent_method": "accept_selected",
|
|
534
|
+
"button_clicked": "Save Preferences",
|
|
535
|
+
"modal_text": "We use cookies to enhance your experience...",
|
|
536
|
+
"geo_region": "ZONE_3",
|
|
537
|
+
"consents": {
|
|
538
|
+
"marketing": false,
|
|
539
|
+
"analytics": true,
|
|
540
|
+
"personalization": false,
|
|
541
|
+
"essential": true
|
|
542
|
+
}
|
|
543
|
+
}
|
|
571
544
|
```
|
|
572
|
-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@your-npm-username/your-package-name@version/your-filename.css">
|
|
573
|
-
```
|
|
574
|
-
|
|
575
|
-
Replace `@your-npm-username/your-package-name@version/your-filename.js` or `.css` with the appropriate values. While you can omit @version to always fetch the latest version of the script, doing so may lead to caching issues if the CDN or browsers cache an older version of the script. Specifying the exact version helps to ensure that users always receive the correct version of your script. Refer to [Addressing Version Caching](#addressing-version-caching) for ways to mitigate these issues.
|
|
576
|
-
|
|
577
|
-
### Verification
|
|
578
545
|
|
|
579
|
-
|
|
546
|
+
**Example 3: Reject All (CCPA Region)**
|
|
580
547
|
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
548
|
+
```json
|
|
549
|
+
{
|
|
550
|
+
"consent_id": "C3D4E5F6G7H8I9J0K1L2M3N4O5P6",
|
|
551
|
+
"action_date": "2024-01-15T14:40:15.789Z",
|
|
552
|
+
"anonymized_ip": "198.51.100.0",
|
|
553
|
+
"user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15",
|
|
554
|
+
"page_url": "https://example.com",
|
|
555
|
+
"consent_method": "reject_all",
|
|
556
|
+
"button_clicked": "Reject All",
|
|
557
|
+
"modal_text": "We use cookies to enhance your experience...",
|
|
558
|
+
"geo_region": "ZONE_2",
|
|
559
|
+
"consents": {
|
|
560
|
+
"marketing": false,
|
|
561
|
+
"analytics": false,
|
|
562
|
+
"personalization": false,
|
|
563
|
+
"essential": true
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
```
|
|
584
567
|
|
|
585
|
-
|
|
568
|
+
#### Privacy & Security Features
|
|
586
569
|
|
|
587
|
-
|
|
570
|
+
**IP Anonymization**
|
|
588
571
|
|
|
589
|
-
|
|
572
|
+
* All IP addresses are automatically anonymized by setting the last octet to "0"
|
|
573
|
+
* Example: `192.168.1.123` becomes `192.168.1.0`
|
|
574
|
+
* This provides location data while protecting user privacy
|
|
590
575
|
|
|
591
|
-
|
|
576
|
+
**Unique Consent IDs**
|
|
592
577
|
|
|
593
|
-
|
|
578
|
+
* Each consent record gets a unique 28-character identifier
|
|
579
|
+
* Generated using SHA-256 hash of timestamp + anonymized IP
|
|
580
|
+
* Enables tracking consent changes over time while maintaining privacy
|
|
594
581
|
|
|
595
|
-
|
|
596
|
-
- **Browser Caching:** Browsers also cache content locally to improve page load times. If a user has recently visited your site, their browser might have cached the old version of your script, and it could take some time before the browser checks for an updated version.
|
|
582
|
+
**Database Security**
|
|
597
583
|
|
|
598
|
-
|
|
584
|
+
* Row-level security (RLS) enabled on all tables
|
|
585
|
+
* Anonymous users can only INSERT records (no SELECT/UPDATE/DELETE)
|
|
586
|
+
* Consent retrieval requires specific function calls with proper permissions
|
|
599
587
|
|
|
600
|
-
|
|
588
|
+
#### Compliance Benefits
|
|
601
589
|
|
|
602
|
-
|
|
590
|
+
**Audit Trail**
|
|
603
591
|
|
|
604
|
-
|
|
592
|
+
* Complete record of all consent decisions
|
|
593
|
+
* Timestamped entries for regulatory compliance
|
|
594
|
+
* Detailed interaction metadata for transparency
|
|
605
595
|
|
|
606
|
-
|
|
596
|
+
**Data Subject Rights**
|
|
607
597
|
|
|
608
|
-
|
|
598
|
+
* Users can request their consent records using their consent ID
|
|
599
|
+
* Records can be exported for data portability requests
|
|
600
|
+
* Clear consent withdrawal tracking
|
|
609
601
|
|
|
610
|
-
|
|
611
|
-
- In the Traditional script import method, for each script tag `src` you would add `"https://cdn.jsdelivr.net/npm/@your-npm-username/your-package-name@version/your-filename.js"`
|
|
612
|
-
- Similarly, for each style tag `href` you would add `"https://cdn.jsdelivr.net/npm/@your-npm-username/your-package-name@version/your-filename.css"`.
|
|
602
|
+
**Regulatory Reporting**
|
|
613
603
|
|
|
614
|
-
|
|
604
|
+
* Structured data format for compliance reporting
|
|
605
|
+
* Geographic region tracking for multi-jurisdictional compliance
|
|
606
|
+
* Detailed consent method tracking for audit purposes
|
|
615
607
|
|
|
616
|
-
|
|
608
|
+
#### Accessing Consent Records
|
|
617
609
|
|
|
618
|
-
|
|
610
|
+
**For Users (ZONE\_3/GDPR)**
|
|
619
611
|
|
|
620
|
-
|
|
612
|
+
Users in GDPR regions can view their consent ID and timestamp directly in the consent banner after making a choice.
|
|
621
613
|
|
|
622
|
-
|
|
614
|
+
**For Administrators**
|
|
623
615
|
|
|
624
|
-
|
|
616
|
+
Use the Supabase dashboard to query consent records. You can run any of these queries as needed:
|
|
625
617
|
|
|
626
|
-
|
|
618
|
+
```sql
|
|
619
|
+
-- Get all consent records for a specific date range
|
|
620
|
+
SELECT * FROM consents
|
|
621
|
+
WHERE action_date >= '2024-01-01'
|
|
622
|
+
AND action_date < '2024-02-01';
|
|
623
|
+
```
|
|
627
624
|
|
|
628
|
-
|
|
625
|
+
```sql
|
|
626
|
+
-- Get consent records by region
|
|
627
|
+
SELECT * FROM consents
|
|
628
|
+
WHERE geo_region = 'ZONE_3';
|
|
629
|
+
```
|
|
629
630
|
|
|
630
|
-
|
|
631
|
+
```sql
|
|
632
|
+
-- Get specific user's consent history
|
|
633
|
+
SELECT * FROM consents
|
|
634
|
+
WHERE consent_id = 'USER_CONSENT_ID';
|
|
635
|
+
```
|
|
631
636
|
|
|
632
|
-
|
|
637
|
+
```sql
|
|
638
|
+
-- Get latest consent for a specific user
|
|
639
|
+
SELECT * FROM get_consent_by_id('USER_CONSENT_ID');
|
|
640
|
+
```
|
|
633
641
|
|
|
634
|
-
|
|
642
|
+
***
|
|
635
643
|
|
|
636
|
-
|
|
637
|
-
- Click on the current branch at the top of the application to view all available branches.
|
|
638
|
-
- Choose “New branch”, name it "dev", and click “Create Branch”.
|
|
639
|
-
- Push the new branch to the remote repository by clicking on “Publish branch”.
|
|
644
|
+
### Consent Categories
|
|
640
645
|
|
|
641
|
-
|
|
646
|
+
CookieFlow™ manages consent across four main categories:
|
|
642
647
|
|
|
643
|
-
|
|
644
|
-
Your local files will now reflect the state of the `dev` branch. Note that this state is preserved even if you close and reopen GitHub Desktop.
|
|
645
|
-
Develop, commit your changes, and push your commits to the `dev` branch.
|
|
648
|
+
#### 1. Marketing Cookies
|
|
646
649
|
|
|
647
|
-
|
|
650
|
+
**Purpose**: Used for advertising and tracking across websites\
|
|
651
|
+
**Includes**: Social media pixels, retargeting pixels, advertising cookies\
|
|
652
|
+
**Control**: Users can enable or disable this category
|
|
648
653
|
|
|
649
|
-
|
|
650
|
-
Stashing temporarily sets aside your changes, allowing you to switch branches and work on something else. When you’re ready, you can come back and apply your stashed changes.
|
|
654
|
+
#### 2. Analytics Cookies
|
|
651
655
|
|
|
652
|
-
|
|
656
|
+
**Purpose**: Used to understand how visitors interact with your site\
|
|
657
|
+
**Includes**: Google Analytics, Webflow Analytics, heatmap tools\
|
|
658
|
+
**Control**: Users can enable or disable this category
|
|
653
659
|
|
|
654
|
-
|
|
660
|
+
#### 3. Personalization Cookies
|
|
655
661
|
|
|
656
|
-
|
|
657
|
-
|
|
662
|
+
**Purpose**: Used to remember user preferences and personalize experience\
|
|
663
|
+
**Includes**: Language preferences, theme preferences, saved settings\
|
|
664
|
+
**Control**: Users can enable or disable this category
|
|
658
665
|
|
|
659
|
-
|
|
666
|
+
#### 4. Essential Cookies (Always On)
|
|
660
667
|
|
|
661
|
-
|
|
668
|
+
**Purpose**: Necessary for website functionality\
|
|
669
|
+
**Includes**: Authentication, security, site functionality\
|
|
670
|
+
**Control**: Cannot be disabled—required for site to function
|
|
662
671
|
|
|
663
|
-
|
|
672
|
+
***
|
|
664
673
|
|
|
665
|
-
|
|
674
|
+
### Adding Project Scripts
|
|
666
675
|
|
|
667
|
-
|
|
668
|
-
All developers should clone the repository to their local machines using GitHub Desktop:
|
|
676
|
+
Once CookieFlow™ is set up, you need to configure your existing scripts to respect user consent preferences. CookieFlow™ provides two methods for script integration:
|
|
669
677
|
|
|
670
|
-
|
|
671
|
-
- Go to “File” > “Clone Repository” and select the repository from the list.
|
|
672
|
-
- Choose the local path for the repository and click “Clone”.
|
|
673
|
-
- Run `pnpm install` to install project dependencies.
|
|
678
|
+
#### Method 1: Adding Scripts Directly in Webflow
|
|
674
679
|
|
|
675
|
-
|
|
680
|
+
This method is ideal if you manage scripts directly within your Webflow project using embed elements or custom code.
|
|
676
681
|
|
|
677
|
-
|
|
678
|
-
In GitHub Desktop:
|
|
682
|
+
**How It Works**
|
|
679
683
|
|
|
680
|
-
|
|
681
|
-
- Click on the current branch at the top, select “New Branch”, name it according to the feature or fix you are working on, and click “Create Branch”.
|
|
682
|
-
- Publish the branch to the remote repository by clicking “Publish branch”.
|
|
684
|
+
CookieFlow™ uses HTML attributes to control when scripts load based on user consent. Add the appropriate attributes to all your project scripts:
|
|
683
685
|
|
|
684
|
-
|
|
686
|
+
**Important: Remove `<noscript>` Tags for Compliance**
|
|
685
687
|
|
|
686
|
-
|
|
687
|
-
Commit your changes in GitHub Desktop:
|
|
688
|
+
**Remove `<noscript>` tags for compliance**: When adding any tracking scripts directly in Webflow, ensure that no `<noscript>` tags are included. If any of your existing scripts contain `<noscript>` tags, remove them as they will bypass consent management and violate compliance requirements.
|
|
688
689
|
|
|
689
|
-
|
|
690
|
-
- Click “Commit to [your-branch-name]”.
|
|
691
|
-
- Push your commits to the remote repository by clicking “Push origin”.
|
|
690
|
+
**Example of what NOT to add** (Google Tag Manager `<noscript>` tag):
|
|
692
691
|
|
|
693
|
-
|
|
692
|
+
```html
|
|
693
|
+
<!-- Google Tag Manager (noscript) -->
|
|
694
|
+
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXX"
|
|
695
|
+
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
|
|
696
|
+
<!-- End Google Tag Manager (noscript) -->
|
|
697
|
+
```
|
|
694
698
|
|
|
695
|
-
|
|
699
|
+
This `<noscript>` tag loads tracking scripts even when JavaScript is disabled, completely bypassing consent management and violating privacy regulations.
|
|
696
700
|
|
|
697
|
-
|
|
698
|
-
- Team members review the code, suggest changes, and discuss implementations.
|
|
699
|
-
- After approval, **merge** the branch into `dev`.
|
|
701
|
+
**Essential Scripts**
|
|
700
702
|
|
|
701
|
-
|
|
703
|
+
**Attribute**: `rd-cookieflow="essential"`\
|
|
704
|
+
**Use for**: Authentication, security, payment processing, accessibility scripts, form validation, load balancing, privacy & consent management
|
|
702
705
|
|
|
703
|
-
|
|
706
|
+
```html
|
|
707
|
+
<!-- Stripe JS Library -->
|
|
708
|
+
<script rd-cookieflow="essential" src="https://js.stripe.com/v3/"></script>
|
|
704
709
|
|
|
705
|
-
|
|
710
|
+
<!-- Authentication Script -->
|
|
711
|
+
<script rd-cookieflow="essential">
|
|
712
|
+
// Your authentication code here
|
|
713
|
+
</script>
|
|
714
|
+
```
|
|
706
715
|
|
|
707
|
-
|
|
708
|
-
- Click “Fetch origin” to retrieve the latest changes from the remote repository. If there are new commits on the remote `dev` branch, GitHub Desktop will show an option to “Pull origin”. Click this button to update your local `dev` branch.
|
|
716
|
+
**Analytics Scripts**
|
|
709
717
|
|
|
710
|
-
|
|
718
|
+
**Attribute**: `type="disabled" rd-cookieflow="analytics"`\
|
|
719
|
+
**Use for**: Google Analytics, Hotjar, tracking and recording scripts, heatmaps, Microsoft Clarity, Adobe Analytics
|
|
711
720
|
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
721
|
+
```html
|
|
722
|
+
<!-- Google Analytics 4 -->
|
|
723
|
+
<script type="disabled" rd-cookieflow="analytics" async src="https://www.googletagmanager.com/gtag/js?id=YOURGA4ID"></script>
|
|
724
|
+
<script type="disabled" rd-cookieflow="analytics">
|
|
725
|
+
window.dataLayer = window.dataLayer || [];
|
|
726
|
+
function gtag(){dataLayer.push(arguments);}
|
|
727
|
+
gtag('js', new Date());
|
|
728
|
+
gtag('config', 'YOURGA4ID');
|
|
729
|
+
</script>
|
|
716
730
|
|
|
717
|
-
|
|
731
|
+
<!-- Hotjar -->
|
|
732
|
+
<script type="disabled" rd-cookieflow="analytics">
|
|
733
|
+
(function(h,o,t,j,a,r){
|
|
734
|
+
h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};
|
|
735
|
+
h._hjSettings={hjid:YOUR_HOTJAR_ID,hjsv:6};
|
|
736
|
+
a=o.getElementsByTagName('head')[0];
|
|
737
|
+
r=o.createElement('script');r.async=1;
|
|
738
|
+
r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv;
|
|
739
|
+
a.appendChild(r);
|
|
740
|
+
})(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv=');
|
|
741
|
+
</script>
|
|
742
|
+
```
|
|
718
743
|
|
|
719
|
-
|
|
720
|
-
|
|
744
|
+
**Marketing Scripts**
|
|
745
|
+
|
|
746
|
+
**Attribute**: `type="disabled" rd-cookieflow="marketing"`\
|
|
747
|
+
**Use for**: Tracking pixels, advertising tags, social media integration scripts, retargeting cookies, affiliate tracking, marketing automation
|
|
748
|
+
|
|
749
|
+
```html
|
|
750
|
+
<!-- Meta Pixel Code -->
|
|
751
|
+
<script type="disabled" rd-cookieflow="marketing">
|
|
752
|
+
!function(f,b,e,v,n,t,s)
|
|
753
|
+
{if(f.fbq)return;n=f.fbq=function(){n.callMethod?
|
|
754
|
+
n.callMethod.apply(n,arguments):n.queue.push(arguments)};
|
|
755
|
+
if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
|
|
756
|
+
n.queue=[];t=b.createElement(e);t.async=!0;
|
|
757
|
+
t.src=v;s=b.getElementsByTagName(e)[0];
|
|
758
|
+
s.parentNode.insertBefore(t,s)}(window, document,'script',
|
|
759
|
+
'https://connect.facebook.net/en_US/fbevents.js');
|
|
760
|
+
fbq('init', 'YOUR_PIXEL_ID');
|
|
761
|
+
fbq('track', 'PageView');
|
|
762
|
+
</script>
|
|
721
763
|
|
|
722
|
-
|
|
764
|
+
<!-- Google Ads Conversion Tracking -->
|
|
765
|
+
<script type="disabled" rd-cookieflow="marketing">
|
|
766
|
+
gtag('event', 'conversion', {
|
|
767
|
+
'send_to': 'AW-CONVERSION_ID/CONVERSION_LABEL',
|
|
768
|
+
'value': 1.0,
|
|
769
|
+
'currency': 'USD'
|
|
770
|
+
});
|
|
771
|
+
</script>
|
|
772
|
+
```
|
|
723
773
|
|
|
724
|
-
|
|
774
|
+
**Personalization Scripts**
|
|
725
775
|
|
|
726
|
-
|
|
776
|
+
**Attribute**: `type="disabled" rd-cookieflow="personalization"`\
|
|
777
|
+
**Use for**: Language preferences, theme or appearance, recommendations, user profile customization, behavioral segmentation, geo-targeting
|
|
727
778
|
|
|
728
|
-
|
|
729
|
-
|
|
779
|
+
```html
|
|
780
|
+
<!-- Language Preference Script -->
|
|
781
|
+
<script type="disabled" rd-cookieflow="personalization">
|
|
782
|
+
function setLanguagePreference(lang) {
|
|
783
|
+
localStorage.setItem('preferred-language', lang);
|
|
784
|
+
document.documentElement.lang = lang;
|
|
785
|
+
}
|
|
786
|
+
</script>
|
|
730
787
|
|
|
731
|
-
|
|
788
|
+
<!-- Theme Customization Script -->
|
|
789
|
+
<script type="disabled" rd-cookieflow="personalization">
|
|
790
|
+
function applyUserTheme(theme) {
|
|
791
|
+
document.body.className = theme;
|
|
792
|
+
localStorage.setItem('user-theme', theme);
|
|
793
|
+
}
|
|
794
|
+
</script>
|
|
795
|
+
```
|
|
732
796
|
|
|
733
|
-
|
|
797
|
+
**Important Notes for Webflow Integration**
|
|
734
798
|
|
|
735
|
-
|
|
736
|
-
|
|
799
|
+
1. **Add attributes to embed elements**: In Webflow, when adding scripts via embed elements, include the attributes in the opening `<script>` tag
|
|
800
|
+
2. **Scripts load automatically**: Once users give consent, CookieFlow™ automatically enables the appropriate scripts
|
|
801
|
+
3. **Essential scripts always load**: Scripts with `rd-cookieflow="essential"` load immediately without requiring consent
|
|
737
802
|
|
|
738
|
-
|
|
803
|
+
***
|
|
739
804
|
|
|
740
|
-
|
|
805
|
+
#### Method 2: Adding Scripts via Google Tag Manager
|
|
741
806
|
|
|
742
|
-
|
|
743
|
-
- Pull the changes by clicking “Pull origin” (if there are new commits to pull).
|
|
744
|
-
- Run `npm ship` to publish the new version to npm.
|
|
807
|
+
This method is recommended if you use Google Tag Manager to manage your website scripts and tracking.
|
|
745
808
|
|
|
746
|
-
|
|
809
|
+
**Prerequisites**
|
|
747
810
|
|
|
748
|
-
|
|
811
|
+
**Remove `<noscript>` tags for compliance**: When installing Google Tag Manager, do not add the `<noscript>` tag after the opening `<body>` tag. If you already have Google Tag Manager installed, remove that part from Webflow.
|
|
749
812
|
|
|
750
|
-
|
|
813
|
+
**Step 1: Set Up Triggers in Google Tag Manager**
|
|
751
814
|
|
|
752
|
-
|
|
815
|
+
Go to **Workspace → Triggers** and click **New** to create triggers for each consent category:
|
|
753
816
|
|
|
754
|
-
|
|
817
|
+
**Essential Cookie Trigger**
|
|
755
818
|
|
|
756
|
-
|
|
819
|
+
* **Name**: `Essential Cookie Activated`
|
|
820
|
+
* **Type**: Other → Custom Event
|
|
821
|
+
* **Event Name**: `essential-activated`
|
|
822
|
+
* **Fires On**: Some Custom Events
|
|
823
|
+
* **Condition**: Event equals `essential-activated`
|
|
757
824
|
|
|
758
|
-
|
|
759
|
-
- [Step 1: Setup Template](#step-1-setup-template2)
|
|
760
|
-
- [Step 2: Setup Public SSH Key](#step-2-setup-public-ssh-key-first-time-only2)
|
|
761
|
-
- [Step 3: Setup Private SSH Key](#step-3-setup-private-ssh-key-for-every-new-project2)
|
|
762
|
-
- [Step 4: Setup NPM](#step-4-setup-npm2)
|
|
763
|
-
- [Step 5: Setup Your Project](#step-5-setup-your-project2)
|
|
764
|
-
- [How to use DevKit](#how-to-use-devkit2)
|
|
765
|
-
- [Building & Testing](#building-testing2)
|
|
766
|
-
- [Importing Scripts](#importing-scripts-in-webflow2)
|
|
767
|
-
- [Shipping to NPM](#shipping-to-npm2)
|
|
768
|
-
- [Addressing Version Caching](#addressing-version-caching2)
|
|
769
|
-
- [Working with Branches & Contributing](#working-with-branches2)
|
|
825
|
+
**Analytics Cookie Trigger**
|
|
770
826
|
|
|
771
|
-
|
|
827
|
+
* **Name**: `Analytics Cookie Activated`
|
|
828
|
+
* **Type**: Other → Custom Event
|
|
829
|
+
* **Event Name**: `analytics-activated`
|
|
830
|
+
* **Fires On**: Some Custom Events
|
|
831
|
+
* **Condition**: Event equals `analytics-activated`
|
|
772
832
|
|
|
773
|
-
|
|
833
|
+
**Marketing Cookie Trigger**
|
|
774
834
|
|
|
775
|
-
|
|
835
|
+
* **Name**: `Marketing Cookie Activated`
|
|
836
|
+
* **Type**: Other → Custom Event
|
|
837
|
+
* **Event Name**: `marketing-activated`
|
|
838
|
+
* **Fires On**: Some Custom Events
|
|
839
|
+
* **Condition**: Event equals `marketing-activated`
|
|
776
840
|
|
|
777
|
-
|
|
841
|
+
**Personalization Cookie Trigger**
|
|
778
842
|
|
|
779
|
-
|
|
780
|
-
|
|
843
|
+
* **Name**: `Personalization Cookie Activated`
|
|
844
|
+
* **Type**: Other → Custom Event
|
|
845
|
+
* **Event Name**: `personalization-activated`
|
|
846
|
+
* **Fires On**: Some Custom Events
|
|
847
|
+
* **Condition**: Event equals `personalization-activated`
|
|
781
848
|
|
|
782
|
-
|
|
849
|
+
**Step 2: Configure Your Tags**
|
|
783
850
|
|
|
784
|
-
|
|
851
|
+
For each existing or new tag in Google Tag Manager:
|
|
785
852
|
|
|
786
|
-
|
|
853
|
+
**Essential Scripts**
|
|
787
854
|
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
```
|
|
855
|
+
* **Trigger**: Essential Cookie Activated
|
|
856
|
+
* **Use for**: Authentication, security, payment processing, accessibility scripts, form validation, load balancing, privacy & consent management
|
|
791
857
|
|
|
792
|
-
|
|
858
|
+
**Analytics Scripts**
|
|
793
859
|
|
|
794
|
-
|
|
860
|
+
* **Trigger**: Analytics Cookie Activated
|
|
861
|
+
* **Use for**: Google Analytics, Hotjar, tracking and recording scripts, heatmaps, Microsoft Clarity, Adobe Analytics
|
|
795
862
|
|
|
796
|
-
|
|
797
|
-
Run ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
|
|
798
|
-
```
|
|
863
|
+
**Marketing Scripts**
|
|
799
864
|
|
|
800
|
-
|
|
865
|
+
* **Trigger**: Marketing Cookie Activated
|
|
866
|
+
* **Use for**: Tracking pixels, advertising tags, social media integration scripts, retargeting cookies, affiliate tracking, marketing automation
|
|
801
867
|
|
|
802
|
-
|
|
803
|
-
eval "$(ssh-agent -s)"
|
|
804
|
-
ssh-add ~/.ssh/id_rsa
|
|
805
|
-
```
|
|
868
|
+
**Personalization Scripts**
|
|
806
869
|
|
|
807
|
-
|
|
870
|
+
* **Trigger**: Personalization Cookie Activated
|
|
871
|
+
* **Use for**: Language preferences, theme or appearance, recommendations, user profile customization, behavioral segmentation, geo-targeting
|
|
808
872
|
|
|
809
|
-
|
|
810
|
-
cat ~/.ssh/id_rsa.pub | pbcopy
|
|
811
|
-
```
|
|
873
|
+
**Step 3: Add Advanced Consent Settings**
|
|
812
874
|
|
|
813
|
-
|
|
875
|
+
For each tag, go to **Tag Configuration → Advanced Settings → Consent Settings** and select **Require additional consent for tag to fire**:
|
|
814
876
|
|
|
815
|
-
|
|
816
|
-
cat ~/.ssh/id_rsa.pub
|
|
817
|
-
```
|
|
877
|
+
**Essential Scripts**
|
|
818
878
|
|
|
819
|
-
|
|
879
|
+
* **Required Consent**: `security_storage`
|
|
820
880
|
|
|
821
|
-
|
|
881
|
+
**Analytics Scripts**
|
|
822
882
|
|
|
823
|
-
|
|
883
|
+
* **Required Consent**: `analytics_storage`
|
|
824
884
|
|
|
825
|
-
|
|
885
|
+
**Marketing Scripts**
|
|
826
886
|
|
|
827
|
-
|
|
887
|
+
* **Required Consent**: `ad_storage`
|
|
828
888
|
|
|
829
|
-
|
|
830
|
-
cat ~/.ssh/id_rsa | pbcopy
|
|
831
|
-
```
|
|
889
|
+
**Personalization Scripts**
|
|
832
890
|
|
|
833
|
-
|
|
891
|
+
* **Required Consent**: `personalization_storage` and `functionality_storage`
|
|
834
892
|
|
|
835
|
-
|
|
836
|
-
cat ~/.ssh/id_rsa
|
|
837
|
-
```
|
|
893
|
+
**Step 4: Publish & Test**
|
|
838
894
|
|
|
839
|
-
|
|
840
|
-
|
|
895
|
+
1. **Publish**: Click **Submit**, name your version, and hit **Publish**
|
|
896
|
+
2. **Test**: Click **Preview**, enter your website URL to initiate test mode
|
|
897
|
+
3. **Verify**: By default, you should only see essential tags firing without further consent
|
|
898
|
+
4. **Test Consent**: Toggle different cookie types on your previewed website to verify their respective tags fire correctly
|
|
841
899
|
|
|
842
|
-
|
|
900
|
+
**Troubleshooting GTM Integration**
|
|
843
901
|
|
|
844
|
-
|
|
902
|
+
* **Tags not firing**: Check that triggers are properly configured and attached to tags
|
|
903
|
+
* **Consent not working**: Verify that advanced consent settings are properly configured
|
|
904
|
+
* **Essential scripts not loading**: Ensure essential tags have the correct trigger and consent settings
|
|
845
905
|
|
|
846
|
-
|
|
847
|
-
- Create NPM Access Token: Generate a classic token, automation type, named descriptively.
|
|
848
|
-
- Copy NPM Token: Ensure you've copied it; it’s not retrievable later.
|
|
849
|
-
- Add Token to GitHub as Secret: In your project’s GitHub settings, under Secrets and variables, add a new secret named `NPM_TOKEN` and paste the token.
|
|
906
|
+
***
|
|
850
907
|
|
|
851
|
-
|
|
908
|
+
## Manual Setup
|
|
852
909
|
|
|
853
|
-
###
|
|
910
|
+
### Setup Guide
|
|
854
911
|
|
|
855
|
-
|
|
912
|
+
If you prefer to build your own UI or need to customize the implementation beyond the prebuilt component, you can manually set up CookieFlow™ by adding the required HTML elements and attributes to your Webflow project.
|
|
856
913
|
|
|
857
|
-
|
|
858
|
-
npm install -g pnpm
|
|
859
|
-
```
|
|
914
|
+
#### Quick Start
|
|
860
915
|
|
|
861
|
-
|
|
916
|
+
1. Add the CookieFlow™ script to your Webflow project
|
|
917
|
+
2. Create the required HTML elements in your Webflow project
|
|
918
|
+
3. Add the necessary attributes to each element
|
|
919
|
+
4. Customize the styling to match your brand
|
|
862
920
|
|
|
863
|
-
|
|
864
|
-
pnpm install
|
|
865
|
-
```
|
|
921
|
+
***
|
|
866
922
|
|
|
867
|
-
|
|
923
|
+
### Adding the Script
|
|
868
924
|
|
|
869
|
-
|
|
925
|
+
Add the following script to your Webflow project's **global settings**, inside the `<head>` tag:
|
|
870
926
|
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
```
|
|
878
|
-
pnpm dev
|
|
927
|
+
```html
|
|
928
|
+
<script
|
|
929
|
+
src="https://cdn.jsdelivr.net/npm/@reform-digital/cookie-flow@1.3.8/prod/index.js"
|
|
930
|
+
rd-consent-storage-url="YOUR_SUPABASE_URL"
|
|
931
|
+
rd-consent-storage-api="YOUR_SUPABASE_API_KEY"
|
|
932
|
+
></script>
|
|
879
933
|
```
|
|
880
934
|
|
|
881
|
-
|
|
935
|
+
#### What's Next?
|
|
882
936
|
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
<a name="importing-scripts-in-webflow2"></a>
|
|
937
|
+
* **Configure your Supabase database**: Follow the [Supabase Setup](#-supabase-setup) guide in Option 1
|
|
938
|
+
* **Learn about script attributes**: See the [Script Configuration](#-script-configuration) section for all available attributes and customization options
|
|
939
|
+
* **Understand regional compliance**: Check the [Regional Compliance Overview](#regional-compliance-overview) section to learn how CookieFlow™ adapts to different regions
|
|
888
940
|
|
|
889
|
-
|
|
941
|
+
***
|
|
890
942
|
|
|
891
|
-
###
|
|
943
|
+
### Elements & Attributes
|
|
892
944
|
|
|
893
|
-
|
|
894
|
-
- Script Logging: DevKit logs script tags for JavaScript and CSS files from the src folder.
|
|
895
|
-
- Integration: Manually copy and paste script tags to your Webflow pages or global settings, being mindful to switch between development and production tags as needed.
|
|
945
|
+
CookieFlow™ uses **HTML data attributes** to identify and control UI elements. These attributes start with `rd-cookieflow` (Reform Digital CookieFlow).
|
|
896
946
|
|
|
897
|
-
|
|
947
|
+
#### Core Components
|
|
898
948
|
|
|
899
|
-
|
|
949
|
+
**1. Wrapper Element**
|
|
900
950
|
|
|
901
|
-
|
|
951
|
+
**Purpose**: Contains all CookieFlow™ components\
|
|
952
|
+
**Attribute**: `rd-cookieflow="wrapper"`
|
|
902
953
|
|
|
903
|
-
```
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
window.devMode = true; // Change to false in production
|
|
908
|
-
window.classViewer = true; // Helper to display classes and ids in DevMode
|
|
909
|
-
window.localPort = 3000; // Also change in bin/localport.js in VS Code
|
|
910
|
-
</script>
|
|
954
|
+
```html
|
|
955
|
+
<div rd-cookieflow="wrapper">
|
|
956
|
+
<!-- All other components go inside here -->
|
|
957
|
+
</div>
|
|
911
958
|
```
|
|
912
959
|
|
|
913
|
-
|
|
960
|
+
**2. Manager Component**
|
|
914
961
|
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
```
|
|
962
|
+
**Purpose**: Small button/floating element that allows users to reopen the consent interface\
|
|
963
|
+
**Attribute**: `rd-cookieflow="manager"`\
|
|
964
|
+
**Additional**: Add `rd-cookieflow="manager-interaction"` to control show/hide state
|
|
919
965
|
|
|
920
|
-
|
|
966
|
+
**Position**: Typically positioned as a floating button, often in the bottom-right corner
|
|
921
967
|
|
|
922
|
-
|
|
923
|
-
<!-- RD® Webflow DevKit / Script Loader -->
|
|
924
|
-
<script src="https://cdn.jsdelivr.net/npm/@reform-digital/webflow-devkit-utils@1.1.0/prod/script-loader.js"></script>
|
|
925
|
-
```
|
|
968
|
+
**3. Banner Components**
|
|
926
969
|
|
|
927
|
-
|
|
970
|
+
**Purpose**: Display consent options to users when they first visit
|
|
928
971
|
|
|
929
|
-
|
|
972
|
+
There are **three banner types**, one for each compliance zone:
|
|
930
973
|
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
const pageScripts = ["home.js"];
|
|
935
|
-
loadWebflowScripts(pageScripts, npmPath);
|
|
936
|
-
</script>
|
|
937
|
-
```
|
|
974
|
+
* **Banner Zone 1** (Basic Notice): `rd-cookieflow="banner-zone-one"`
|
|
975
|
+
* **Banner Zone 2** (Opt-Out/CCPA): `rd-cookieflow="banner-zone-two"`
|
|
976
|
+
* **Banner Zone 3** (Opt-In/GDPR): `rd-cookieflow="banner-zone-three"`
|
|
938
977
|
|
|
939
|
-
|
|
978
|
+
**Important**: All three banners are hidden by default. CookieFlow™ will automatically remove the banners that don't apply to the user's location.
|
|
940
979
|
|
|
941
|
-
|
|
942
|
-
<!-- RD® Webflow DevKit / Page Styles -->
|
|
943
|
-
<script>
|
|
944
|
-
const pageStyles = ["home.css"];
|
|
945
|
-
loadWebflowStylesheets(pageStyles, npmPath);
|
|
946
|
-
</script>
|
|
947
|
-
```
|
|
980
|
+
**Additional**: Add `rd-cookieflow="banner-interaction"` to control show/hide state
|
|
948
981
|
|
|
949
|
-
|
|
982
|
+
**4. Settings/Preferences Component**
|
|
950
983
|
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
<!-- RD® Webflow DevKit / Global Scripts -->
|
|
955
|
-
<script>
|
|
956
|
-
const globalScripts = ["global.js", "analytics.js"];
|
|
957
|
-
loadWebflowScripts(globalScripts, npmPath);
|
|
958
|
-
</script>
|
|
959
|
-
```
|
|
984
|
+
**Purpose**: Detailed consent management modal where users can customize their preferences\
|
|
985
|
+
**Attribute**: `rd-cookieflow="settings"`\
|
|
986
|
+
**Additional**: Add `rd-cookieflow="preferences-interaction"` to control show/hide state
|
|
960
987
|
|
|
961
|
-
|
|
988
|
+
**Components Inside Settings**:
|
|
962
989
|
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
loadWebflowStylesheets(globalStyles, npmPath);
|
|
968
|
-
</script>
|
|
969
|
-
```
|
|
990
|
+
* Header text
|
|
991
|
+
* Consent category toggles
|
|
992
|
+
* Action buttons (Accept All, Reject All, Accept Selected)
|
|
993
|
+
* Close button
|
|
970
994
|
|
|
971
|
-
|
|
995
|
+
**5. Consent Info Banner (GDPR Only)**
|
|
972
996
|
|
|
973
|
-
|
|
997
|
+
**Purpose**: Displays consent ID and information about cookies for GDPR users\
|
|
998
|
+
**Attribute**: `rd-cookieflow="consent-banner"`\
|
|
999
|
+
**Additional**: Add `rd-cookieflow="consent-interaction"` to control show/hide state
|
|
974
1000
|
|
|
975
|
-
|
|
976
|
-
pnpm ship
|
|
977
|
-
```
|
|
1001
|
+
#### Essential UI Elements Within Components
|
|
978
1002
|
|
|
979
|
-
|
|
1003
|
+
**Consent Buttons**
|
|
980
1004
|
|
|
981
|
-
|
|
1005
|
+
All consent-related buttons need these attributes:
|
|
982
1006
|
|
|
983
|
-
|
|
1007
|
+
* **Accept All**: `rd-cookieflow="accept"`
|
|
1008
|
+
* **Reject All**: `rd-cookieflow="reject"`
|
|
1009
|
+
* **Custom/Selected**: `rd-cookieflow="accept-selected"`
|
|
1010
|
+
* **Open Settings**: `rd-cookieflow="open-settings"`
|
|
1011
|
+
* **Close**: `rd-cookieflow="close"`
|
|
984
1012
|
|
|
985
|
-
|
|
1013
|
+
**Consent Checkboxes**
|
|
986
1014
|
|
|
987
|
-
|
|
1015
|
+
For the settings/preferences modal, add checkboxes for each consent category:
|
|
988
1016
|
|
|
989
|
-
|
|
1017
|
+
* **Marketing Cookies**:
|
|
1018
|
+
* Checkbox: `rd-cookieflow="marketing-checkbox"`
|
|
1019
|
+
* Toggle interaction: `rd-cookieflow="toggle-interaction"` (inside the checkbox container)
|
|
1020
|
+
* State display: `rd-cookieflow="marketing-state"` (to show On/Off text)
|
|
1021
|
+
* **Analytics Cookies**:
|
|
1022
|
+
* Checkbox: `rd-cookieflow="analytics-checkbox"`
|
|
1023
|
+
* Toggle interaction: `rd-cookieflow="toggle-interaction"` (inside the checkbox container)
|
|
1024
|
+
* State display: `rd-cookieflow="analytics-state"` (to show On/Off text)
|
|
1025
|
+
* **Personalization Cookies**:
|
|
1026
|
+
* Checkbox: `rd-cookieflow="personalization-checkbox"`
|
|
1027
|
+
* Toggle interaction: `rd-cookieflow="toggle-interaction"` (inside the checkbox container)
|
|
1028
|
+
* State display: `rd-cookieflow="personalization-state"` (to show On/Off text)
|
|
990
1029
|
|
|
991
|
-
|
|
992
|
-
<script src="https://cdn.jsdelivr.net/npm/@your-npm-username/your-package-name@version/your-filename.js"></script>
|
|
993
|
-
```
|
|
1030
|
+
**Scroll Lock Attribute**
|
|
994
1031
|
|
|
995
|
-
|
|
1032
|
+
To prevent page scrolling when the settings modal is open, add this attribute to the settings component container:
|
|
996
1033
|
|
|
1034
|
+
```html
|
|
1035
|
+
<div rd-cookieflow-scroll="disabled">
|
|
1036
|
+
<!-- Settings modal content -->
|
|
1037
|
+
</div>
|
|
997
1038
|
```
|
|
998
|
-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@your-npm-username/your-package-name@version/your-filename.css">
|
|
999
|
-
```
|
|
1000
|
-
|
|
1001
|
-
<a name="addressing-version-caching2"></a>
|
|
1002
|
-
|
|
1003
|
-
## 🔄 Addressing Version Caching
|
|
1004
|
-
|
|
1005
|
-
### @latest Versioning
|
|
1006
|
-
|
|
1007
|
-
- Initial Release: @latest (or omitting @version) is ok for initial release.
|
|
1008
|
-
- Subsequent Releases: @latest might lead to outdated content due to CDN and browser caching.
|
|
1009
|
-
|
|
1010
|
-
### Cache Management
|
|
1011
|
-
|
|
1012
|
-
- CDN Cache: Manually purge via [jsDelivr’s Purge Tool](https://www.jsdelivr.com/tools/purge).
|
|
1013
|
-
- Browser Cache: Educate users; no direct control, can only hard refresh or clear own browser cache.
|
|
1014
|
-
|
|
1015
|
-
### Use Specific Versions to Prevent Caching Issues
|
|
1016
|
-
|
|
1017
|
-
- Automated Import: npm path `"@your-npm-username/your-package-name@version"`
|
|
1018
|
-
- Traditional Import: src path `"https://cdn.jsdelivr.net/npm/@your-npm-username/your-package-name@version/your-filename.js"`
|
|
1019
|
-
|
|
1020
|
-
<a name="working-with-branches2"></a>
|
|
1021
|
-
|
|
1022
|
-
## 🔀 Working with Branches & Contributing
|
|
1023
|
-
|
|
1024
|
-
### Single Developer Workflow
|
|
1025
1039
|
|
|
1026
|
-
|
|
1027
|
-
- **Creating a Dev Branch:** After initial release, create a dev branch.
|
|
1028
|
-
- **Routine Development:** Work in dev, commit changes, push commits.
|
|
1029
|
-
- **Merging and Releasing:** Merge dev into main, publish to npm.
|
|
1040
|
+
#### Example Structure
|
|
1030
1041
|
|
|
1031
|
-
|
|
1042
|
+
Here's an example of a complete CookieFlow™ structure:
|
|
1032
1043
|
|
|
1033
|
-
|
|
1034
|
-
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
-
|
|
1038
|
-
-
|
|
1039
|
-
|
|
1040
|
-
- **Shipping to npm:** Switch to main, fetch latest, pull changes, publish to npm.
|
|
1044
|
+
```html
|
|
1045
|
+
<div rd-cookieflow="wrapper" style="display: none;">
|
|
1046
|
+
|
|
1047
|
+
<!-- Manager Button (always visible) -->
|
|
1048
|
+
<div rd-cookieflow="manager">
|
|
1049
|
+
<button rd-cookieflow="open-settings">Cookie Settings</button>
|
|
1050
|
+
</div>
|
|
1041
1051
|
|
|
1042
|
-
|
|
1052
|
+
<!-- Zone 1 Banner (Basic Notice) -->
|
|
1053
|
+
<div rd-cookieflow="banner-zone-one">
|
|
1054
|
+
<p>We use cookies to enhance your experience...</p>
|
|
1055
|
+
<button rd-cookieflow="accept">Accept</button>
|
|
1056
|
+
</div>
|
|
1043
1057
|
|
|
1044
|
-
|
|
1045
|
-
|
|
1058
|
+
<!-- Zone 2 Banner (Opt-Out/CCPA) -->
|
|
1059
|
+
<div rd-cookieflow="banner-zone-two">
|
|
1060
|
+
<p>We use cookies to enhance your experience...</p>
|
|
1061
|
+
<button rd-cookieflow="accept">Accept All</button>
|
|
1062
|
+
<button rd-cookieflow="reject">Reject All</button>
|
|
1063
|
+
<button rd-cookieflow="open-settings">Manage Preferences</button>
|
|
1064
|
+
</div>
|
|
1046
1065
|
|
|
1047
|
-
|
|
1066
|
+
<!-- Zone 3 Banner (Opt-In/GDPR) -->
|
|
1067
|
+
<div rd-cookieflow="banner-zone-three">
|
|
1068
|
+
<p>We use cookies to enhance your experience. Choose your preferences...</p>
|
|
1069
|
+
<button rd-cookieflow="accept">Accept All</button>
|
|
1070
|
+
<button rd-cookieflow="reject">Reject All</button>
|
|
1071
|
+
<button rd-cookieflow="accept-selected">Accept Selected</button>
|
|
1072
|
+
<button rd-cookieflow="open-settings">Customize</button>
|
|
1073
|
+
</div>
|
|
1074
|
+
|
|
1075
|
+
<!-- Settings/Preferences Modal -->
|
|
1076
|
+
<div rd-cookieflow="settings" rd-cookieflow-scroll="disabled">
|
|
1077
|
+
<h2>Cookie Preferences</h2>
|
|
1078
|
+
|
|
1079
|
+
<!-- Marketing Toggle -->
|
|
1080
|
+
<div>
|
|
1081
|
+
<input type="checkbox" rd-cookieflow="marketing-checkbox">
|
|
1082
|
+
<button rd-cookieflow="toggle-interaction"></button>
|
|
1083
|
+
<span rd-cookieflow="marketing-state">Off</span>
|
|
1084
|
+
</div>
|
|
1085
|
+
|
|
1086
|
+
<!-- Analytics Toggle -->
|
|
1087
|
+
<div>
|
|
1088
|
+
<input type="checkbox" rd-cookieflow="analytics-checkbox">
|
|
1089
|
+
<button rd-cookieflow="toggle-interaction"></button>
|
|
1090
|
+
<span rd-cookieflow="analytics-state">Off</span>
|
|
1091
|
+
</div>
|
|
1092
|
+
|
|
1093
|
+
<!-- Personalization Toggle -->
|
|
1094
|
+
<div>
|
|
1095
|
+
<input type="checkbox" rd-cookieflow="personalization-checkbox">
|
|
1096
|
+
<button rd-cookieflow="toggle-interaction"></button>
|
|
1097
|
+
<span rd-cookieflow="personalization-state">Off</span>
|
|
1098
|
+
</div>
|
|
1099
|
+
|
|
1100
|
+
<button rd-cookieflow="accept">Accept All</button>
|
|
1101
|
+
<button rd-cookieflow="reject">Reject All</button>
|
|
1102
|
+
<button rd-cookieflow="accept-selected">Accept Selected</button>
|
|
1103
|
+
<button rd-cookieflow="close">Close</button>
|
|
1104
|
+
</div>
|
|
1105
|
+
|
|
1106
|
+
<!-- GDPR Consent Info Banner -->
|
|
1107
|
+
<div rd-cookieflow="consent-banner">
|
|
1108
|
+
<p>Your Consent ID: [will be populated automatically]</p>
|
|
1109
|
+
<button rd-cookieflow="open-settings">Manage Cookies</button>
|
|
1110
|
+
<button rd-cookieflow="close">Close</button>
|
|
1111
|
+
</div>
|
|
1112
|
+
|
|
1113
|
+
</div>
|
|
1114
|
+
```
|
|
1115
|
+
|
|
1116
|
+
***
|