Search8 min read

How to Integrate Swiftype with Your Headless CMS

Connect Swiftype to your headless CMS so published articles, product pages, docs, and support content appear in search within seconds.

Published April 29, 2026
01 — Overview

What is Swiftype?

Swiftype is a hosted search platform from Elastic for building site search and application search experiences. Teams use it to index pages or structured records, tune relevance, manage synonyms, and review search analytics without running their own search cluster. It’s commonly used for documentation sites, marketing sites, product catalogs, help centers, and internal knowledge bases.


02 — The case for integration

Why integrate Swiftype with a headless CMS?

Search gets messy when your content and your search index drift apart. An editor updates a support article, but Swiftype still shows the old title. A product page gets unpublished, but customers can still find it in search. A category name changes, and now half your filters are wrong.,Connecting Swiftype to a headless CMS fixes that gap by making the search index react to content events. When content is published, updated, or deleted, a webhook or server-side function can send the right document shape to Swiftype’s Documents API. That means the Swiftype engine contains clean fields like title, slug, category, excerpt, body text, and updated_at instead of scraped HTML.,With Sanity’s AI Content Operating System, structured content lives in the Content Lake as typed JSON. GROQ selects exactly the fields Swiftype needs, including referenced data like author names or category titles. Webhooks or Functions trigger the sync on publish events, so you don’t have to run a nightly batch job, wait for a crawler, or ask editors to copy content into two systems.


03 — Architecture

Architecture overview

A typical Swiftype integration starts when an editor publishes or changes content in Sanity Studio. That mutation is written to the Content Lake, then a Sanity webhook or Function runs immediately. The sync code receives the document ID, uses @sanity/client with a GROQ query to fetch the search-ready fields, maps the result to a Swiftype document, and calls Swiftype’s App Search Documents API at https://{hostIdentifier}.api.swiftype.com/api/as/v1/engines/{engineName}/documents with a private API key. For deletes or unpublishes, the same flow calls the DELETE documents endpoint with the Sanity document ID. On the front end, your site or app sends the user’s query to Swiftype, displays ranked results, and can use Swiftype features like facets, synonyms, curations, and analytics.


04 — Use cases

Common use cases

🔎

Documentation search

Index article titles, body text, product versions, and tags so users can filter Swiftype results by version, category, or content type.

🛍️

Product catalog search

Sync product names, descriptions, categories, availability labels, and merchandising fields from Sanity into a Swiftype engine.

đź§­

Marketing site search

Search across landing pages, case studies, blog posts, and resources with Swiftype relevance tuning and synonym controls.

🧑‍💻

Support knowledge base search

Push published help articles to Swiftype so customers can find current answers without waiting for a crawler to revisit the page.


05 — Implementation

Step-by-step integration

  1. 1

    Set up Swiftype

    Create a Swiftype or Elastic App Search engine for the content you want to index. Copy the host identifier, engine name, and a private API key. If you’re using Node, install swiftype-app-search-node for the client SDK, or call the Documents API directly with fetch.

  2. 2

    Model search fields in Sanity Studio

    Define schema fields that search needs, such as title, slug, excerpt, body, category, tags, audience, and publishedAt. Add fields for search-specific controls only if your editors need them, such as noIndex, boostKeywords, or searchSummary.

  3. 3

    Write the GROQ query

    Use GROQ to fetch one clean search document. Join referenced fields in the same query, such as category->title or author->name, and convert Portable Text to plain text with pt::text(body) before sending it to Swiftype.

  4. 4

    Create the sync trigger

    Use a Sanity webhook for an HTTP endpoint, or use Functions to run the sync code server-side on content mutations without external infrastructure. Filter the trigger to published document types like article, product, guide, or helpArticle.

  5. 5

    Send documents to Swiftype

    Map each Sanity document to a Swiftype record with a stable id, title, url, body, category, and updated_at. POST an array of documents to Swiftype’s Documents API for creates and updates, and DELETE by id when content is removed.

  6. 6

    Test search behavior

    Publish a test document, confirm it appears in the Swiftype engine, then test the front end with real queries, filters, misspellings, and deleted content. Keep a small test checklist for editors, because search bugs often show up as stale results, missing facets, or unexpected ranking.


06 — Code

Code example

tsapp/api/sanity-to-swiftype/route.ts
import {createClient} from "@sanity/client";

const sanity = createClient({
  projectId: process.env.SANITY_PROJECT_ID!,
  dataset: process.env.SANITY_DATASET!,
  apiVersion: "2025-02-19",
  token: process.env.SANITY_READ_TOKEN,
  useCdn: false,
});

const query = `*[_id == $id][0]{
  _id,
  title,
  "slug": slug.current,
  excerpt,
  "body": pt::text(body),
  "category": category->title,
  _updatedAt
}`;

export async function POST(req: Request) {
  const payload = await req.json();
  const rawId = payload._id || payload.ids?.[0];
  if (!rawId) return new Response("Missing Sanity document ID", {status: 400});

  const id = rawId.replace(/^drafts\./, "");
  const isDelete = payload.transition === "delete" || payload.operation === "delete";

  const endpoint = `https://${process.env.SWIFTYPE_HOST_IDENTIFIER}.api.swiftype.com/api/as/v1/engines/${process.env.SWIFTYPE_ENGINE}/documents`;
  const headers = {
    "Authorization": `Bearer ${process.env.SWIFTYPE_PRIVATE_API_KEY}`,
    "Content-Type": "application/json",
  };

  if (isDelete) {
    const res = await fetch(endpoint, {
      method: "DELETE",
      headers,
      body: JSON.stringify([id]),
    });
    if (!res.ok) throw new Error(await res.text());
    return Response.json({deleted: id});
  }

  const doc = await sanity.fetch(query, {id});
  if (!doc) return Response.json({skipped: id});

  const swiftypeDoc = {
    id: doc._id,
    title: doc.title,
    url: `/articles/${doc.slug}`,
    excerpt: doc.excerpt,
    body: doc.body,
    category: doc.category,
    updated_at: doc._updatedAt,
  };

  const res = await fetch(endpoint, {
    method: "POST",
    headers,
    body: JSON.stringify([swiftypeDoc]),
  });
  if (!res.ok) throw new Error(await res.text());

  return Response.json({indexed: doc._id});
}

07 — Why Sanity

How Sanity + Swiftype works

Build your Swiftype integration on Sanity

Sanity gives you structured content in the Content Lake, real-time event triggers, and flexible APIs to keep Swiftype indexes current.

Start building free →

08 — Comparison

CMS approaches to Swiftype

CapabilityTraditional CMSSanity
Search document shapeOften indexes rendered pages, so Swiftype may receive navigation text, footer links, and duplicate copy.Uses GROQ to create one clean Swiftype record with typed fields and joined references.
Sync timingOften depends on crawlers, plugins, or scheduled jobs, which can leave stale results after edits.Uses webhooks or Functions to trigger Swiftype indexing on publish, update, and delete events.
Field-level controlSearch fields are often tied to page templates or plugin settings.GROQ projections send only the fields Swiftype needs, including plain text from Portable Text.
Delete and unpublish handlingDeleted pages may stay searchable until the crawler or plugin catches up.Mutation events can call Swiftype’s DELETE documents endpoint with stable Sanity document IDs.
Editorial search metadataEditors may depend on generic SEO fields that don’t match search behavior.Sanity Studio can add search-specific fields, validation, previews, and help text for editors.

09 — Next steps

Keep building

Explore related integrations to complete your content stack.

Ready to try Sanity?

See how Sanity's Content Operating System powers integrations with Swiftype and 200+ other tools.