Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.siftly.ai/llms.txt

Use this file to discover all available pages before exploring further.

Overview

This guide is for Strapi users who want to publish Siftly-generated content and apply GEO/SEO field recommendations (meta tags, JSON-LD, keywords) directly to their Strapi collections. After following it, you’ll be able to push optimized content with full SEO metadata into your Strapi schema and render it correctly on your frontend. Difficulty: ⚠️ Some technical setup — Strapi is headless, so you control the schema and frontend rendering. Strapi is an open-source headless CMS that lets you design your own content types and serve them through a REST or GraphQL API. The Siftly–Strapi integration pushes content directly into your collection using the Strapi REST API, respecting your schema’s field names and Draft & Publish settings.
Siftly to Strapi publish flow — content editor to REST API to live entry
This integration is built for Strapi 5 (self-hosted and Strapi Cloud). Strapi 4 instances will also work for basic fields, but new features like the ?status= query parameter and documentId responses require Strapi 5.

Prerequisites

Before connecting, you’ll need:
  • A running Strapi 5 instance — either Strapi Cloud or a self-hosted deployment reachable over the public internet
  • Admin access to the Strapi dashboard so you can create an API token
  • A collection type with at least a title, slug and content/body field (e.g. the default articles collection)
Local Strapi instances on http://localhost:1337 can only be used by Siftly when running Siftly in development mode. Production Siftly requires an HTTPS endpoint reachable from the internet, such as https://cms.yourdomain.com.

Step 1: Create a Strapi API token

