Налаштування 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+ реалізованих проєктів. Гарантуємо документацію та підтримку після запуску. Замовте аудит вашої архітектури, щоб виявити вузькі місця.







