From 9f53641f16f53f5f6d4ae763c98c771c32a50a1e Mon Sep 17 00:00:00 2001 From: striker Date: Mon, 16 Mar 2026 04:04:50 +0300 Subject: [PATCH] seo: GA4, breadcrumbs JSON-LD, IndexNow post-deploy, llms.txt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add GA4 (G-C9J0D8FFH3) to root layout alongside Yandex.Metrika - Add BreadcrumbList JSON-LD schema to all inner pages - Add scripts/indexnow.mjs — submits 30 URLs to IndexNow + Yandex on deploy - Add indexnow to postdeploy step in package.json - Update llms.txt with all 8 services and new pages (about/clients/partners) Co-Authored-By: Claude Sonnet 4.6 --- package.json | 2 +- public/llms.txt | 19 +++++++- scripts/indexnow.mjs | 68 +++++++++++++++++++++++++++ src/app/[lang]/about/page.tsx | 6 +++ src/app/[lang]/clients/page.tsx | 6 +++ src/app/[lang]/faq/page.tsx | 11 +++-- src/app/[lang]/kontakty/page.tsx | 10 ++-- src/app/[lang]/partners/page.tsx | 6 +++ src/app/[lang]/uslugi/[slug]/page.tsx | 9 ++++ src/app/[lang]/uslugi/page.tsx | 5 ++ src/app/layout.tsx | 8 ++++ src/lib/breadcrumbs.ts | 12 +++++ 12 files changed, 151 insertions(+), 11 deletions(-) create mode 100644 scripts/indexnow.mjs create mode 100644 src/lib/breadcrumbs.ts diff --git a/package.json b/package.json index 4e319e8..980cc59 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "dev": "next dev", "build": "next build", "start": "next start", - "deploy": "BUILD_DIR=../public_html next build" + "deploy": "BUILD_DIR=../public_html next build && node scripts/indexnow.mjs" }, "dependencies": { "next": "^15.2.3", diff --git a/public/llms.txt b/public/llms.txt index 3f25e97..29d183c 100644 --- a/public/llms.txt +++ b/public/llms.txt @@ -12,10 +12,25 @@ - **IT-аутсорсинг** — полное обслуживание IT-инфраструктуры: серверы, сети, рабочие станции. Поддержка 24/7, удалённое и выездное обслуживание, фиксированная стоимость. - **Кибербезопасность** — защита корпоративных данных, аудит безопасности, настройка межсетевых экранов и VPN, защита от утечек данных. - **Техническая поддержка** — help desk, управление заявками, обучение пользователей. SLA от 15 минут. +- **Видеонаблюдение** — проектирование и монтаж систем видеонаблюдения, IP-камеры, NVR, облачное хранение, удалённый доступ. +- **Сетевая инфраструктура** — проектирование, монтаж и обслуживание корпоративных сетей, Wi-Fi, VPN, управляемые коммутаторы. +- **Серверная инфраструктура** — поставка, настройка и обслуживание серверов, виртуализация, резервное копирование. +- **IP-телефония** — корпоративные АТС, SIP-телефония, интеграция с CRM, запись звонков. +- **Облачные решения** — перенос инфраструктуры в облако, Microsoft 365, резервное копирование в облаке. + +## Страницы + +- Главная: https://sag24.ru/ru/ +- Услуги: https://sag24.ru/ru/uslugi/ +- О компании: https://sag24.ru/ru/about/ +- Клиенты: https://sag24.ru/ru/clients/ +- Партнёры: https://sag24.ru/ru/partners/ +- FAQ: https://sag24.ru/ru/faq/ +- Контакты: https://sag24.ru/ru/kontakty/ ## Контакты -- Телефон: +7 495 363-74-76 +- Телефон: +7 495 363-74-76, +7 495 363-73-35, +7 909 945-44-56 - Email: info@sag24.ru -- Адрес: Пушкино, Московская область +- Адрес: Пушкино, пр-кт Московский, д. 38/14, Московская область, 141207 - Сайт: https://sag24.ru diff --git a/scripts/indexnow.mjs b/scripts/indexnow.mjs new file mode 100644 index 0000000..6197e01 --- /dev/null +++ b/scripts/indexnow.mjs @@ -0,0 +1,68 @@ +#!/usr/bin/env node +// IndexNow — уведомляем поисковики об обновлении сайта после деплоя +// https://www.indexnow.org/ + +const KEY = '40c65b722891b81d944f2c3fea6cab95' +const HOST = 'sag24.ru' + +const URLS = [ + 'https://sag24.ru/ru/', + 'https://sag24.ru/en/', + 'https://sag24.ru/ru/about/', + 'https://sag24.ru/en/about/', + 'https://sag24.ru/ru/clients/', + 'https://sag24.ru/en/clients/', + 'https://sag24.ru/ru/partners/', + 'https://sag24.ru/en/partners/', + 'https://sag24.ru/ru/uslugi/', + 'https://sag24.ru/en/uslugi/', + 'https://sag24.ru/ru/uslugi/it-autsorsing/', + 'https://sag24.ru/en/uslugi/it-autsorsing/', + 'https://sag24.ru/ru/uslugi/kiberbezopasnost/', + 'https://sag24.ru/en/uslugi/kiberbezopasnost/', + 'https://sag24.ru/ru/uslugi/tehpodderzhka/', + 'https://sag24.ru/en/uslugi/tehpodderzhka/', + 'https://sag24.ru/ru/uslugi/videonablyudenie/', + 'https://sag24.ru/en/uslugi/videonablyudenie/', + 'https://sag24.ru/ru/uslugi/seti/', + 'https://sag24.ru/en/uslugi/seti/', + 'https://sag24.ru/ru/uslugi/servery/', + 'https://sag24.ru/en/uslugi/servery/', + 'https://sag24.ru/ru/uslugi/telefoniya/', + 'https://sag24.ru/en/uslugi/telefoniya/', + 'https://sag24.ru/ru/uslugi/oblako/', + 'https://sag24.ru/en/uslugi/oblako/', + 'https://sag24.ru/ru/faq/', + 'https://sag24.ru/en/faq/', + 'https://sag24.ru/ru/kontakty/', + 'https://sag24.ru/en/kontakty/', +] + +const ENDPOINTS = [ + 'https://api.indexnow.org/indexnow', + 'https://yandex.com/indexnow', +] + +async function submit(endpoint) { + const res = await fetch(endpoint, { + method: 'POST', + headers: { 'Content-Type': 'application/json; charset=utf-8' }, + body: JSON.stringify({ + host: HOST, + key: KEY, + keyLocation: `https://${HOST}/${KEY}.txt`, + urlList: URLS, + }), + }) + return res.status +} + +console.log(`IndexNow: submitting ${URLS.length} URLs...`) +const results = await Promise.allSettled(ENDPOINTS.map(async ep => { + const status = await submit(ep) + console.log(` ${ep} → ${status}`) + return status +})) + +const ok = results.every(r => r.status === 'fulfilled' && (r.value === 200 || r.value === 202)) +console.log(ok ? 'IndexNow: done.' : 'IndexNow: some errors (non-critical).') diff --git a/src/app/[lang]/about/page.tsx b/src/app/[lang]/about/page.tsx index fa19035..38109f8 100644 --- a/src/app/[lang]/about/page.tsx +++ b/src/app/[lang]/about/page.tsx @@ -1,5 +1,6 @@ import type { Metadata } from 'next' import { getDictionary, LOCALES, type Locale } from '@/lib/i18n' +import { breadcrumbSchema } from '@/lib/breadcrumbs' import AboutSection from '@/components/sections/AboutSection' export function generateStaticParams() { @@ -37,9 +38,14 @@ export default async function AboutPage({ params }: { params: Promise<{ lang: st const { lang: langStr } = await params const lang = langStr as Locale const d = getDictionary(lang) + const isRu = lang === 'ru' return (
+ {/* Yandex.Metrika */}