๐ 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
Add a webhook endpoint to your site that accepts POST requests and stores blog posts
Protect your endpoint with a secret Bearer token to prevent unauthorized requests
Add your webhook URL and token under Publishing Connections in the dashboard
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:
- Add the code to your project
- Set
SEOBOT_SECRET_TOKENin your .env file โ make sure to also add this env var in your hosting provider (Vercel, Netlify, etc.), not just locally - Deploy your changes
- Use your API endpoint URL when connecting to Fast SEO Fix
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/publishImportant: 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
| Field | Type | Description |
|---|---|---|
title | string | The AI-generated post title, SEO-optimized with the primary keyword |
slug | string | URL-safe slug, e.g. how-to-improve-seo. Unique per post. Use this as the URL path on your site |
publishDate | string (ISO 8601) | Scheduled publish date as a UTC timestamp. Use for displaying the post date and for ordering |
author | string | Author name as configured in your publishing connection settings |
categories | string[] | List of category names. May be empty if no categories are configured |
tags | string[] | List of tags, derived from the post's target keywords |
contentHtml | string | Full 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 |
contentMarkdown | string | Full 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) |
content | string | The original raw Markdown as generated by the AI, without images. Kept for backwards compatibility โ prefer contentHtml or contentMarkdown |
excerpt | string | Short description (up to 160 characters). Use as the post card summary in blog list pages |
tldr | string | null | AI-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 }[] | null | 5 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.title | string | SEO title, optimized to ~60 characters. Use in <title> and og:title |
seoMeta.description | string | Meta description, ~150-160 characters. Use in <meta name="description"> and og:description |
seoMeta.keywords | string[] | Target keywords for the post |
seoMeta.ogImage | string | URL 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 |
featured | boolean | Whether the post is marked as featured. Use to highlight posts in your blog layout |
status | string | Always "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
Authorizationheader matches yourSEOBOT_SECRET_TOKENenvironment variable - Test Connection button โ Use the Test Connection button in the dashboard to send a sample payload to your endpoint