Server side
The honest boundary
JavaScript cannot read or delete httpOnly cookies. It also cannot stop your
server from emitting a Set-Cookie header. The Agreely banner never claims
otherwise. If your application emits cookies server-side, handling those cookies
is your responsibility, and the banner cannot substitute for that.
The right approach: read the agreely_consent first-party cookie server-side
before any processing or before emitting a non-essential Set-Cookie.
The agreely_consent cookie
The banner emits a first-party cookie named agreely_consent:
SameSite=Lax,Secure(on HTTPS),Path=/Max-Age: 183 days (symmetric for both accept and refuse)- Value: URL-encoded JSON
Safari, like some privacy-focused browsers, limits how long cookies written by JavaScript can last (7 days or less). On those browsers, the banner may ask for consent again before the planned duration (183 days) has run out. The banner rewrites the cookie on each visit, with its original expiry: a person who comes back before the browser's limit keeps their choice.
{
"v": 1,
"consentId": "550e8400-e29b-41d4-a716-446655440000",
"decisions": {
"analytics": false,
"marketing": false,
"functional": false
},
"configVersion": 3,
"ts": 1721390400,
"locale": "en"
}
The decisions key contains the non-essential purposes declared for your website
with the value true (granted) or false (refused or not yet granted). The
absence of the cookie means no decision has been made: treat it as a refusal.
PHP: read consent before a Set-Cookie
<?php
function agrConsentDecision(string $purpose): bool
{
$raw = $_COOKIE['agreely_consent'] ?? null;
if ($raw === null) {
return false; // no decision = refuse
}
$data = json_decode(urldecode($raw), true);
return ($data['decisions'][$purpose] ?? false) === true;
}
// Before emitting an analytics cookie:
if (agrConsentDecision('analytics')) {
setcookie('_ga_custom', $value, [
'expires' => time() + 63072000,
'path' => '/',
'secure' => true,
'httponly' => false,
'samesite' => 'Lax',
]);
}
// Before a marketing tracking session:
if (agrConsentDecision('marketing')) {
// load pixel, tracker, etc.
}
Node.js / Express: read consent before a Set-Cookie
import cookieParser from 'cookie-parser';
function agrConsent(req, purpose) {
const raw = req.cookies?.agreely_consent;
if (!raw) return false;
try {
const data = JSON.parse(decodeURIComponent(raw));
return data?.decisions?.[purpose] === true;
} catch {
return false;
}
}
// Express middleware
app.use(cookieParser());
app.get('/track', (req, res) => {
if (!agrConsent(req, 'analytics')) {
return res.status(204).end(); // refused: no tracker
}
res.cookie('_mytracker', sessionId, {
maxAge: 63072000 * 1000,
httpOnly: false,
secure: true,
sameSite: 'lax',
});
// continue with tracker
});
Best practices
- Treat the absence of the cookie as a refusal. A user whose cookie has expired or who has not yet interacted with the banner has not consented.
- Do not cache the consent decision in session memory. Read the cookie on each relevant request, because the visitor may withdraw consent in another tab.
- Do not create tracking
httpOnlysession cookies before the decision. AnhttpOnlystrictly-necessary cookie (e.g., an authentication session cookie) is fine; ahttpOnlyanalytics or marketing cookie set before agreement defeats the choice the banner collects.
Law 25 note. Consent must be clear, free and informed and be given for specific purposes, and it is requested for each such purpose (P-39.1 s. 14, first paragraph; A-2.1 s. 53.1, first paragraph). If you use technology that includes functions allowing the person to be identified, located or profiled, you must first inform them of it and of the means available to activate those functions (P-39.1 s. 8.1; A-2.1 s. 65.0.1). Reading the
agreely_consentcookie server-side is the way to honor the visitor's decision for your server-emitted cookies. Agreely helps you document and demonstrate your approach; you remain responsible for the legal validity of consent for your own purposes.