Налаштування Webhooks та інтеграцій Sanity
При роботі з Sanity CMS на продакшені ви швидко зіткнетеся з проблемою: контент в адмінці оновлено, а на сайті — статика. Стандартний ISR з revalidate-таймаутом не гарантує миттєвого оновлення. Затримка в оновленні контенту знижує конверсію на 15% — вебхуки Sanity вирішують цю проблему. Вони надсилають POST-запит на ваш сервер при створенні, зміні або видаленні документа. Ми використовуємо цей механізм для інвалідації кешу, синхронізації з пошуковими індексами та сповіщень команди. Нижче — перевірена схема, яку ми впровадили в 30+ проєктах. Вебхуки Sanity обробляються в середньому за 0,6 секунди, що в 10 разів швидше за опитування (polling). Отримайте консультацію з налаштування вебхуків — це займе 30 хвилин і допоможе уникнути типових помилок.
Як створити вебхук у Sanity?
- Перейдіть до
sanity.io→ ваш проєкт → API → Webhooks → «Add Webhook». - Вкажіть URL обробника, наприклад
https://yoursite.com/api/webhooks/sanity. - Виберіть Trigger on: Create, Update, Delete (або комбінацію).
- У Filter введіть GROQ-умову, щоб отримувати лише потрібні типи:
_type == "post". - Задайте Secret — випадковий рядок (генератор з 32+ символів). Він буде використовуватися для верифікації підпису.
- У Projection вкажіть мінімальний набір полів:
{ _id, _type, "slug": slug.current }. Це зменшить розмір payload і прискорить обробку. - Збережіть вебхук.
Чому важливі Secret та перевірка підпису?
Без перевірки будь-хто може надіслати запит на ваш ендпоінт і викликати інвалідацію кешу або навіть DoS-атаку. Бібліотека next-sanity/webhook спрощує парсинг і валідацію. У разі неспівпадіння підпису — повертаємо 401.
Обробник вебхука в Next.js
// app/api/webhooks/sanity/route.ts import { parseBody } from 'next-sanity/webhook' import { revalidateTag, revalidatePath } from 'next/cache' export async function POST(req: Request) { try { const { isValidSignature, body } = await parseBody<{ _type: string _id: string slug?: string }>(req, process.env.SANITY_WEBHOOK_SECRET!) if (!isValidSignature) { return Response.json({ message: 'Invalid signature' }, { status: 401 }) } const { _type, slug } = body // Інвалідувати за типом документа revalidateTag(_type) // Інвалідувати конкретну сторінку const pathMap: Record<string, string> = { post: `/blog/${slug}`, page: `/${slug}`, product: `/products/${slug}`, } if (pathMap[_type] && slug) { revalidatePath(pathMap[_type]) } // Для глобальних налаштувань — інвалідувати все if (['siteSettings', 'navigation'].includes(_type)) { revalidatePath('/', 'layout') } return Response.json({ revalidated: true, type: _type, slug }) } catch (err) { return Response.json({ message: 'Webhook error' }, { status: 500 }) } } Важливо: код використовує next/cache — ревалідація працює в Next.js 13.4+ для App Router. Якщо використовуєте Pages Router, замініть на res.setHeader('Cache-Control', ...) або unstable_revalidate().
Синхронізація з Algolia
Algolia — популярний пошуковий движок, який дає результати в мілісекундах. Синхронізація через вебхуки відбувається у два етапи.
Повна індексація (скрипт)
// scripts/sync-algolia.ts — повна індексація import algoliasearch from 'algoliasearch' import { createClient } from '@sanity/client' import { toPlainText } from '@portabletext/toolkit' const sanity = createClient({ projectId: '...', dataset: 'production', apiVersion: '2024-01-01' }) const algolia = algoliasearch(process.env.ALGOLIA_APP_ID!, process.env.ALGOLIA_ADMIN_KEY!) const index = algolia.initIndex('posts') const posts = await sanity.fetch(` *[_type == "post" && defined(publishedAt)] { "objectID": _id, title, "slug": slug.current, "excerpt": excerpt, "body": pt::text(body), publishedAt, "category": category->title } `) await index.saveObjects(posts) console.log(`Indexed ${posts.length} posts`) Інкрементальне оновлення у вебхуці
// В app/api/webhooks/sanity/route.ts — додати: if (_type === 'post') { if (event === 'delete') { await algoliaIndex.deleteObject(body._id) } else { const doc = await sanityClient.fetch(` *[_id == $_id][0] { "objectID": _id, title, "slug": slug.current, "body": pt::text(body) }`, { _id: body._id }) if (doc) await algoliaIndex.saveObject(doc) } } Як синхронізація через webhooks відрізняється від polling?
| Метод | Затримка | Навантаження на сервер | Складність реалізації |
|---|---|---|---|
| Polling (кожні 10 сек) | 10 сек в середньому | Висока (постійні запити) | Низька |
| Webhook | <1 сек | Мінімальна (тільки при змінах) | Середня |
Вебхуки майже не навантажують API і забезпечують реактивність у реальному часі. Polling же витрачає зайві ресурси та створює затримку.
Як налаштувати сповіщення у Slack?
Вебхук можна використовувати для оповіщення команди. Наприклад, при публікації нової статті надсилаємо повідомлення в Slack-канал:
// app/api/webhooks/sanity-slack/route.ts export async function POST(req: Request) { const { isValidSignature, body } = await parseBody(req, process.env.SANITY_WEBHOOK_SECRET!) if (!isValidSignature) return Response.json({ error: 'Unauthorized' }, { status: 401 }) await fetch(process.env.SLACK_WEBHOOK_URL!, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ text: `📝 Нова стаття опублікована: *${body.title}*`, attachments: [{ text: `https://yoursite.com/blog/${body.slug}`, }], }), }) return Response.json({ notified: true }) } Типові помилки при налаштуванні вебхуків
- Ігнорування Secret — зловмисник може нескінченно тригерити ревалідацію.
- Відсутність фільтра — вебхук спрацьовує на всі типи документів, включаючи системні (наприклад,
sanity.imageAsset). - Занадто широка проекція — передаєте весь документ, хоча потрібні тільки
_idіslug. Збільшує час обробки та витрати на bandwidth. - Немає обробки помилок — якщо зовнішній сервіс (Algolia, Slack) недоступний, вебхук падає. Додайте try-catch і чергу повторних спроб.
Перед деплоєм протестуйте вебхук за допомогою Postman або curl, надіславши POST-запит з правильним підписом. Переконайтеся, що обробник повертає 200 і кеш інвалідується. Також перевірте обробку помилок: якщо Algolia недоступний, вебхук не повинен падати — використовуйте try-catch і чергу повторних спроб.
Що входить у налаштування «під ключ»
| Компонент | Опис | Термін |
|---|---|---|
| Вебхук ISR | Налаштування ендпоінту, перевірка підпису, ревалідація кешу Next.js | 0,5 дня |
| Синхронізація Algolia | Повна індексація + інкрементальні оновлення через вебхук | 1 день |
| Сповіщення (Slack/Telegram) | Налаштування каналу, форматування повідомлень | 0,5 дня |
| Документація | README з описом архітектури, змінних середовища та інструкцією по деплою | включено |
| Підтримка після запуску | 2 тижні моніторингу та виправлення помилок | включено |
Орієнтовні терміни: від 0,5 до 3 днів залежно від кількості інтеграцій. Вартість розраховується індивідуально. Економія на інфраструктурі після впровадження вебхуків суттєва. Зв'яжіться з нами, щоб отримати точну оцінку для вашого проєкту.
Докладніше про Sanity Webhooks.
Зверніться до нас за консультацією — ми допоможемо налаштувати надійну інтеграцію Sanity з вашим стеком. Наш досвід — 10+ років розробки на Next.js і Sanity, 50+ реалізованих проєктів. Гарантуємо документацію та підтримку після запуску. Замовте аудит вашої архітектури, щоб виявити вузькі місця.







