Age Restriction Warning Setup in 1C-Bitrix
The "Are you 18 or older?" pop-up is not a decorative element. The absence of such a warning on a site selling alcohol, tobacco, or weapons constitutes an administrative violation. Simply implementing it as a basic popup is not enough: proper handling of crawlers, correct SEO behavior, confirmation storage, and behavior on refusal all matter.
Confirmation Storage Mechanism
The key decision is where to store the consent. Three options:
Cookie — the most common approach. Set for 24 hours or until the end of the session. Advantage: no server resources required. Disadvantage: the user can clear cookies.
Bitrix Session — more reliable for the current visit. Uses \Bitrix\Main\Application::getInstance()->getSession()->set('AGE_CONFIRMED', true). Resets when the browser is closed.
User Profile — if the user is authorized, the confirmation flag can be stored in a user field (UF_AGE_CONFIRMED, type boolean). After a one-time confirmation — never ask again. Combined with cookies for anonymous users.
Recommended scheme: cookie for anonymous users (30 days) + UF field for registered users.
Warning Component
The warning is implemented as a separate component connected in the site template (header.php or via bitrix:main.include). The component checks for the cookie/session and, if no confirmation has been received, renders an overlay.
Component structure:
/local/components/custom/age.warning/
├── class.php
├── templates/
│ └── .default/
│ ├── template.php
│ └── script.js
└── .description.php
In class.php — the check and cookie-setting logic:
public function executeComponent() {
$cookieName = 'AGE_CONFIRMED';
$request = \Bitrix\Main\Application::getInstance()->getContext()->getRequest();
if ($request->getCookie($cookieName) === 'Y') {
return; // Confirmation already present
}
if ($this->arParams['CHECK_AUTH'] === 'Y') {
global $USER;
if ($USER->IsAuthorized()) {
$userFields = CUser::GetByID($USER->GetID())->Fetch();
if ($userFields['UF_AGE_CONFIRMED'] === '1') {
return;
}
}
}
$this->IncludeComponentTemplate();
}
Behavior on Refusal
This is a critical point that is often overlooked. If the user clicks "No, I am under 18" — what happens?
- Redirect to a dedicated page with a message about unavailable content
- Blocking the ability to navigate back via
history.pushState - Setting a refusal cookie (
AGE_DENIED=Y) for 24 hours so the popup is not shown again
The refusal page must not contain links to restricted sections. Its URL is usually /age-restricted/ or /sorry/.
SEO and Bots
Search crawlers must not be blocked by the warning. Correct implementation:
- The warning is rendered only via JS after the page loads — HTML content is available for indexing
- Server-side checks (302 redirect) apply only to real users, excluding known crawler User-Agents
- Catalog pages with 18+ products are not blocked from indexing — only the "Buy" button is replaced
// Check: is this a bot?
const isBot = /bot|crawl|spider|slurp|teoma/i.test(navigator.userAgent);
if (!isBot && !getCookie('AGE_CONFIRMED')) {
showAgeConfirmModal();
}
Event Log Integration
For legally significant sites (licensed activities), the fact of age confirmation is recorded in a log. After the user clicks "Yes", an AJAX request is sent to a controller that records the time, IP, User-Agent, and session identifier — via \Bitrix\Main\Diag\Logger or into a custom table.
Delivery Timeframes
| Implementation Variant | Timeframe |
|---|---|
| Basic popup with cookie | 4–6 hours |
| Component with session + redirect on refusal | 8–12 hours |
| Full system: authorized + anonymous + log | 1–2 days |
A properly configured warning is an invisible but legally important part of a store's infrastructure.

