Documentation

Learn how to use Fast SEO Fix to automate your content strategy

๐Ÿ”— Automated SEO - Webhook Setup

Connect Fast SEO Fix to your Next.js, Astro, Gatsby, or custom site to automatically receive published blog posts via HTTP webhook. When you publish a post in Fast SEO Fix, your endpoint receives a POST request with the full post content, SEO metadata, TL;DR, and FAQ โ€” ready to store and render.

How It Works

1. Add API Endpoint

Add a webhook endpoint to your site that accepts POST requests and stores blog posts

2. Secure with Token

Protect your endpoint with a secret Bearer token to prevent unauthorized requests

3. Connect in Fast SEO Fix

Add your webhook URL and token under Publishing Connections in the dashboard

4. Publish Content

Fast SEO Fix sends a POST request to your endpoint whenever you publish a post

Code Templates

Choose your framework and copy the ready-to-use code:

Code Templates

Copy and paste this code into your project to receive published content from SEOBot.

// app/api/seobot/publish/route.js
import { NextResponse } from 'next/server';
import fs from 'fs/promises';
import path from 'path';

export async function POST(request) {
  // Verify authentication
  const auth = request.headers.get('authorization');
  const expectedToken = process.env.SEOBOT_SECRET_TOKEN;

  if (!auth || auth !== `Bearer ${expectedToken}`) {
    return NextResponse.json(
      { error: 'Unauthorized' },
      { status: 401 }
    );
  }

  try {
    const { title, slug, content, publishDate, seoMeta, categories, tags } = await request.json();

    // Create markdown file with frontmatter
    const markdown = `---
title: "${title}"
date: ${publishDate}
slug: ${slug}
description: "${seoMeta.description}"
categories: [${categories.map(c => `"${c}"`).join(', ')}]
tags: [${tags.map(t => `"${t}"`).join(', ')}]
---

${content}`;

    // Write to content directory
    const filePath = path.join(process.cwd(), 'content/blog', `${slug}.md`);
    await fs.writeFile(filePath, markdown, 'utf-8');

    // Optional: Trigger rebuild (Vercel, Netlify, etc.)
    if (process.env.DEPLOY_HOOK_URL) {
      await fetch(process.env.DEPLOY_HOOK_URL, { method: 'POST' });
    }

    return NextResponse.json({
      success: true,
      url: `https://yoursite.com/blog/${slug}`,
      postId: slug,
    });
  } catch (error) {
    console.error('Publish error:', error);
    return NextResponse.json(
      { error: error.message },
      { status: 500 }
    );
  }
}

Setup Steps:

  1. Add the code to your project
  2. Set SEOBOT_SECRET_TOKEN in your .env file โ€” make sure to also add this env var in your hosting provider (Vercel, Netlify, etc.), not just locally
  3. Deploy your changes
  4. Use your API endpoint URL when connecting to Fast SEO Fix
Environment Variable Setup

Add this to your .env or .env.local file:

# SEOBot Publishing Secret
SEOBOT_SECRET_TOKEN=your-secret-token-here

# Optional: Deploy hook for auto-rebuild
DEPLOY_HOOK_URL=https://api.vercel.com/v1/integrations/deploy/...

Generate a secure random token and use it in both your site's environment and in SEOBot's connection settings.

Your Webhook URL:

https://yoursite.com/api/seobot/publish

Important: Security

Generate a strong random token (at least 32 characters). Use the same token in both your site's environment and Fast SEO Fix connection settings. Reject any request that does not include the correct Authorization: Bearer YOUR_TOKEN header.

Payload Structure

Fast SEO Fix sends a POST request with Content-Type: application/json and this body:

{
  "title": "Blog Post Title",
  "slug": "blog-post-title",
  "publishDate": "2024-01-15T00:00:00.000Z",
  "author": "Your Name",
  "categories": ["SEO", "Content Marketing"],
  "tags": ["seo", "content"],
  "contentHtml": "<h1>Blog Post Title</h1><p>Content...</p>",
  "contentMarkdown": "# Blog Post Title\n\nContent...",
  "content": "# Blog Post Title\n\nContent...",
  "excerpt": "Brief summary of the post",
  "tldr": "2-3 sentence plain-text summary of the post.",
  "faq": [
    { "question": "What is X?", "answer": "X is..." },
    { "question": "How does Y work?", "answer": "Y works by..." }
  ],
  "seoMeta": {
    "title": "SEO Title (60 chars)",
    "description": "Meta description (160 chars)",
    "keywords": ["seo", "content marketing"],
    "ogImage": "https://cdn.fastseofix.com/image.png"
  },
  "featured": false,
  "status": "published",
  "customFields": {}
}

Field Reference

FieldTypeDescription
titlestringThe AI-generated post title, SEO-optimized with the primary keyword
slugstringURL-safe slug, e.g. how-to-improve-seo. Unique per post. Use this as the URL path on your site
publishDatestring (ISO 8601)Scheduled publish date as a UTC timestamp. Use for displaying the post date and for ordering
authorstringAuthor name as configured in your publishing connection settings
categoriesstring[]List of category names. May be empty if no categories are configured
tagsstring[]List of tags, derived from the post's target keywords
contentHtmlstringFull post content as rendered HTML, including headings, lists, tables, links, and all AI-generated images (featured + section images as <img> tags). Use this if you're storing the post in a database or rendering it directly in a template
contentMarkdownstringFull post content as Markdown. Does not reliably include images โ€” use contentHtml if you need images embedded, or reference seoMeta.ogImage for the featured image separately. Use this if you're writing to .md files (e.g. Next.js, Astro, Hugo)
contentstringThe original raw Markdown as generated by the AI, without images. Kept for backwards compatibility โ€” prefer contentHtml or contentMarkdown
excerptstringShort description (up to 160 characters). Use as the post card summary in blog list pages
tldrstring | nullAI-generated 2-3 sentence plain-text summary of the post. Ideal for rendering a highlighted summary box at the top of the article. null for posts generated before this feature was introduced
faq{ question: string, answer: string }[] | null5 AI-generated question and answer pairs based on the post content. Use to render an FAQ section and add FAQPage JSON-LD schema for Google rich results. null for posts generated before this feature was introduced
seoMeta.titlestringSEO title, optimized to ~60 characters. Use in <title> and og:title
seoMeta.descriptionstringMeta description, ~150-160 characters. Use in <meta name="description"> and og:description
seoMeta.keywordsstring[]Target keywords for the post
seoMeta.ogImagestringURL of the AI-generated featured image hosted on CDN. Use as og:image and the post header image. May be empty if image generation is disabled
featuredbooleanWhether the post is marked as featured. Use to highlight posts in your blog layout
statusstringAlways "published" for webhook deliveries

Response

Your endpoint must return a 200 or 201 status code to confirm receipt. Fast SEO Fix will treat any other status code as a failure and show an error in the dashboard. The response body can be any JSON:

{
  "success": true,
  "url": "https://yoursite.com/blog/blog-post-slug"
}

Testing Your Webhook

  • Use webhook.site โ€” Get a free public URL at webhook.site, add it as a connection in your dashboard, publish a post, and inspect the full payload in your browser
  • Use ngrok โ€” Tunnel your local dev server to a public URL for end-to-end testing with your actual endpoint code
  • Check server logs โ€” All webhook deliveries are logged. Look for the post title and slug to confirm receipt
  • Verify token โ€” Ensure the Authorization header matches your SEOBOT_SECRET_TOKEN environment variable
  • Test Connection button โ€” Use the Test Connection button in the dashboard to send a sample payload to your endpoint
Webhook Setup - Fast SEO Fix Documentation