fivo_cookie_consent 0.2.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.
- checksums.yaml +7 -0
- data/.nvmrc +1 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.windsurfrules +76 -0
- data/CHANGELOG.md +64 -0
- data/LICENSE.txt +21 -0
- data/README.md +524 -0
- data/Rakefile +11 -0
- data/app/assets/javascripts/fivo_cookie_consent.js +924 -0
- data/app/assets/stylesheets/fivo_cookie_consent.scss +654 -0
- data/app/helpers/rails_cookies_gdpr/application_helper.rb +156 -0
- data/app/views/rails_cookies_gdpr/_banner.html.erb +27 -0
- data/app/views/rails_cookies_gdpr/_modal.html.erb +123 -0
- data/config/database.yml +6 -0
- data/db/test.sqlite3 +0 -0
- data/db/test.sqlite3-shm +0 -0
- data/db/test.sqlite3-wal +0 -0
- data/lib/fivo_cookie_consent/configuration.rb +141 -0
- data/lib/fivo_cookie_consent/engine.rb +31 -0
- data/lib/fivo_cookie_consent/railtie.rb +18 -0
- data/lib/fivo_cookie_consent/version.rb +5 -0
- data/lib/fivo_cookie_consent.rb +16 -0
- data/lib/generators/fivo_cookie_consent/install_generator.rb +144 -0
- data/scratchpad.md +315 -0
- data/yarn.lock +4 -0
- metadata +190 -0
data/README.md
ADDED
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
# fivo_cookie_consent
|
|
2
|
+
|
|
3
|
+
GDPR cookie-banner for Rails 7 (esbuild/jsbundling).
|
|
4
|
+
|
|
5
|
+
A minimal, opinionated GDPR cookie consent banner for Rails 7 projects using esbuild + jsbundling-rails + sass. Designed specifically for German-only audiences without I18n complexity.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- 🚀 **Rails Engine** - Auto-mounted routes, views, and helpers
|
|
10
|
+
- 📱 **Responsive Design** - Mobile-first with desktop optimization
|
|
11
|
+
- 🎨 **Modern UI** - Clean design with WCAG-AA contrast compliance
|
|
12
|
+
- 🛠 **Configurable** - Customize labels, URLs, and cookie lifespan
|
|
13
|
+
- 📦 **localStorage** - Persistent consent storage with expiration
|
|
14
|
+
- 🎯 **Event-driven** - Custom events for analytics integration
|
|
15
|
+
- ♿ **Accessible** - Full keyboard navigation and screen reader support
|
|
16
|
+
- 🧪 **Well-tested** - Comprehensive RSpec + Capybara test suite
|
|
17
|
+
- 🔍 **Auto-Detection** - Automatically detects and categorizes cookies (client-side)
|
|
18
|
+
- 🛡️ **Server-Side Cookies** - Detects HttpOnly Rails session/CSRF cookies on the server and merges them client-side so users always see *all* cookies
|
|
19
|
+
- 📋 **Expandable Lists** - Collapsible cookie details with name, duration, and description
|
|
20
|
+
- 🚫 **Empty State Handling** - Graceful handling of categories with no cookies
|
|
21
|
+
- ⚙️ **Script Loaders** - Consent-gated loading for GTM, GA4, reCAPTCHA, Hotjar, and Facebook Pixel
|
|
22
|
+
- 🧩 **Extensible API** - Ruby API and JS facade for registering and loading custom third-party scripts
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
### From RubyGems (when published)
|
|
27
|
+
|
|
28
|
+
Add this line to your application's Gemfile:
|
|
29
|
+
|
|
30
|
+
```ruby
|
|
31
|
+
gem 'fivo_cookie_consent'
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
And then execute:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
bundle add fivo_cookie_consent
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### From GitLab Repository (current)
|
|
41
|
+
|
|
42
|
+
To use the latest version directly from GitLab, add this to your Gemfile:
|
|
43
|
+
|
|
44
|
+
```ruby
|
|
45
|
+
# GDPR Cookie Consent
|
|
46
|
+
gem 'fivo_cookie_consent', git: 'https://gitlab.com/fivo/fivo_cookie_consent.git'
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Or specify a branch/tag:
|
|
50
|
+
|
|
51
|
+
```ruby
|
|
52
|
+
# Use main branch (recommended)
|
|
53
|
+
gem 'fivo_cookie_consent', git: 'https://gitlab.com/fivo/fivo_cookie_consent.git', branch: 'main'
|
|
54
|
+
|
|
55
|
+
# Or use a specific tag
|
|
56
|
+
gem 'fivo_cookie_consent', git: 'https://gitlab.com/fivo/fivo_cookie_consent.git', tag: 'v0.1.0'
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Then execute:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
bundle install
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Run the generator to install required files:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
rails generate fivo_cookie_consent:install
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Manual Setup
|
|
72
|
+
|
|
73
|
+
After running the generator, add the imports to your bundler files:
|
|
74
|
+
|
|
75
|
+
**app/javascript/application.js**
|
|
76
|
+
```javascript
|
|
77
|
+
import "./fivo_cookie_consent"
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**app/assets/stylesheets/application.scss**
|
|
81
|
+
```scss
|
|
82
|
+
@use "fivo_cookie_consent";
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Usage
|
|
86
|
+
|
|
87
|
+
Add the cookie banner to your layout before the closing `</body>` tag:
|
|
88
|
+
|
|
89
|
+
```erb
|
|
90
|
+
<!-- app/views/layouts/application.html.erb -->
|
|
91
|
+
<%= gdpr_cookie_banner %>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The helper injects a `data-server-cookies` attribute containing a JSON string of HttpOnly cookies detected on the server (Rails session, CSRF token, etc.).
|
|
95
|
+
|
|
96
|
+
**Important:** Do **not** mark this JSON as `html_safe`. The gem’s helper already escapes it correctly—see `server_cookies_json`—so the string remains valid markup and can be parsed on the client with `JSON.parse()`.
|
|
97
|
+
|
|
98
|
+
The banner will automatically appear for new visitors and hide once consent is given.
|
|
99
|
+
|
|
100
|
+
### Step 1: Add the banner and assets
|
|
101
|
+
|
|
102
|
+
1. Ensure you have imported the JS and SCSS as shown in the "Manual Setup" section.
|
|
103
|
+
2. Add `<%= gdpr_cookie_banner %>` once in your main layout, typically `app/views/layouts/application.html.erb`, just before `</body>`.
|
|
104
|
+
|
|
105
|
+
### Step 2: Choose how to load analytics/marketing scripts
|
|
106
|
+
|
|
107
|
+
You have two primary integration modes:
|
|
108
|
+
|
|
109
|
+
1. **Strict lazy-load** – third-party scripts are not loaded at all until the user has given consent for the relevant category.
|
|
110
|
+
2. **Google Consent Mode pre-load** – GTM/GA4 are loaded immediately but with storage denied by default; consent updates are forwarded to Consent Mode.
|
|
111
|
+
|
|
112
|
+
#### Option A: Strict lazy-load for GTM/GA4
|
|
113
|
+
|
|
114
|
+
Add consent-gated placeholders to your `<head>` using `gdpr_lazy_load_tag`:
|
|
115
|
+
|
|
116
|
+
```erb
|
|
117
|
+
<!-- app/views/layouts/application.html.erb -->
|
|
118
|
+
<head>
|
|
119
|
+
<title>My App</title>
|
|
120
|
+
|
|
121
|
+
<%# Strict lazy-load: scripts are only loaded after consent %>
|
|
122
|
+
<%= gdpr_lazy_load_tag(:gtm, id: 'GTM-XXXX') %>
|
|
123
|
+
<%= gdpr_lazy_load_tag(:ga4, id: 'G-XXXXXXX') %>
|
|
124
|
+
|
|
125
|
+
<%= csrf_meta_tags %>
|
|
126
|
+
<%= csp_meta_tag %>
|
|
127
|
+
</head>
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
What this does:
|
|
131
|
+
|
|
132
|
+
- Renders `<script type="text/plain" data-gdpr-category="analytics" ...>` placeholders.
|
|
133
|
+
- The gem’s JavaScript turns these placeholders into real `<script>` tags **only if** the user has granted consent for the `analytics` category.
|
|
134
|
+
- Works with both "Accept all" and granular settings in the modal.
|
|
135
|
+
|
|
136
|
+
#### Option B: Google Consent Mode pre-load for GTM/GA4
|
|
137
|
+
|
|
138
|
+
If you want to use Google Consent Mode, call `gdpr_consent_mode_defaults` **before** your GTM/GA scripts, then still lazy-load the actual script tags so that they only execute when appropriate:
|
|
139
|
+
|
|
140
|
+
```erb
|
|
141
|
+
<!-- app/views/layouts/application.html.erb -->
|
|
142
|
+
<head>
|
|
143
|
+
<title>My App</title>
|
|
144
|
+
|
|
145
|
+
<%# 1) Set Consent Mode defaults and wire gdpr:accept/decline events %>
|
|
146
|
+
<%= gdpr_consent_mode_defaults(functionality: true, security: true) %>
|
|
147
|
+
|
|
148
|
+
<%# 2) Load GA4 + GTM via consent-gated placeholders %>
|
|
149
|
+
<%= gdpr_lazy_load_tag(:ga4, id: 'G-XXXXXXX') %>
|
|
150
|
+
<%= gdpr_lazy_load_tag(:gtm, id: 'GTM-XXXX') %>
|
|
151
|
+
|
|
152
|
+
<%= csrf_meta_tags %>
|
|
153
|
+
<%= csp_meta_tag %>
|
|
154
|
+
</head>
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
What this does:
|
|
158
|
+
|
|
159
|
+
- Defines `window.dataLayer` and a `gtag` helper.
|
|
160
|
+
- Sets initial Consent Mode defaults (analytics/marketing denied until consent).
|
|
161
|
+
- Listens to `gdpr:accept` and `gdpr:decline` events and forwards category choices to Google Consent Mode.
|
|
162
|
+
- Uses the same lazy-load placeholders under the hood so GTM/GA only start working when consent is present.
|
|
163
|
+
|
|
164
|
+
### Step 3: Register custom scripts
|
|
165
|
+
|
|
166
|
+
You can register additional scripts (e.g., Hotjar, reCAPTCHA, custom trackers) in your initializer and then load them with `gdpr_lazy_load_tag`:
|
|
167
|
+
|
|
168
|
+
```ruby
|
|
169
|
+
# config/initializers/fivo_cookie_consent.rb
|
|
170
|
+
RailsCookiesGdpr.configure do |config|
|
|
171
|
+
# existing options ...
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Register custom scripts (using the FivoCookieConsent API)
|
|
175
|
+
RailsCookiesGdpr.register_script(:hotjar, category: :analytics)
|
|
176
|
+
RailsCookiesGdpr.register_script(:recaptcha, category: :functional)
|
|
177
|
+
RailsCookiesGdpr.register_script(
|
|
178
|
+
:adroll,
|
|
179
|
+
category: :marketing,
|
|
180
|
+
src: 'https://example-cdn.com/adroll.js',
|
|
181
|
+
async: true
|
|
182
|
+
)
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Then, in your layout or views:
|
|
186
|
+
|
|
187
|
+
```erb
|
|
188
|
+
<%= gdpr_lazy_load_tag(:hotjar, src: 'https://static.hotjar.com/c/hotjar-XXXX.js') %>
|
|
189
|
+
|
|
190
|
+
<%= gdpr_lazy_load_tag(:recaptcha, src: 'https://www.google.com/recaptcha/api.js', async: true, defer: true) %>
|
|
191
|
+
|
|
192
|
+
<%= gdpr_lazy_load_tag(:adroll) %>
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
The gem ensures these scripts are only executed once the corresponding category (`analytics`, `functional`, `marketing`, etc.) has been granted.
|
|
196
|
+
|
|
197
|
+
## Configuration
|
|
198
|
+
|
|
199
|
+
Edit the generated initializer to customize labels and settings:
|
|
200
|
+
|
|
201
|
+
```ruby
|
|
202
|
+
# config/initializers/fivo_cookie_consent.rb
|
|
203
|
+
RailsCookiesGdpr.configure do |config|
|
|
204
|
+
config.analytics_label = 'Analyse-Cookies'
|
|
205
|
+
config.marketing_label = 'Marketing-Cookies'
|
|
206
|
+
config.functional_label = 'Präferenz-Cookies'
|
|
207
|
+
config.privacy_url = '/datenschutz'
|
|
208
|
+
config.cookie_lifespan = 365 # days
|
|
209
|
+
|
|
210
|
+
# Optional: Customize cookie patterns for auto-detection
|
|
211
|
+
config.cookie_patterns = {
|
|
212
|
+
necessary: [/^_session_/, /^csrf_token/, /^authenticity_token/],
|
|
213
|
+
analytics: [/^_ga/, /^_gid/, /^_gat/, /^_gtag/],
|
|
214
|
+
marketing: [/^_fbp/, /^_fbc/, /^fr$/],
|
|
215
|
+
functional: [/^_locale/, /^language/, /^theme/]
|
|
216
|
+
}
|
|
217
|
+
end
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Configuration Options
|
|
221
|
+
|
|
222
|
+
All configuration settings are optional and have sensible defaults. The generator creates an initializer with all available options:
|
|
223
|
+
|
|
224
|
+
| Option | Default | Description |
|
|
225
|
+
|--------|---------|-------------|
|
|
226
|
+
| `analytics_label` | `'Analyse-Cookies'` | Display label for analytics cookie category in the banner |
|
|
227
|
+
| `marketing_label` | `'Marketing-Cookies'` | Display label for marketing cookie category in the banner |
|
|
228
|
+
| `functional_label` | `'Präferenz-Cookies'` | Display label for functional cookie category in the banner |
|
|
229
|
+
| `privacy_url` | `'/datenschutz'` | URL path to your privacy policy page (linked from banner) |
|
|
230
|
+
| `cookie_lifespan` | `365` | Number of days until user consent expires and banner reappears |
|
|
231
|
+
| `cookie_patterns` | See below | Hash of regex patterns for automatically categorizing detected cookies |
|
|
232
|
+
|
|
233
|
+
#### Setting Details
|
|
234
|
+
|
|
235
|
+
**Labels (`analytics_label`, `marketing_label`, `functional_label`)**
|
|
236
|
+
- Control the text displayed for each cookie category in the banner
|
|
237
|
+
- Should match your site's language (currently German-focused)
|
|
238
|
+
- Used in both the quick banner and detailed settings modal
|
|
239
|
+
|
|
240
|
+
**Privacy URL (`privacy_url`)**
|
|
241
|
+
- Must be a valid route in your Rails application
|
|
242
|
+
- Banner includes a "Privacy Policy" link pointing to this URL
|
|
243
|
+
- Commonly `/datenschutz`, `/privacy`, or `/impressum`
|
|
244
|
+
|
|
245
|
+
**Cookie Lifespan (`cookie_lifespan`)**
|
|
246
|
+
- Controls when the banner reappears for returning users
|
|
247
|
+
- Stored as `savedAt` timestamp in localStorage
|
|
248
|
+
- Set to `0` to show banner on every visit (not recommended)
|
|
249
|
+
|
|
250
|
+
**Cookie Patterns (`cookie_patterns`)**
|
|
251
|
+
- Hash with keys: `:necessary`, `:analytics`, `:marketing`, `:functional`
|
|
252
|
+
- Each key contains an array of regular expressions
|
|
253
|
+
- Used to automatically categorize detected cookies
|
|
254
|
+
- See "Automatic Cookie Detection" section below for details
|
|
255
|
+
|
|
256
|
+
## Automatic Cookie Detection
|
|
257
|
+
|
|
258
|
+
The gem automatically detects cookies in your application and categorizes them based on configurable patterns. This feature:
|
|
259
|
+
|
|
260
|
+
- **Scans `document.cookie`** every 2 seconds to detect new cookies
|
|
261
|
+
- **Categorizes cookies** using regular expression patterns
|
|
262
|
+
- **Shows cookie details** in expandable lists with name, duration, and description
|
|
263
|
+
- **Handles empty categories** with appropriate messaging and disabled controls
|
|
264
|
+
- **Development mode** shows an "Uncategorised" section for cookies that don't match any pattern
|
|
265
|
+
|
|
266
|
+
### Default Cookie Patterns
|
|
267
|
+
|
|
268
|
+
The gem includes sensible defaults for common cookie patterns:
|
|
269
|
+
|
|
270
|
+
```ruby
|
|
271
|
+
# Necessary cookies (always enabled)
|
|
272
|
+
necessary: [
|
|
273
|
+
/^_session_/, # Rails session cookies
|
|
274
|
+
/^csrf_token/, # CSRF protection
|
|
275
|
+
/^authenticity_token/,
|
|
276
|
+
/^_rails_/, # Rails framework cookies
|
|
277
|
+
/^gdpr_cookie_consent$/ # Our own consent cookie
|
|
278
|
+
]
|
|
279
|
+
|
|
280
|
+
# Analytics cookies
|
|
281
|
+
analytics: [
|
|
282
|
+
/^_ga/, # Google Analytics
|
|
283
|
+
/^_gid/, /^_gat/, /^_gtag/,
|
|
284
|
+
/^__utm/, # Google Analytics UTM
|
|
285
|
+
/^_dc_gtm_/, # Google Tag Manager
|
|
286
|
+
/^_hj/ # Hotjar
|
|
287
|
+
]
|
|
288
|
+
|
|
289
|
+
# Marketing cookies
|
|
290
|
+
marketing: [
|
|
291
|
+
/^_fbp/, /^_fbc/, # Facebook Pixel
|
|
292
|
+
/^fr$/, /^tr$/, # Facebook tracking
|
|
293
|
+
/^_pinterest_/, # Pinterest
|
|
294
|
+
/^__Secure-3PAPISID/, # Google Ads
|
|
295
|
+
/^NID$/, /^IDE$/ # Google advertising
|
|
296
|
+
]
|
|
297
|
+
|
|
298
|
+
# Functional cookies
|
|
299
|
+
functional: [
|
|
300
|
+
/^_locale/, # Language preferences
|
|
301
|
+
/^language/,
|
|
302
|
+
/^theme/, # UI preferences
|
|
303
|
+
/^preferences/,
|
|
304
|
+
/^_user_settings/
|
|
305
|
+
]
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### Customizing Cookie Patterns
|
|
309
|
+
|
|
310
|
+
You can override or extend the cookie patterns in your initializer:
|
|
311
|
+
|
|
312
|
+
```ruby
|
|
313
|
+
RailsCookiesGdpr.configure do |config|
|
|
314
|
+
# Add custom patterns
|
|
315
|
+
config.cookie_patterns = {
|
|
316
|
+
necessary: config.default_cookie_patterns[:necessary] + [/^my_app_session/],
|
|
317
|
+
analytics: [/^custom_analytics_/],
|
|
318
|
+
marketing: [/^my_marketing_/],
|
|
319
|
+
functional: [/^user_pref_/]
|
|
320
|
+
}
|
|
321
|
+
end
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
## Events
|
|
325
|
+
|
|
326
|
+
The gem dispatches custom events that you can listen to for integrating with analytics:
|
|
327
|
+
|
|
328
|
+
```javascript
|
|
329
|
+
// Listen for consent acceptance
|
|
330
|
+
document.addEventListener('gdpr:accept', function(event) {
|
|
331
|
+
const { categories } = event.detail;
|
|
332
|
+
// categories = ['analytics', 'marketing', 'functional']
|
|
333
|
+
|
|
334
|
+
if (categories.includes('analytics')) {
|
|
335
|
+
// Initialize Google Analytics, etc.
|
|
336
|
+
gtag('consent', 'update', {
|
|
337
|
+
'analytics_storage': 'granted'
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
// Listen for consent decline
|
|
343
|
+
document.addEventListener('gdpr:decline', function(event) {
|
|
344
|
+
const { categories } = event.detail;
|
|
345
|
+
// Handle declined categories
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
// Listen for any consent change (recommended for most integrations)
|
|
349
|
+
document.addEventListener('gdpr:change', function(event) {
|
|
350
|
+
const { consent } = event.detail;
|
|
351
|
+
// consent = { necessary: true, analytics: true/false, marketing: true/false, functional: true/false, savedAt: ... }
|
|
352
|
+
});
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### Event Details
|
|
356
|
+
|
|
357
|
+
- **gdpr:accept** - Fired when categories are accepted
|
|
358
|
+
- **gdpr:decline** - Fired when categories are declined
|
|
359
|
+
- **gdpr:change** - Fired whenever consent is updated (accept all, decline all, or custom settings)
|
|
360
|
+
- `event.detail.categories` - Array of affected category names
|
|
361
|
+
- `event.detail.consent` - Full consent object (for `gdpr:change`)
|
|
362
|
+
|
|
363
|
+
## Cookie Storage
|
|
364
|
+
|
|
365
|
+
User consent is stored in localStorage under the key `gdpr_cookie_consent`:
|
|
366
|
+
|
|
367
|
+
```json
|
|
368
|
+
{
|
|
369
|
+
"necessary": true,
|
|
370
|
+
"analytics": true,
|
|
371
|
+
"marketing": false,
|
|
372
|
+
"functional": true,
|
|
373
|
+
"savedAt": "2024-01-15T10:30:00.000Z"
|
|
374
|
+
}
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
## Accessing Consent Status
|
|
378
|
+
|
|
379
|
+
You can check consent status from JavaScript.
|
|
380
|
+
|
|
381
|
+
### Recommended: via the `GDPRConsent` facade
|
|
382
|
+
|
|
383
|
+
The gem exposes a small JS helper on `window.GDPRConsent` and as an ES module export:
|
|
384
|
+
|
|
385
|
+
```javascript
|
|
386
|
+
// Get full consent object
|
|
387
|
+
const consent = GDPRConsent.getConsent();
|
|
388
|
+
|
|
389
|
+
// Check specific category
|
|
390
|
+
if (GDPRConsent.hasConsent('analytics')) {
|
|
391
|
+
// Load analytics scripts
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// Subscribe to changes (fires on accept/decline/save preferences)
|
|
395
|
+
GDPRConsent.on('gdpr:change', (event) => {
|
|
396
|
+
const { consent } = event.detail;
|
|
397
|
+
console.log('Updated consent:', consent);
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
// Open settings programmatically, e.g. from a footer link
|
|
401
|
+
// GDPRConsent.showModal();
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
### Low-level: direct localStorage access
|
|
405
|
+
|
|
406
|
+
If you prefer, you can still read the raw localStorage entry yourself:
|
|
407
|
+
|
|
408
|
+
```javascript
|
|
409
|
+
// Get full consent object
|
|
410
|
+
const consent = JSON.parse(localStorage.getItem('gdpr_cookie_consent'));
|
|
411
|
+
|
|
412
|
+
// Check specific category
|
|
413
|
+
function hasConsent(category) {
|
|
414
|
+
const consent = JSON.parse(localStorage.getItem('gdpr_cookie_consent') || '{}');
|
|
415
|
+
return consent[category] === true;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
if (hasConsent('analytics')) {
|
|
419
|
+
// Load analytics scripts
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// Access detected cookies information
|
|
423
|
+
const detectedCookies = window.RailsCookiesGdpr?.detectCookies?.() || {};
|
|
424
|
+
console.log('Current cookies by category:', detectedCookies);
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
## UI Features
|
|
428
|
+
|
|
429
|
+
### Expandable Category Rows
|
|
430
|
+
|
|
431
|
+
Each cookie category can be expanded to show detailed information about detected cookies:
|
|
432
|
+
|
|
433
|
+
- **Chevron indicators** (▶/▾) show expansion state
|
|
434
|
+
- **Cookie tables** display name, duration, and description
|
|
435
|
+
- **Collapsible interface** keeps the modal clean and focused
|
|
436
|
+
- **No persistence** - expansion state resets on modal close
|
|
437
|
+
|
|
438
|
+
### Empty State Handling
|
|
439
|
+
|
|
440
|
+
When no cookies are detected in a category:
|
|
441
|
+
|
|
442
|
+
- Shows **"Keine Cookies gesetzt"** message
|
|
443
|
+
- **Disables the toggle** with `aria-disabled="true"`
|
|
444
|
+
- **Automatically enables** when cookies are detected
|
|
445
|
+
- **Maintains accessibility** with proper ARIA attributes
|
|
446
|
+
|
|
447
|
+
### Development Mode
|
|
448
|
+
|
|
449
|
+
In development environment:
|
|
450
|
+
|
|
451
|
+
- Shows **"Uncategorised"** section for cookies that don't match any pattern
|
|
452
|
+
- Helps identify new cookies that need pattern rules
|
|
453
|
+
- Hidden in production to avoid user confusion
|
|
454
|
+
|
|
455
|
+
## Styling
|
|
456
|
+
|
|
457
|
+
The gem uses a clean, modern design with the following color scheme:
|
|
458
|
+
|
|
459
|
+
- **Brand Green**: `#1E858B` - Primary buttons and links
|
|
460
|
+
- **Neutral Grey**: `#626465` - Secondary elements and text
|
|
461
|
+
|
|
462
|
+
### CSS Classes
|
|
463
|
+
|
|
464
|
+
Key CSS classes for customization:
|
|
465
|
+
|
|
466
|
+
- `.gdpr-banner` - Main banner container
|
|
467
|
+
- `.gdpr-modal` - Settings modal
|
|
468
|
+
- `.gdpr-banner__btn--primary` - Accept button style
|
|
469
|
+
- `.gdpr-banner__btn--secondary` - Decline button style
|
|
470
|
+
|
|
471
|
+
## Browser Support
|
|
472
|
+
|
|
473
|
+
- Chrome 60+
|
|
474
|
+
- Firefox 60+
|
|
475
|
+
- Safari 12+
|
|
476
|
+
- Edge 79+
|
|
477
|
+
|
|
478
|
+
## Development
|
|
479
|
+
|
|
480
|
+
After checking out the repo, run:
|
|
481
|
+
|
|
482
|
+
```bash
|
|
483
|
+
bin/setup
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
To run the test suite:
|
|
487
|
+
|
|
488
|
+
```bash
|
|
489
|
+
bundle exec rake spec
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
To run the dummy app for testing:
|
|
493
|
+
|
|
494
|
+
```bash
|
|
495
|
+
cd spec/dummy
|
|
496
|
+
rails server
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
## Contributing
|
|
500
|
+
|
|
501
|
+
1. Fork the project
|
|
502
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
503
|
+
3. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
504
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
505
|
+
5. Open a Pull Request
|
|
506
|
+
|
|
507
|
+
## Release
|
|
508
|
+
|
|
509
|
+
To release a new version:
|
|
510
|
+
|
|
511
|
+
1. Update the version number in `lib/fivo_cookie_consent/version.rb`
|
|
512
|
+
2. Update `CHANGELOG.md` with the new changes
|
|
513
|
+
3. Commit the changes
|
|
514
|
+
4. Run:
|
|
515
|
+
|
|
516
|
+
```bash
|
|
517
|
+
bundle exec rake release
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
This will create a git tag, push commits and tags, and publish the gem to RubyGems.
|
|
521
|
+
|
|
522
|
+
## License
|
|
523
|
+
|
|
524
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|