FR EN

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 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
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.
}
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 httpOnly session cookies before the decision. An httpOnly strictly-necessary cookie (e.g., an authentication session cookie) is fine; a httpOnly analytics 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_consent cookie 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.