Siftly authenticates with Strapi using a server-to-server API token — no OAuth involved. You generate this token once inside the Strapi admin panel.
  1. Log in to your Strapi admin panel (https://your-strapi-host/admin)
  2. Go to Settings → Global Settings → API Tokens
  3. Click Create new API Token
  4. Fill out the form:
    • Name: Siftly (or anything memorable)
    • Description: optional
    • Token duration: Unlimited is recommended so publishing doesn’t break when the token silently expires
    • Token type: Full access (recommended) or Custom (see below)
  5. Click Save
  6. Copy the token shown on the confirmation screen — Strapi only displays it once
Strapi shows the token only on the creation screen. If you navigate away before copying it, you’ll need to regenerate the token. Store it in a password manager.

Required permissions

Siftly needs to read your collection (to validate the connection) and create documents in it (to publish content). When Draft & Publish is enabled on the collection, Siftly also needs publish permission so it can flip the new entry from draft to live in a single call. The table below lists the exact Strapi permissions Siftly calls during each step of the flow:
Siftly actionStrapi permissionAPI call
Validate the connectionfind on your collectionGET /api/{collection}?pagination[pageSize]=1
Publish contentcreate on your collectionPOST /api/{collection}?status=published
Save as draftcreate on your collectionPOST /api/{collection}?status=draft
Publish now (D&P enabled)publish on your collectionpart of the same POST above

Option A — Full access (easiest)

Select Full access when creating the token. This grants every permission on every content type, which is simple and future-proof (adding new mapped fields won’t require a token change).

Option B — Custom token (least privilege)

If your security policy requires scoping the token to the minimum:
  1. On the Create new API Token screen set Token type to Custom
  2. In the permissions tree, expand your collection (e.g. Article)
  3. Tick these permissions on that collection only:
    • find — lets Siftly verify the connection during setup
    • create — lets Siftly create content entries
    • publish — lets Siftly publish on create (only needed when Draft & Publish is enabled on the collection)
  4. Leave everything else unticked and save
If you are using Strapi 4 or have Draft & Publish turned off on the collection, the publish permission is not available or not required — create is enough. Content created via the REST API is immediately visible.

Step 2: Connect Strapi in Siftly

  1. In Siftly, go to Settings → Integrations (or open Integrations from the content editor)
  2. Click Connect next to Strapi
  3. Fill in the form:
FieldDescriptionExample
Base URLThe root URL of your Strapi instance. No trailing slash, no /admin, no /api.https://cms.mycompany.com
API TokenThe Full access or custom token from Step 1.f0a1…
Collection TypeThe plural API ID of the collection Siftly should publish into. Find it in Content-Type Builder → your type → Advanced Settings → API ID (Plural).articles
Blog Base URL (optional)Public domain where your blog is served — used to build the final published URL returned to Siftly.https://mycompany.com/blog
  1. Click Next: Map Fields
Siftly calls GET /api/{collection}?pagination[pageSize]=1 to confirm the URL and token are valid before moving to the mapping step. Typical failures:
  • 401 Invalid Strapi API token — double-check you copied the full token
  • 403 Insufficient permissions — the custom token is missing find; switch to Full access or add find
  • 404 Collection not found — the Collection Type value must be the plural API ID (e.g. articles, not Article)

Step 3: Pick the content field format

Strapi 5 has two common rich-text field types, and they accept very different payloads. Before mapping fields you must tell Siftly which one your content field uses.
FormatWhen to pick itWhat Siftly sends
HTML / MarkdownContent field is Text (long), Rich text (Markdown), or any plain-string fieldRaw HTML string
Rich text (Blocks)Content field is the Strapi 5 Rich text (Blocks) typeStrapi Blocks JSON (headings, paragraphs, lists, quotes)
Check your content field’s type in Content-Type Builder → your collection → your content field. Strapi 5 defaults to Rich text (Blocks) on new collections.
Sending HTML into a Rich text (Blocks) field (or Blocks JSON into a Markdown field) produces a 400 validation error. If publishing fails with “must be an array” or “must be a string”, the wrong format is selected here.

Step 4: Field Mapping

Siftly uses a 3-tier field mapping system. Enter the API ID of each Strapi attribute you want Siftly to populate.

Required Fields

Siftly FieldDefault Strapi NameNotes
TitletitlePlain text
SlugslugTypically a Strapi UID field
BodycontentFormat is controlled by Step 3

Optional Fields

Leave any of these blank to skip writing them to Strapi. When mapped, they are auto-populated from your content data.
Siftly FieldTypical Strapi NameField Type
Meta Titleseo.metaTitleText, inside an SEO component
Meta Descriptionseo.metaDescriptionText (long), inside an SEO component
KeywordskeywordsJSON array of strings, or repeatable Text component
CategoriescategoriesJSON array of strings, or repeatable Text component
JSON-LDjsonLdText (long) or JSON — stored as a JSON-stringified array
Word CountwordCountNumber (integer)

Dot notation for components

Strapi Components live under a named key on the document. Siftly supports dot notation to address fields inside a component:
seo.metaTitle        -> data.seo.metaTitle
seo.metaDescription  -> data.seo.metaDescription
Use dot notation for any nested component field.
Media fields (cover / featuredImage / image), relation fields to Users or Tag content-types, and repeatable components are not supported in this release. If your schema requires any of these, either make them optional in Strapi or fall back to a plain string field until full support lands.

Custom Fields

Add extra fields your Strapi collection requires that aren’t part of Siftly’s standard content schema.

Field Types

TypeDescriptionExample
StringPlain textAuthor name, subtitle
NumberNumeric valuePriority, reading time
BooleanTrue/falseFeatured post, comments enabled
JSONStructured objectSEO config, social media metadata
SelectPick from predefined optionsCategory, status, content type

Default Values

Set a default value when adding a custom field. This value pre-fills at publish time — you can override it for each post.

Use Existing Field

Instead of setting a manual default, you can link a custom field to an existing content field. For example, map your Strapi collection’s excerpt field to use the same value as Meta Description. This is useful when your CMS has multiple fields that should contain the same data (e.g., seo.metaDescription and excerpt both using your meta description).

Publishing

Draft vs Published

When publishing, choose between:
  • Draft — content is pushed to Strapi as a draft entry for review in Strapi Admin
  • Published — the entry is created and immediately published
Siftly sends the ?status= query parameter to control this:
Siftly StatusStrapi BehaviorVisible on public site?
PublishedDocument is created and immediately publishedYes, if your frontend queries published entries
DraftDocument is created as a draftNo — you’ll need to publish it in Strapi Admin
If Draft & Publish is disabled on the collection, Strapi ignores ?status= and every entry is live on create.

Custom Fields at Publish Time

If you’ve defined custom fields, they appear in the publish dialog pre-filled with their default values (or auto-filled from linked fields). You can edit them before publishing. Standard fields (title, slug, body, meta data, keywords, categories, JSON-LD, word count) are auto-populated from your content — no manual input needed.

Idempotency

Every publish creates a new entry. Re-publishing the same Siftly content sends a fresh POST and Strapi assigns a new documentId. If you need upsert semantics (one Strapi entry per Siftly content), publish once, then continue editing inside Strapi Admin.

Troubleshooting

The token was rejected. Regenerate a Full access token from Settings → API Tokens and paste the complete token — it’s a long string shown only once on creation.
Your token lacks a required permission. If it’s a Custom token, make sure find, create and (for collections with Draft & Publish) publish are ticked for this collection. Switching to Full access is the simplest fix.
The Collection Type value must be the plural API ID shown in Content-Type Builder — e.g. articles, not Article or /api/articles. Check it under Content-Type Builder → your type → Advanced Settings → API ID (Plural).
Content-field format mismatch. Open Settings → Integrations → Strapi → Edit mapping and switch Content field format between HTML / Markdown and Rich text (Blocks) so it matches the actual type of your content attribute in Strapi.
Your collection has a required field that Siftly didn’t send. Either make the field optional in Strapi, or add it as a custom field in Siftly’s field mapping and supply a value (or default) at publish time.
Draft & Publish is enabled on the collection and you published with status Draft — or the frontend is filtering to publishedAt != null. Re-publish with Published, or open the entry in Strapi Admin and click Publish.

Where to apply Siftly’s recommendations on Strapi

Strapi is headless — it stores data but doesn’t render HTML. You control where SEO fields live in your schema and how your frontend renders them. Here’s the recommended setup. Strapi has an official SEO plugin that adds a reusable SEO component to your content types:
npm install @strapi/plugin-seo
# or
yarn add @strapi/plugin-seo
After installing, add the SEO component to your article collection type in the Content-Type Builder. This gives you:
  • seo.metaTitle — Meta title field
  • seo.metaDescription — Meta description field
  • seo.metaImage — OG image (media field)
  • seo.keywords — Keywords
  • seo.canonicalURL — Canonical URL override
  • seo.structuredData — JSON-LD structured data (JSON field)
Siftly maps directly to these fields using dot notation (e.g., seo.metaTitle).

Meta Title

Schema location: seo.metaTitle (via SEO plugin) or a custom metaTitle text field. Frontend rendering (Next.js example):
// app/blog/[slug]/page.tsx
export async function generateMetadata({ params }) {
  const article = await getArticle(params.slug);
  return {
    title: article.seo?.metaTitle || article.title,
  };
}

Meta Description

Schema location: seo.metaDescription (via SEO plugin) or a custom metaDescription text field. Frontend rendering:
export async function generateMetadata({ params }) {
  const article = await getArticle(params.slug);
  return {
    title: article.seo?.metaTitle || article.title,
    description: article.seo?.metaDescription || article.excerpt,
  };
}

Open Graph Image

Schema location: seo.metaImage (media field via SEO plugin) or a custom image URL text field.
Siftly cannot push image uploads to Strapi media fields currently. Use a plain text field for OG image URLs, or upload images to Strapi manually and reference them.

Canonical URL

Schema location: seo.canonicalURL or a custom canonicalUrl text field. Frontend rendering:
export async function generateMetadata({ params }) {
  const article = await getArticle(params.slug);
  return {
    alternates: {
      canonical: article.seo?.canonicalURL || `/blog/${article.slug}`,
    },
  };
}

Tags & Categories

Schema location: Use a JSON array field (keywords) or a Relation field linking to a Tags collection. Siftly pushes keywords as a JSON array of strings. Your frontend can render them as <meta name="keywords"> or use them for internal filtering/navigation.

JSON-LD Structured Data

Schema location: seo.structuredData (JSON field via SEO plugin) or a custom jsonLd text (long) field. Siftly pushes the full JSON-LD object as a stringified JSON value. Your frontend renders it in the <head>:
// app/blog/[slug]/page.tsx
export default async function ArticlePage({ params }) {
  const article = await getArticle(params.slug);
  
  return (
    <>
      {article.seo?.structuredData && (
        <script
          type="application/ld+json"
          dangerouslySetInnerHTML={{
            __html: JSON.stringify(article.seo.structuredData),
          }}
        />
      )}
      <article>{/* content */}</article>
    </>
  );
}

Keywords

Schema location: keywords JSON array field, or seo.keywords if using the SEO plugin. Frontend rendering:
<meta name="keywords" content={article.keywords?.join(', ')} />

Pushing Siftly recommendations automatically

1

Generate content in Siftly

Siftly produces your article plus meta title, meta description, keywords, and JSON-LD.
2

Click Publish → Strapi

Select your Strapi collection. Choose Draft or Published status.
3

All mapped fields pushed in one call

Siftly sends a single POST /api/{collection} with all mapped fields — content body, SEO component fields, keywords, JSON-LD — in one API call.
4

Frontend picks up new content

Your frontend (Next.js, Nuxt, Gatsby, etc.) fetches the new entry on the next request or build. All SEO metadata renders from the populated fields.

Platform-specific quirks & limitations

Nothing is automatic. Strapi is headless — it stores data but renders nothing. Every meta tag, JSON-LD block, and OG tag must be explicitly rendered by your frontend code. If your frontend doesn’t read and render seo.metaTitle, it won’t appear in HTML regardless of what Siftly pushes to Strapi.
SEO plugin version: The @strapi/plugin-seo component structure may vary between Strapi 4 and Strapi 5. Verify field paths in your Content-Type Builder after installation.
  • Media field limitation: Siftly cannot upload images to Strapi’s Media Library via the content API. Use text URL fields for OG images, or upload images manually and link them.
  • Relation fields: If your categories/tags are a separate collection type with Relations, Siftly cannot create or link relations automatically. Use JSON array fields instead.
  • Component validation: If your SEO component has required fields (e.g., metaTitle is required), Siftly must map and populate them — otherwise the publish will fail with a 400 validation error.
  • Draft & Publish: When enabled, entries created as “Published” are immediately visible to your frontend’s published-content queries. Draft entries require manual publish in Strapi Admin.
  • Incremental Static Regeneration: If your frontend uses ISR (Next.js) or similar, new content may take up to your revalidation period to appear. Trigger a revalidation webhook from Strapi for instant updates.

Validating the setup

After publishing your first entry from Siftly:
1

Check the entry in Strapi Admin

Open your Strapi Admin → collection → find the new entry. Verify all fields (title, slug, body, SEO component, JSON-LD) are populated correctly.
2

View the live page source

Open the rendered page on your frontend. Right-click → View Page Source. Search for:
  • <title> — should contain your meta title value from Strapi
  • <meta name="description" — should contain your meta description
  • <script type="application/ld+json"> — should contain your JSON-LD
3

Run Google Rich Results Test

Go to Google Rich Results Test and paste your page URL. Confirm JSON-LD is detected and valid.
4

Run Schema.org Validator

Go to Schema.org Validator for additional validation.

Difficulty & setup recap

Strapi Setup Summary

AspectRating
Initial setup⚠️ Medium — API token + schema design + field mapping
Applying SEO fields⚠️ Requires @strapi/plugin-seo or custom schema design
JSON-LD⚠️ Stored in Strapi, but frontend must render it explicitly
Ongoing editing✅ Easy — publish from Siftly, content appears in Strapi Admin
Developer needed?Yes — for initial schema setup and frontend rendering code

CMS Integrations Overview

Compare all supported platforms and the unified field mapping system.

Quickstart Guide

Set up your brand and run your first GEO analysis.

Content Generation

How Siftly generates GEO-optimized content and recommendations.

Choosing a CMS for AI Visibility

Our guide to picking the right CMS for GEO optimization.