ForestSEO

Payload CMS Integration

Connect Forest SEO to Payload CMS for headless content management with flexible schema mapping and API-based publishing.

Connect Forest SEO to Payload CMS for powerful headless content management. Payload's flexible architecture allows custom field mapping, making it perfect for developers who need control over their content structure.


✅ Prerequisites

Before connecting Payload CMS, ensure you have:

RequirementDetailsDocumentation
Payload CMS InstanceSelf-hosted or cloudpayloadcms.com
API AccessREST or GraphQL enabledAPI Docs
API KeyAuthentication tokenAuthentication
Collections ConfiguredContent schema definedCollections
Admin AccessUser with API permissionsAccess Control

💡 Note

Payload CMS is fully open-source and self-hosted. You have complete control over your data and deployment.


🚀 Setup Guide

Step 1: Prepare Payload CMS


Step 2: Configure Collections

Example Blog Post Collection:

// collections/Posts.ts
import { CollectionConfig } from 'payload/types';

const Posts: CollectionConfig = {
  slug: 'posts',
  admin: {
    useAsTitle: 'title',
  },
  access: {
    read: () => true,
  },
  fields: [
    {
      name: 'title',
      type: 'text',
      required: true,
    },
    {
      name: 'content',
      type: 'richText',
      required: true,
    },
    {
      name: 'slug',
      type: 'text',
      required: true,
      unique: true,
    },
    {
      name: 'metaTitle',
      type: 'text',
      maxLength: 60,
    },
    {
      name: 'metaDescription',
      type: 'textarea',
      maxLength: 160,
    },
    {
      name: 'featuredImage',
      type: 'upload',
      relationTo: 'media',
    },
    {
      name: 'categories',
      type: 'relationship',
      relationTo: 'categories',
      hasMany: true,
    },
    {
      name: 'tags',
      type: 'relationship',
      relationTo: 'tags',
      hasMany: true,
    },
    {
      name: 'status',
      type: 'select',
      options: [
        { label: 'Draft', value: 'draft' },
        { label: 'Published', value: 'published' },
      ],
      defaultValue: 'draft',
    },
  ],
};

export default Posts;

Step 3: Create API User

Generate API Credentials:

  1. Login to Payload Admin (usually at /admin)
  2. Navigate to Users collection
  3. Click "Create New"
  4. Fill in user details:
    • Email: [email protected] (or your preference)
    • Password: (secure password)
    • Role: Admin or API access role
  5. Save user

Generate API Key:

# Via Payload API
POST /api/users/login
{
  "email": "[email protected]",
  "password": "your-secure-password"
}

# Response includes JWT token
{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "user": { ... }
}

Save the JWT token for Forest SEO integration.


Step 4: Connect in Forest SEO

In Forest SEO Dashboard:

  1. Go to SettingsIntegrations

  2. Click "Add Integration"

  3. Select "Payload CMS"

  4. Fill in connection details:

FieldValueExample
NameIntegration identifier"My Payload Blog"
API URLPayload API endpointhttps://cms.example.com/api
API KeyJWT token from Step 3eyJhbGciOiJIUzI1NiIs...
User CollectionAuth collection slugusers (default)
Default CollectionContent collectionposts
  1. Click "Test Connection" to verify
  2. If successful, click "Save Integration"

⚙️ Field Mapping

Understanding Field Mapping

Payload CMS is schema-flexible, so Forest SEO needs to know how to map content fields:


Default Field Mappings

Configure how Forest SEO fields map to your Payload schema:

{
  "default_fields": {
    "title": "title",
    "content": "content",
    "slug": "slug",
    "excerpt": "excerpt",
    "meta_title": "metaTitle",
    "meta_description": "metaDescription",
    "featured_image": "featuredImage",
    "status": "status",
    "published_at": "publishedAt",
    "categories": "categories",
    "tags": "tags"
  }
}

Field Configuration:

Forest SEO FieldPayload FieldTypeRequired
titletitletext
contentcontentrichText
slugslugtext
excerptexcerpttextarea
meta_titlemetaTitletext
meta_descriptionmetaDescriptiontextarea
featured_imagefeaturedImageupload
statusstatusselect
categoriescategoriesrelationship
tagstagsrelationship

