Публичный сайт и личный кабинет в одном проекте: как не потерять SEO и безопасность
Публичный сайт и личный кабинет часто воспринимают как две части одного интерфейса. Для посетителя это действительно один бренд и, возможно, один домен. Но технически они решают разные задачи. Сайт должен быть доступен без входа, понятен поисковым системам, быстро показывать содержание и приводить человека к следующему шагу. Кабинет работает с конкретным пользователем, его заказами, документами и разрешёнными действиями.
Проблемы начинаются, когда эти требования смешивают. Закрытые данные попадают в общий кеш, публичная страница зависит от недоступного API, поисковый робот получает пустой экран, а ключ CRM оказывается в браузерном коде. Избежать этого можно без двух полностью отдельных проектов: достаточно заранее разделить маршруты, данные и правила исполнения.
Один продукт не означает одну техническую зону
Сайт отвечает на вопросы нового посетителя: чем занимается компания, кому подходит услуга, как устроена работа, какие есть условия и как обратиться. Кабинет отвечает уже известному пользователю: что происходит с моим заказом, какой документ действует, что требуется от меня и какое действие я могу выполнить сейчас.
Общими могут быть фирменный стиль, компоненты интерфейса, система аналитики и часть инфраструктуры. Но публичные и приватные страницы должны иметь разные правила:
Свойство Публичный сайт Личный кабинет
——————- ————————————————— —————————————————————-
Доступ Без авторизации После проверки пользователя и прав
Индексация Нужна для полезных посадочных и статей Не нужна
Кеширование Допустимо для общего контента Только с учётом пользователя и чувствительности данных
Основные данные Редакционные страницы и общие предложения Заказы, документы, платежи и действия конкретного пользователя
Отказ зависимости Основной контент желательно продолжать показывать Нельзя выдавать устаревшее состояние как актуальное
Такое разделение полезно зафиксировать ещё до выбора технологий. Тогда решение о серверном HTML, клиентском приложении или CMS принимается для конкретной зоны, а не сразу для всего домена.
Начните с карты маршрутов
Самый простой архитектурный документ — таблица URL. Для каждого маршрута указываются аудитория, необходимость входа, источник данных, возможность индексации и правило кеширования. Например, страницы услуг и блога публичны; вход и восстановление доступа доступны без сессии, но не индексируются; заказы, документы и настройки требуют авторизации.
Явное разделение может выглядеть так:
— /uslugi/, /blog/, /o-kompanii/ — публичный индексируемый контент;
— /login/, /reset-password/ — служебные публичные страницы без поисковой ценности;
— /cabinet/, /cabinet/orders/, /cabinet/documents/ — приватная зона;
— /api/ — серверные операции, которые никогда не становятся страницами сайта.
Префикс не создаёт безопасность сам по себе. Он только делает границу понятной. Каждый запрос к приватным данным всё равно проходит проверку сессии, роли и доступа к объекту.
Критичный публичный контент лучше отдавать готовым HTML
Поисковым системам и пользователям проще работать со страницей, в первом ответе которой уже есть заголовок, основной текст, ссылки и метаданные. Яндекс умеет выполнять JavaScript при индексировании, поэтому утверждение «JavaScript-сайты не индексируются» неверно. Однако рендеринг является отдельным этапом: робот сам решает, выполнять ли скрипты, а ошибка API или долгий запуск приложения может оставить страницу без значимого содержания.
Для услуг, статей, категорий и других поисковых страниц разумно использовать серверный HTML, статическую генерацию или надёжный пререндеринг. Интерактивные элементы могут включаться поверх готового содержания. Это снижает зависимость первого экрана от JavaScript и помогает посетителю получить информацию даже при медленном соединении.
Выбор не обязательно сводится к одной технологии. Пользователь может перейти с обычной страницы сайта для бизнеса (/razrabotka-sajtov/) в насыщенный клиентский интерфейс, оставаясь визуально в одном продукте.
У публичной страницы должен быть устойчивый URL
Каждая индексируемая страница получает один основной адрес, корректный title, description, canonical и место в структуре внутренних ссылок. Если один материал доступен по нескольким параметрам или техническим маршрутам, система должна определить основную версию. Sitemap перечисляет только те URL, которые действительно следует обходить.
Фильтры, результаты внутренних действий, страницы входа и приватные маршруты не нужно добавлять в карту сайта. Файл robots.txt помогает управлять обходом, но не является средством защиты. Адрес, закрытый только от поискового робота, остаётся доступным любому человеку, который его знает.
По этой же причине метатег noindex не заменяет авторизацию. Для кабинета он может быть дополнительной мерой против случайного появления служебной страницы в поиске, но данные должны быть недоступны без действующей сессии независимо от поведения робота.
Приватные данные приходят только после серверной проверки
Браузер не должен решать, какие заказы разрешено показать. Он отправляет запрос от имени текущего пользователя, а сервер выбирает только доступные объекты. Если интерфейс запрашивает заказ по идентификатору, сервер проверяет принадлежность или иное разрешённое отношение к этому заказу.
OWASP API Security Top 10 отдельно выделяет нарушение авторизации на уровне объекта. Типичная ошибка — получить ID из URL и вернуть запись, убедившись лишь в том, что пользователь вошёл. Сессия подтверждает личность, но не доказывает право на любой объект системы.
Проверка распространяется и на отдельные поля. Клиент может видеть сумму и клиентский комментарий, но не внутреннюю себестоимость или служебную заметку. API лучше формировать явный ответ для кабинета, чем возвращать полную CRM-карточку и надеяться, что frontend скроет лишнее.
Ключи интеграций не размещают во frontend
Код, загруженный в браузер, доступен пользователю. Скрытая переменная, минификация или отдельный JavaScript-файл не превращают секрет в защищённое значение. Поэтому кабинет не должен напрямую обращаться к CRM, хранилищу документов или платёжному провайдеру с постоянным привилегированным ключом.
Путь выглядит иначе: браузер обращается к backend проекта; backend проверяет сессию и действие; затем выполняет узкую операцию во внешней системе с серверными учётными данными. Ответ содержит только те поля, которые нужны текущему экрану. Такой слой одновременно защищает секреты, нормализует данные и не позволяет интерфейсу обходить бизнес-правила.
Описание API можно закрепить контрактом OpenAPI: маршруты, параметры, схемы ответов, варианты ошибок и требования к авторизации становятся видимыми для команды и тестов. Но сам контракт не определяет, кому принадлежит заказ и кто вправе его изменить, — эти правила задаются отдельно.
Общий кеш требует особенно аккуратных границ
Публичные страницы выгодно кешировать на сервере или CDN: один и тот же ответ подходит многим посетителям. В кабинете ответ зависит от пользователя. Ошибка в ключе кеша может привести к тому, что один клиент увидит данные другого.
Приватные ответы не должны попадать в общий публичный кеш. Для них задаются соответствующие HTTP-заголовки и проверяется поведение CDN, reverse proxy и браузера. Особого внимания требует service worker: он может перехватывать запросы и сохранять ответы, поэтому стратегия «кешировать всё для офлайн-работы» неприемлема для документов и персональных данных.
Кеширование справочников или обезличенных общих данных возможно, но должно быть осознанным. У каждого класса ответа полезно заранее указать: можно ли хранить, где, как долго и от какого события он должен быть сброшен.
Сессия должна иметь понятный жизненный цикл
После входа сервер создаёт сессию, которая живёт ограниченное время и может быть прекращена при выходе, длительном бездействии, смене критичных данных или отзыве доступа. NIST рекомендует управление сессиями вместо постоянной повторной передачи учётных данных: это и безопаснее, и удобнее для пользователя.
Нужно определить, что происходит при смене телефона или почты, потере устройства, увольнении представителя клиента и подозрительной активности. Возможность завершить другие сессии полезнее, чем формальная кнопка «выйти» только в текущем браузере.
Форма входа должна работать с менеджерами паролей и позволять вставлять код подтверждения. WCAG 2.2 рассматривает доступную аутентификацию отдельно: искусственный запрет вставки и задачи, требующие запоминания, создают барьер для пользователей и подталкивают к небезопасным обходным действиям.
Сбой API не должен превращаться в белый экран
Публичная страница должна сохранять основной текст, навигацию и способ связи, даже если временно недоступны калькулятор или форма. Для формы можно сохранить введённые данные локально в допустимом объёме, показать честный статус и предложить повтор. Нельзя сообщать «заявка отправлена», пока сервер не подтвердил приём.
В кабинете опасно показывать старый статус как свежий без пояснения. Если CRM недоступна, интерфейс может отобразить последнюю известную информацию с временем обновления и временно запретить действие, результат которого нельзя проверить. Значимая операция получает идентификатор: после восстановления связи система выясняет, была ли она выполнена, прежде чем предлагать повтор.
Состояния загрузки, отсутствия данных, запрета доступа, конфликта версии и технической ошибки проектируются так же внимательно, как успешный экран. Именно их чаще видит пользователь в сложном процессе.
Общая дизайн-система не требует общей логики
Шапка, типографика, цвета, поля и кнопки могут быть одинаковыми на сайте и в кабинете. Это поддерживает ощущение цельного продукта и уменьшает стоимость изменений. При этом публичная навигация ориентирована на знакомство и выбор, а навигация кабинета — на текущие объекты и действия.
Не стоит загружать весь код кабинета на каждую страницу блога только ради повторного использования нескольких компонентов. И наоборот, рекламные виджеты и сторонние скрипты публичной части не всегда уместны в зоне, где человек открывает документы и финансовую информацию. Общий визуальный слой лучше отделять от маршрутов, данных и зависимостей.
Производительность и доступность проверяют в обеих зонах
Для публичного сайта особенно важны скорость появления основного содержания, отзывчивость и стабильность макета. Core Web Vitals дают три соответствующих направления измерения, но один лабораторный запуск не описывает всех посетителей. Полезно смотреть реальные данные по типам страниц и устройствам.
В кабинете приоритет может смещаться к скорости повторных переходов, работе больших списков и ясной обратной связи после действий. Это не означает, что первый вход можно сделать тяжёлым. Пользователь часто открывает кабинет с телефона по ссылке из сообщения, поэтому загрузка авторизации и нужного заказа должна быть прямой.
Разделение сборок и зависимостей помогает обеим зонам: публичная страница не оплачивает вес сложной таблицы, а кабинет не загружает код всех маркетинговых блоков.
Доступность относится и к маркетингу, и к операциям
На публичном сайте доступность помогает прочитать содержание, пройти навигацию и отправить форму. В кабинете последствия ошибки выше: человек может не суметь оплатить, скачать документ или подтвердить действие. Поэтому видимый фокус, подписи полей, сообщения об ошибках, управление клавиатурой и достаточный размер целей проверяются в обеих зонах.
Статус нельзя передавать только цветом. После отправки действия интерфейс сообщает результат текстом и делает его доступным вспомогательным технологиям. Тайм-аут сессии не должен внезапно уничтожать заполненную длинную форму без предупреждения и возможности продолжить безопасным способом.
Интеграция с CRM проходит через бизнес-события
Публичная форма создаёт обращение, но не обязана напрямую записывать произвольные поля в основную базу. Backend проверяет данные, защищается от дублей, сохраняет маркетинговые идентификаторы и вызывает разрешённую операцию. Кабинет работает с более широким набором событий: запрос на изменение, подтверждение документа, платёж, загрузка файла, отмена или комментарий.
Для каждого события определяются:
— кто имеет право его инициировать;
— какие поля обязательны;
— какое состояние объекта допускает действие;
— какая система выполняет окончательное изменение;
— как обрабатываются повтор, задержка и частичный сбой;
— что видит пользователь после результата.
Так CRM становится источником рабочего контекста (/crm-erp/), а сайт и кабинет — разными контролируемыми входами в один процесс, а не независимыми базами.
Проверяйте проект матрицей зон
Перед запуском полезно пройти каждый маршрут в четырёх режимах: анонимный пользователь, авторизованный клиент, пользователь без права на конкретный объект и сотрудник с расширенными полномочиями. Параллельно проверяется выдаваемый HTML, индексация, кеш и набор загружаемых скриптов.
Минимальный контрольный список включает:
— публичный текст присутствует без выполнения клиентского JavaScript;
— canonical и sitemap содержат только нужные публичные URL;
— служебные и приватные маршруты не попадают в индексируемую структуру;
— доступ к каждому заказу и файлу проверяется сервером;
— frontend не содержит ключей CRM и других постоянных секретов;
— приватные ответы не сохраняются общим кешем;
— ошибка интеграции не создаёт повторную заявку или оплату;
— вход, восстановление и основные действия доступны с клавиатуры и на мобильном устройстве;
— журнал позволяет разобрать значимую операцию.
Развивайте зоны независимо, сохраняя общий процесс
Публичный сайт будет получать новые посадочные, статьи и инструменты. Кабинет — новые объекты и действия. Если их границы определены, каждая часть может развиваться в своём темпе без риска сломать другую. Обновление дизайна не меняет авторизацию, а добавление рабочего модуля не заставляет перестраивать все индексируемые страницы.
Именно это отличает цельную архитектуру от попытки поместить всё в одно приложение. Посетитель видит один SynchroWeb-продукт, а внутри публичный контент, веб-приложение (/veb-servisy/), backend и CRM выполняют свои строго определённые роли.
Источники
— Яндекс Вебмастер: рендеринг страниц с JavaScript (https://yandex.ru/support/webmaster/ru/yandex-indexing/rendering)
— Яндекс Вебмастер: рекомендации для мобильных сайтов (https://yandex.ru/support/webmaster/ru/recommendations/mobile-site)
— OWASP API1:2023 — Broken Object Level Authorization (https://owasp.org/API-Security/editions/2023/en/0xa1-broken-object-level-authorization/)
— OWASP API3:2023 — Broken Object Property Level Authorization (https://owasp.org/API-Security/editions/2023/en/0xa3-broken-object-property-level-authorization/)
— NIST SP 800-63B: Authentication and Lifecycle Management (https://pages.nist.gov/800-63-4/sp800-63b.html)
— W3C Web Content Accessibility Guidelines 2.2 (https://www.w3.org/TR/WCAG22/)
— web.dev: Core Web Vitals (https://web.dev/articles/vitals)
— OpenAPI Specification (https://spec.openapis.org/oas/latest.html)