Escape Room Website Development on 1C-Bitrix
An escape room sells an experience. The website must convey atmosphere before the visit — while ensuring fast booking without calls. In practice, 60% of bookings come in the evening, when the administrator is offline. An automated booking system with slots and online payment is not optional but necessary.
On 1C-Bitrix, such a website is built on quest catalog infoblocks, a Highload block for scheduling, the sale module for payment, and CRM integration for request processing.
Quest Catalog: Infoblock Structure
Each quest is an infoblock element with an expanded set of properties. Standard "title + description + picture" is insufficient — a visitor chooses a quest by specific parameters.
"Quests" infoblock properties:
- Genre — horror, detective, adventure, fantasy, sci-fi (reference property, multiple — a quest can combine genres)
- Difficulty — 1 to 5 (numeric, displayed as lock icons)
- Player count — min and max (two numeric properties)
- Age restriction — 6+, 12+, 16+, 18+ (list)
- Duration — in minutes (numeric)
- Teaser video — YouTube/VK Video link (string)
-
Photo gallery — multiple "File" property with watermark enabled through
OnBeforeIBlockElementUpdatehandler - Completion percentage — statistics, updated by agent based on booking data from the Highload block
- Status — active, temporarily closed, new (list, affects sorting and badges in catalog)
On the catalog page, a smart-filter (CIBlockSmartFilter) works by genre, player count, and difficulty. Results are cached in a faceted index — even with 30+ quests (network of locations), response is instant.
The detailed quest page is built on cinematic principles: full-screen hero block with teaser video background, parameters in compact cards, gallery with lightbox, reviews block and fixed CTA booking button in viewport.
Booking with Slots and Dynamic Pricing
This is the most technically dense part of the project. Quest booking is not just "select date and pay". You must account for: specific quest availability at specific times, room preparation between sessions, price differences by day of week and time of day, and group discounts.
"Booking slots" Highload block:
| Field | Type | Purpose |
|---|---|---|
| UF_QUEST_ID | Integer | Quest reference |
| UF_DATE | Date | Session date |
| UF_TIME | String | Start time (10:00, 11:30...) |
| UF_STATUS | List | available / reserved / paid / completed / cancelled |
| UF_PRICE | Number | Calculated price for this slot |
| UF_PLAYERS | Integer | Actual player count |
| UF_ORDER_ID | Integer | Sale order reference |
| UF_PROMO | String | Applied promo code |
| UF_SOURCE | List | website / phone / aggregator |
Slot generation. The agent (CAgent) runs daily at 01:00 and creates slots for 21 days ahead. Interval between slots = quest duration + 20 minutes for room reset. For a 60-minute quest operating 10:00–22:00, this gives 9 slots per day. The agent takes duration and preparation time from quest infoblock properties — if parameters change, new slots are generated with current data.
Dynamic pricing is implemented through a separate "Price rules" Highload block:
| Field | Type | Example |
|---|---|---|
| UF_QUEST_ID | Integer | 5 |
| UF_DAY_TYPE | List | weekday / weekend / holiday |
| UF_TIME_FROM | String | 10:00 |
| UF_TIME_TO | String | 16:00 |
| UF_BASE_PRICE | Number | 80 BYN |
| UF_PLAYER_PRICE | Number | 0 (fixed) or 15 (per person) |
| UF_MIN_PRICE | Number | 60 BYN (threshold for small groups) |
During slot generation, the agent determines UF_DAY_TYPE by day of week (weekends and holidays from a separate reference), finds the matching rule, and writes UF_PRICE. If the pricing model is "per person" — the website displays "from X to Y BYN", and the final price is calculated after specifying the number of players.
Client-side booking algorithm:
- Visitor selects a quest — calendar loads with available dates (AJAX request to controller, filter by
UF_STATUS = availableandUF_DATE >= today) - Selects date — available slots appear with prices
- Specifies number of players — price recalculates if "per person" model
- Enters promo code (optional) — discount applied through
salemodule basket rules - Fills contact data — name, phone, email
- Pays online — payment system via
sale.paysystem(ЕРИП, cards)
Slot reservation happens at step 5: status changes to reserved, 15-minute timer starts. If payment doesn't arrive — agent returns status to available. This prevents slots from "hanging" due to incomplete payment.
After successful payment:
- Slot status →
paid - Client receives email with details and SMS with address/time
- CRM Bitrix24 deal is created (via REST API or
crmmodule) - 3 hours before session — automatic SMS reminder via
messageservice
Corporate Offers
A separate section with a form for corporate event requests. The form is created through an iblock feedback component and includes fields: company, participant count, preferred dates, budget (range), wishes. The request goes to CRM as a lead with "corporate" source — separate funnel with stages "agreement → prepayment → execution → review".
For corporate clients, exclusive rent is provided — booking all quests for a specific time period. Implemented through mass status changes with UF_SOURCE = corporate marking.
Reviews and Gift Certificates
Reviews are stored in an infoblock with pre-moderation. Properties: quest reference (E), rating (1-5), text, photo, completion date. After quest completion, client receives email with review form link — no authentication required, identification by order token.
Gift certificates — sale module products with unique code generation. When a certificate is purchased, a record is created in the "Certificates" Highload block with fields: code, denomination, validity period, balance. The certificate is applied as a coupon when booking. PDF certificate is generated automatically via TCPDF library and sent to buyer's email.
Technical Solutions
-
SEO — pretty URLs by scheme
/quests/horror/quest-name/, auto meta-generation from infoblock properties template - Speed — composite cache for catalog and detail pages, schedule loads via AJAX without cache
-
Analytics —
dataLayerevents at each booking step for funnel in Google Analytics / Yandex.Metrica - Mobile version — booking calendar adapted for touch interface, slots displayed as vertical list instead of grid
- Multilanguage — when operating in tourism market, multi-site module connected with English-language catalog version