Collection-Specific Mappings

For multiple content types, configure per-collection mappings:

{
  "collection_mappings": {
    "posts": {
      "title": "title",
      "content": "body",
      "featured_image": "coverImage"
    },
    "pages": {
      "title": "pageTitle",
      "content": "pageContent",
      "featured_image": "heroImage"
    },
    "products": {
      "title": "productName",
      "content": "description",
      "featured_image": "productImage"
    }
  }
}

Use Case:

  • Different collections have different schemas
  • Map Forest SEO fields to appropriate Payload fields
  • Maintain consistency across content types

📝 Content Type Support

Rich Text Handling

Payload supports multiple rich text editors:

Forest SEO Compatibility:

EditorSupportFormat
Lexical✅ FullJSON (native)
Slate✅ FullJSON
Markdown✅ FullMarkdown
HTML✅ FullHTML string

Supported Payload Field Types

Payload TypeForest SEO MappingNotes
textText fieldsDirect mapping
textareaLong textMeta descriptions, excerpts
richTextHTML/JSON contentMain article body
numberNumbersReading time, word count
dateTimestampsPublished date, updated date
selectSingle choiceStatus, category
relationshipLinks to other collectionsCategories, tags, authors
uploadMedia referencesFeatured images, galleries
arrayListsMultiple values
blocksFlexible contentAdvanced layouts

🖼️ Media Management

Media Upload Configuration

{
  "media": {
    "collection": "media",
    "folder_field": "folder",
    "alt_field": "alt",
    "caption_field": "caption",
    "default_folder": "forest-seo-uploads"
  }
}

Media Settings:

SettingDescriptionDefault
collectionMedia collection slugmedia
folder_fieldFolder organization fieldfolder
alt_fieldAlt text field namealt
caption_fieldCaption field namecaption
default_folderUpload destinationforest-seo-uploads

Image Upload Process

Image Handling:

  • Upload to Payload Media collection
  • Store in configured folder
  • Set alt text and caption
  • Reference by ID in posts
  • Support multiple sizes (Payload generates)

🔗 Relationships & Taxonomies

Categories Configuration

{
  "taxonomy": {
    "categories": {
      "collection": "categories",
      "label_field": "name",
      "slug_field": "slug",
      "auto_create": true
    },
    "tags": {
      "collection": "tags",
      "label_field": "name",
      "slug_field": "slug",
      "auto_create": true
    }
  }
}

Taxonomy Options:

FieldDescriptionExample
collectionTaxonomy collection slugcategories, tags
label_fieldDisplay name fieldname, title
slug_fieldURL-safe identifierslug
auto_createCreate if doesn't existtrue, false

Relationship Handling

Payload Relationships:

Payload uses relationship fields to link documents:

// In Post collection
{
  name: 'categories',
  type: 'relationship',
  relationTo: 'categories',
  hasMany: true, // Multiple categories
}

{
  name: 'author',
  type: 'relationship',
  relationTo: 'users',
  hasMany: false, // Single author
}

Forest SEO Behavior:

  • Looks up existing relationships by slug/name
  • Creates new entries if auto_create: true
  • Links by ID in Payload
  • Maintains referential integrity

🌍 Localization Support

Multi-Language Configuration

Payload supports localization out of the box:

// payload.config.ts
export default buildConfig({
  localization: {
    locales: ['en', 'es', 'fr', 'de'],
    defaultLocale: 'en',
    fallback: true,
  },
});

Forest SEO Integration:

{
  "locale_field": "locale",
  "localized_fields": ["title", "content", "metaDescription"]
}

Multi-Language Flow:


✅ Testing Your Integration

Connection Test

Verify API connectivity:

Test Checklist:

  1. Click "Test Connection" in integration settings
  2. Verify:
    • API URL is reachable
    • Authentication succeeds
    • Collections are accessible
    • Write permissions granted
    • Media upload works
  3. Review test results
  4. Fix any issues
  5. Save integration

Test Publish

Steps:

  1. In Forest SEO, select an article
  2. Click "Publish""Payload CMS"
  3. Choose collection (if multiple)
  4. Set status to draft
  5. Click "Publish Now"
  6. Wait for confirmation
  7. Check Payload Admin:
    • Navigate to your collection
    • Find the published document
    • Verify all fields mapped correctly
    • Check media uploaded
    • Review relationships

