Разработка сайта застройщика на 1С-Битрикс
Сайт застройщика — не агрегатор недвижимости и не доска объявлений. Застройщик продаёт конкретные квартиры в конкретных корпусах, и покупатель принимает решение не по фотографиям чужих интерьеров, а по планировке, виду из окна и стадии строительства. Средний цикл сделки — 2-4 месяца. За это время посетитель возвращается на сайт 8-15 раз: сравнивает планировки, следит за ходом стройки, пересчитывает ипотеку. Если сайт не отвечает на эти задачи — клиент уходит к конкуренту, у которого шахматка работает.
Ключевая техническая особенность сайта застройщика — интерактивный поэтажный план (шахматка). Это не просто таблица «этаж × секция». Это SVG-схема, на которой каждая квартира кликабельна, окрашена по статусу и связана с реальными данными из инфоблока. Именно шахматка отличает сайт застройщика от шаблонного каталога.
Архитектура данных: ЖК → корпус → квартира
Структура инфоблоков отражает физическую иерархию: жилой комплекс содержит корпуса (секции), корпус содержит квартиры.
Инфоблок «Жилые комплексы» (или Highload-блок, если комплексов меньше 50) — родительская сущность. Свойства:
| Свойство | Тип | Назначение |
|---|---|---|
| NAME | Название ЖК | Заголовок и SEO |
| ADDRESS | S (строка) | Адрес, геокодирование |
| COORDINATES | S ("lat,lng") | Точка на карте |
| STAGE | L (список) | Этап: проект, котлован, строительство, сдан |
| COMPLETION_DATE | S (дата) | Плановый срок сдачи |
| INFRASTRUCTURE | S (HTML/текст) | Описание инфраструктуры |
| DEVELOPER_ID | E (привязка) | Ссылка на компанию-застройщика |
| GENPLAN_SVG | F (файл) | SVG генплана территории |
Разделы инфоблока — корпуса и секции. Каждый ЖК — раздел первого уровня. Корпуса — разделы второго уровня внутри ЖК. Если в корпусе несколько секций (подъездов) — разделы третьего уровня. Такая вложенность позволяет использовать штатную навигацию bitrix:catalog.section.list без кастомных запросов.
Элементы инфоблока — квартиры. Каждая квартира привязана к разделу-корпусу (или разделу-секции). Минимальный набор свойств:
| Свойство | Тип | Индекс | Комментарий |
|---|---|---|---|
| ROOMS | L (список) | Фасетный | Студия, 1, 2, 3, 4+ |
| AREA_TOTAL | N (число) | Фасетный | Общая площадь, м² |
| AREA_LIVING | N | Нет | Жилая площадь |
| AREA_KITCHEN | N | Нет | Площадь кухни |
| FLOOR | N | Фасетный | Этаж квартиры |
| PRICE | N | Фасетный | Цена, ₽ |
| PRICE_PER_M2 | N | Фасетный | Цена за м² |
| STATUS | L | Фасетный | Свободна / Забронирована / Продана |
| LAYOUT_IMG | F (файл) | Нет | Изображение планировки |
| LAYOUT_SVG_ID | S (строка) | Нет | ID квартиры в SVG-шахматке |
| FINISHING | L | Фасетный | Без отделки / Черновая / Чистовая |
| WINDOW_VIEW | L | Нет | Во двор / На улицу / Панорамный |
| DECORATION_IMG | F (множ.) | Нет | Фото отделки, если есть |
Свойство LAYOUT_SVG_ID — связующее звено между данными в базе и SVG-файлом шахматки. Об этом подробно ниже.
Интерактивная шахматка: глубокое погружение
Шахматка — визуальное представление этажей и квартир в разрезе корпуса. Пользователь видит фасад здания или схему этажа, кликает на квартиру, получает карточку с ценой, площадью и планировкой. Квартиры окрашены по статусу: зелёный — свободна, жёлтый — забронирована, серый — продана. Это ключевой конверсионный инструмент: застройщик с рабочей шахматкой получает на 30-40% больше заявок, чем застройщик с табличным каталогом.
Подготовка SVG-файла. Дизайнер рисует фасад или поэтажный план в Adobe Illustrator / Figma и экспортирует в SVG. Каждая квартира — отдельный <path>, <polygon> или <rect> с атрибутом data-apartment-id, который совпадает со значением свойства LAYOUT_SVG_ID элемента инфоблока. Пример фрагмента SVG:
<svg viewBox="0 0 1200 800" xmlns="http://www.w3.org/2000/svg">
<!-- Этаж 5, секция 1 -->
<g data-floor="5" data-section="1">
<path data-apartment-id="K1-5-01"
d="M100,200 L250,200 L250,350 L100,350 Z"
class="apartment" />
<path data-apartment-id="K1-5-02"
d="M260,200 L450,200 L450,350 L260,350 Z"
class="apartment" />
<path data-apartment-id="K1-5-03"
d="M460,200 L600,200 L600,350 L460,350 Z"
class="apartment" />
</g>
<!-- Лестничная клетка, лифт — без data-apartment-id -->
<rect x="610" y="200" width="40" height="150" class="stairs" />
</svg>
Правила именования data-apartment-id: корпус-этаж-номер (K1-5-01). Формат фиксируется в техническом задании и не меняется после начала разработки. Если дизайнер пришлёт SVG без атрибутов — разработчик потратит 2-3 дня на разметку вручную. Поэтому шаблон SVG с примерами атрибутов передаётся дизайнеру до начала отрисовки.
Инлайн SVG, а не <img>. SVG подключается не через тег <img> и не через <object>, а инлайнится прямо в HTML страницы. Причина — к содержимому <img src="plan.svg"> нельзя обратиться из JavaScript (кроссдоменная политика и отсутствие DOM-доступа). Инлайн SVG становится частью DOM страницы, и каждый <path data-apartment-id="..."> доступен через document.querySelector.
На практике: Битрикс читает SVG-файл из свойства раздела (корпуса) и выводит его содержимое через file_get_contents() прямо в шаблон компонента:
// template.php компонента шахматки
$svgPath = CFile::GetPath($arResult['SECTION']['UF_FLOOR_PLAN_SVG']);
$svgContent = file_get_contents($_SERVER['DOCUMENT_ROOT'] . $svgPath);
// Удаляем XML-декларацию, если есть
$svgContent = preg_replace('/<\?xml[^?]*\?>/', '', $svgContent);
echo '<div class="chess-board">' . $svgContent . '</div>';
JavaScript: связываем SVG с данными квартир. При загрузке страницы фронтенд получает JSON-массив квартир текущего корпуса через AJAX-запрос или инлайн <script> с данными из CIBlockElement::GetList. Структура JSON:
const apartments = [
{
svgId: "K1-5-01",
id: 4521,
rooms: 2,
area: 58.3,
floor: 5,
price: 7200000,
pricePerM2: 123500,
status: "available", // available | reserved | sold
layoutImg: "/upload/layouts/k1-5-01.jpg",
url: "/zhk-solnechnyj/korpus-1/kvartira-4521/"
},
// ...
];
Инициализация шахматки:
function initChessBoard(apartments) {
const svgContainer = document.querySelector('.chess-board svg');
if (!svgContainer) return;
// 1. Раскрашиваем по статусу
const statusColors = {
available: '#4CAF50',
reserved: '#FFC107',
sold: '#9E9E9E'
};
apartments.forEach(apt => {
const el = svgContainer.querySelector(
`[data-apartment-id="${apt.svgId}"]`
);
if (!el) return;
el.style.fill = statusColors[apt.status];
el.style.cursor = apt.status === 'sold' ? 'default' : 'pointer';
el.style.transition = 'fill 0.2s, opacity 0.2s';
// 2. Hover — подсветка
el.addEventListener('mouseenter', () => {
if (apt.status === 'sold') return;
el.style.opacity = '0.7';
showTooltip(el, apt);
});
el.addEventListener('mouseleave', () => {
el.style.opacity = '1';
hideTooltip();
});
// 3. Клик — карточка квартиры или переход
el.addEventListener('click', () => {
if (apt.status === 'sold') return;
showApartmentCard(apt);
});
});
}
Tooltip при наведении. При hover над квартирой показывается всплывающая подсказка с краткой информацией: комнаты, площадь, цена. Позиция tooltip вычисляется через getBoundingClientRect() элемента SVG:
function showTooltip(svgElement, apt) {
const tooltip = document.getElementById('chess-tooltip');
const rect = svgElement.getBoundingClientRect();
tooltip.innerHTML = `
<div class="chess-tooltip__rooms">${apt.rooms}-комн.</div>
<div class="chess-tooltip__area">${apt.area} м²</div>
<div class="chess-tooltip__price">
${apt.price.toLocaleString('ru-RU')} ₽
</div>
`;
tooltip.style.left = `${rect.left + rect.width / 2}px`;
tooltip.style.top = `${rect.top - 10}px`;
tooltip.style.display = 'block';
}
Карточка по клику. При клике на свободную квартиру открывается боковая панель или модальное окно с полной информацией: планировка, площадь по комнатам, этаж, вид из окна, отделка, кнопки «Забронировать» и «Скачать PDF». Данные уже загружены в массив apartments — дополнительного AJAX-запроса не нужно.
Фильтрация прямо на шахматке. Над SVG-схемой — панель фильтров: количество комнат (чекбоксы), диапазон площади, диапазон цены. При изменении фильтра JavaScript скрывает не подходящие квартиры через el.style.display = 'none' или уменьшает их opacity до 0.15. Подходящие остаются яркими. Это работает мгновенно, без обращения к серверу — все данные уже на клиенте.
function filterChessBoard(filters) {
apartments.forEach(apt => {
const el = document.querySelector(
`[data-apartment-id="${apt.svgId}"]`
);
if (!el) return;
const match =
(filters.rooms.length === 0 ||
filters.rooms.includes(apt.rooms)) &&
apt.area >= filters.areaMin &&
apt.area <= filters.areaMax &&
apt.price >= filters.priceMin &&
apt.price <= filters.priceMax;
el.style.opacity = match ? '1' : '0.1';
el.style.pointerEvents = match ? 'auto' : 'none';
});
}
Адаптивность SVG. На десктопе SVG занимает 100% ширины контейнера, viewBox обеспечивает масштабирование. На мобильных устройствах (экран < 768px) шахматка в режиме фасада нечитаема — квартиры слишком мелкие для тапа пальцем. Два варианта решения: 1) переключение на поэтажный вид, где один этаж занимает всю ширину экрана, пользователь свайпает между этажами; 2) pinch-to-zoom через CSS touch-action: manipulation и JavaScript-обработку жестов (библиотека panzoom или hammer.js). Первый вариант надёжнее.
Обновление статусов в реальном времени. Когда менеджер бронирует квартиру в CRM или 1С, статус на сайте должен измениться без перезагрузки. Варианты: WebSocket (избыточно для большинства застройщиков), Server-Sent Events (проще), или polling каждые 30 секунд. Polling — самый простой: AJAX-запрос возвращает массив [{svgId, status}], JavaScript обновляет цвета. При 200 квартирах в корпусе JSON ответа — менее 5 КБ.
Ход строительства: фотоотчёты и камеры
Раздел «Ход строительства» — обязательный для объектов на стадии строительства. Инфоблок «Фотоотчёты»: элемент = один отчёт (дата, описание, множественное свойство «Фото»). Разделы — корпуса. Вывод — timeline, сортировка по DATE_ACTIVE_FROM DESC.
Видео с дрона — свойство типа «Строка» с URL YouTube/Vimeo. Embed через <iframe> с loading="lazy".
Веб-камера — <iframe> с потоком от провайдера (Ivideon, Trassir). Встраивается в шаблон раздела ЖК. Кеширование шаблона отключается для блока камеры (<? $this->SetViewTarget('nocache'); ?>), остальная страница кешируется штатно.
Ипотечный калькулятор с программами банков
Чистый JavaScript. Highload-блок «Ипотечные программы»: поля BANK_NAME, PROGRAM_NAME, RATE, MIN_DOWNPAYMENT, MAX_TERM, IS_ACTIVE. При загрузке страницы квартиры — AJAX-запрос или инлайн JSON с активными программами.
Формула аннуитетного платежа:
P = S × (r × (1 + r)^n) / ((1 + r)^n − 1)
где S = стоимость − первый взнос
r = годовая ставка / 12 / 100
n = срок в месяцах
Интерфейс: выбор банка (select) → подставляется ставка и минимальный взнос → три ползунка (стоимость квартиры подставляется автоматически из карточки, первый взнос, срок) → результат: ежемесячный платёж, переплата, общая сумма. Пересчёт — при каждом движении ползунка, input event, без debounce (вычисление мгновенное).
Сравнение квартир и избранное
Избранное для неавторизованных — localStorage. Массив объектов {id, complexId}, максимум 30. Иконка сердечка в карточке квартиры и на шахматке. Счётчик в шапке сайта. При авторизации — синхронизация localStorage с Highload-блоком UserFavorites.
Сравнение — до 4 квартир. Таблица с горизонтальным скроллом на мобильных: комнаты, площадь общая/жилая/кухня, этаж, цена, цена за м², отделка, статус. Планировки отображаются в ряд для визуального сравнения.
Генерация PDF планировки
Клиент нажимает «Скачать PDF» на карточке квартиры — получает PDF с планировкой, параметрами и контактами застройщика. Генерация на сервере через mPDF или Dompdf.
Шаблон PDF — HTML-файл, который рендерится в PDF. Содержимое: логотип застройщика, название ЖК, корпус, этаж, номер квартиры, планировка (изображение), таблица характеристик, QR-код со ссылкой на карточку. Изображение планировки вставляется через <img src="..."> с абсолютным серверным путём (mPDF не загружает по URL надёжно).
$mpdf = new \Mpdf\Mpdf(['tempDir' => '/tmp/mpdf']);
$html = $this->renderPdfTemplate($apartment);
$mpdf->WriteHTML($html);
$mpdf->Output('apartment-' . $apartment['ID'] . '.pdf', 'D');
PDF генерируется по запросу, не заранее. Кеширование — по ELEMENT_ID + TIMESTAMP_X (хеш): если квартира не менялась, отдаём сохранённый PDF из /upload/pdf_cache/.
Интеграция с CRM и 1С
Заявки → Битрикс24. Форма «Забронировать» / «Получить консультацию» → REST API crm.deal.add (не lead, а deal — застройщик работает со сделками). Поля: TITLE = «Заявка на кв. №{номер}, ЖК {название}», CATEGORY_ID = воронка продаж недвижимости, UF_CRM_APARTMENT_ID = ID элемента инфоблока, UF_CRM_COMPLEX = название ЖК, SOURCE_ID = «WEB». Webhook с секретным ключом, HTTPS.
Синхронизация с 1С. Застройщики ведут учёт квартир в 1С:Предприятие. Цены и статусы обновляются в 1С, а сайт должен отражать актуальные данные. Варианты интеграции:
-
Штатный обмен 1С-Битрикс (модуль
catalog) — работает через CommerceML (XML). 1С выгружает XML с товарами, Битрикс импортирует. Подходит для цен, но статусы квартир (свободна/забронирована/продана) требуют маппинга кастомных свойств. -
REST API — 1С вызывает endpoint на сайте (
/api/apartments/update-status/), передаёт JSON{apartment_code: "K1-5-01", status: "reserved", price: 7500000}. Контроллер на стороне Битрикса находит элемент поLAYOUT_SVG_ID, обновляет свойства черезCIBlockElement::SetPropertyValues. - Периодическая выгрузка CSV — 1С кладёт CSV на FTP, агент Битрикса раз в 15 минут забирает и парсит. Грубо, но работает для застройщиков с устаревшей 1С без REST API.
SEO и микроразметка
Шаблоны meta через настройки инфоблока:
- Title:
Купить квартиру в ЖК #SECTION_NAME# — #ELEMENT_NAME#, от #PROPERTY_PRICE# ₽ - Description:
#PROPERTY_ROOMS#-комн. квартира #PROPERTY_AREA_TOTAL# м² на #PROPERTY_FLOOR# этаже в ЖК #SECTION_NAME#. Застройщик #PROPERTY_DEVELOPER#.
Микроразметка — Schema.org Residence для ЖК и Offer для квартиры:
{
"@context": "https://schema.org",
"@type": "Residence",
"name": "ЖК Солнечный",
"address": "г. Москва, ул. Строителей, 15",
"geo": {"@type": "GeoCoordinates", "latitude": 55.75, "longitude": 37.61},
"makesOffer": [
{
"@type": "Offer",
"name": "2-комн. квартира, 58.3 м², 5 этаж",
"price": "7200000",
"priceCurrency": "RUB",
"availability": "https://schema.org/InStock"
}
]
}
Для SEO-продвижения по запросам «купить квартиру в ЖК [название]» критично: уникальный текстовый контент на странице ЖК (не только карточки квартир), хлебные крошки (BreadcrumbList), XML sitemap с отдельными URL для каждой квартиры.
Этапы и сроки
| Масштаб проекта | Срок |
|---|---|
| Один ЖК, 1-2 корпуса, до 200 квартир, базовая шахматка | 1-4 недели |
| 2-5 ЖК, шахматка + ход строительства + ипотечный калькулятор + CRM | 5-8 недель |
| Портал застройщика, 10+ ЖК, интеграция с 1С, PDF, личный кабинет | 8-12 недель |
Сроки предполагают готовые SVG-файлы шахматок от дизайнера с правильной разметкой data-apartment-id. Если SVG нужно создавать с нуля по планировкам из проектной документации — добавляется 1-2 недели на корпус.