🔧 Troubleshooting

Common Issues


Authentication Errors

Problem: "Unauthorized" or "Invalid token"

Solutions:

  1. Regenerate JWT token via Payload login
  2. Check token hasn't expired (Payload default: 7 days)
  3. Verify API user has correct permissions
  4. Ensure API URL is correct (include /api)

Token Refresh:

POST /api/users/refresh-token
Authorization: Bearer <old-token>

# Returns new token

Field Mapping Errors

Problem: Fields not saving correctly

Solutions:

IssueFix
Field not foundCheck field name spelling
Type mismatchEnsure field types compatible
Required field missingMap all required fields
Rich text formatSet correct content type

Debug Steps:

  1. Review Payload collection config
  2. Check field names match exactly
  3. Verify field types are supported
  4. Test with minimal field set first

Media Upload Issues

Problem: Images not uploading

Check:

  • Media collection exists and is configured
  • API user has upload permissions
  • File size within Payload limits
  • Correct media collection slug in mapping
  • Folder field (if used) exists

Payload Media Permissions:

// collections/Media.ts
access: {
  create: () => true,  // Allow uploads
  read: () => true,
  update: () => true,
}

🚀 Advanced Features

Custom Blocks Support

Payload's block fields allow flexible content structures:

{
  name: 'layout',
  type: 'blocks',
  blocks: [
    {
      slug: 'richText',
      fields: [{ name: 'content', type: 'richText' }],
    },
    {
      slug: 'callout',
      fields: [
        { name: 'text', type: 'text' },
        { name: 'style', type: 'select', options: ['info', 'warning', 'success'] },
      ],
    },
  ],
}

Forest SEO Integration:

  • Converts HTML to appropriate blocks
  • Maps semantic elements to block types
  • Preserves rich formatting

Webhooks & Events

Payload supports webhooks for real-time updates:

// payload.config.ts
export default buildConfig({
  hooks: {
    afterChange: [
      async ({ doc, req, operation }) => {
        if (operation === 'create') {
          // Notify external systems
          await fetch('https://example.com/webhook', {
            method: 'POST',
            body: JSON.stringify(doc),
          });
        }
      },
    ],
  },
});

Use Cases:

  • Notify frontend when content published
  • Trigger builds on Vercel/Netlify
  • Update search indices
  • Sync to CDN

GraphQL Support

Payload auto-generates GraphQL API:

Query Example:

query GetPosts {
  Posts(limit: 10, where: { status: { equals: "published" } }) {
    docs {
      id
      title
      content
      featuredImage {
        url
        alt
      }
    }
  }
}

Forest SEO:

  • Currently uses REST API
  • GraphQL support planned
  • Can be extended via custom implementation

📊 Monitoring & Performance

API Rate Limits

Payload doesn't enforce strict rate limits by default, but consider:

Best Practices:

AspectRecommendationReason
Batch OperationsLimit to 10-20 concurrentAvoid overwhelming server
Image UploadsSequential, not parallelPrevent memory issues
Large ContentChunk if >1MBNetwork stability
RetriesExponential backoffHandle transient errors

Performance Optimization

Tips for Large-Scale Publishing:

  1. Index frequently queried fields

    {
      name: 'slug',
      type: 'text',
      unique: true,
      index: true, // Faster lookups
    }
  2. Use pagination for queries

    • Limit results to 100 per request
    • Implement cursor-based pagination
  3. Optimize media uploads

    • Resize images before upload
    • Use CDN for serving media
    • Enable Payload's image optimization
  4. Cache API responses

    • Implement Redis cache layer
    • Cache collection configurations
    • Invalidate on updates

🔗 Integration with Features

With Content Generation

  • Generate AI content
  • Map to custom schemas
  • Publish to any collection

Learn more about Content →

With Schedules

  • Automate content publishing
  • Support multiple collections
  • Scale to 100+ posts/month

Learn more about Schedules →

With Custom Development

  • Extend with custom fields
  • Build unique content types
  • Full API control

Learn more about Payload →


📚 Next Steps