skip to content →
FIELD_MANUAL / LIVEREVISIONv1.2 · 2026.05.26Updated 2026-05-26CHAPTERS4 FILEDCH_05INTEGRATION
[ CH_05 / FIELD_MANUAL ]API · MONITORING · CMS_ADAPTERS

The field manual.
wire it in, read the signals.

VectraSEO's API and adapter library lets you generate SEO content, publish it to seven CMS platforms, and run continuous site-health monitoring against any sitemap. Authenticate with a JWT obtained via magic link, POST to /api/v1/projects/{id}/posts/generate or /api/v1/projects/{id}/posts/hybrid-generate to start a generation pipeline, then poll /api/v1/jobs/{id} until the job completes. Daily monitors run 42 SEO health rules plus 12 AEO readiness checks and email diff alerts when new issues appear.

[ CH_05.01 / REST_API ]

REST API reference

All endpoints live under /api/v1. Two auth modes: interactive/management endpoints use a session JWT (Authorization: Bearer <jwt>) from magic-link login, while the read-only Analytics API (/projects/{id}/analytics/*) and the agent recommendations feed authenticate with a per-project API key sent as the x-api-key header — generate one under Project → Settings → Analytics API. Analytics calls are metered per project and return X-RateLimit-* headers.

> base_url
https://api.vectraseo.com/api/v1
Authentication
POST/auth/magic-linkRequest magic link
POST/auth/magic-link/verifyVerify token, get JWT
Projects
GET/projectsList projects
POST/projectsCreate project
GET/projects/:idGet project
PUT/projects/:idUpdate project
DELETE/projects/:idDelete project
POST/projects/:id/runTrigger pipeline run
Competitors
GET/projects/:id/competitorsList competitors
POST/projects/:id/competitorsAdd competitor
DELETE/projects/:id/competitors/:cidRemove competitor
POST/projects/:id/competitors/analyzeRun analysis
Content Gaps
GET/projects/:id/gaps?limit=20&cursor=List gaps (paginated)
POST/projects/:id/gaps/identifyIdentify gaps
DELETE/projects/:id/gaps/:gap_idDelete gap
Blog Posts
GET/projects/:id/posts?limit=20&cursor=List posts (paginated)
POST/projects/:id/posts/generateGenerate posts
GET/projects/:id/posts/:post_idGet post
PUT/projects/:id/posts/:post_idUpdate post
DELETE/projects/:id/posts/:post_idDelete post
POST/projects/:id/posts/:post_id/publishPublish to CMS
Blog Publish (Inbound)
POST/blog/publishCreate blog post
PUT/blog/publish/:idUpdate blog post
DELETE/blog/publish/:idDelete blog post
Scheduler
GET/projects/:id/scheduleGet schedule
PUT/projects/:id/scheduleUpdate schedule
DELETE/projects/:id/scheduleDisable schedule
Monitors
GET/projects/:id/monitorsList monitors
POST/projects/:id/monitorsCreate monitor
GET/projects/:id/monitors/:midGet monitor
PUT/projects/:id/monitors/:midUpdate monitor
DELETE/projects/:id/monitors/:midDelete monitor
POST/projects/:id/monitors/:mid/scanTrigger manual scan
GET/projects/:id/monitors/:mid/scansList scan history
GET/projects/:id/monitors/:mid/issuesList active issues
AI Visibility Monitor
GET/projects/:id/visibility/monitorsList AI visibility monitors
POST/projects/:id/visibility/monitorsCreate AI visibility monitor
GET/projects/:id/visibility/monitors/:midGet monitor (with prompts)
PATCH/projects/:id/visibility/monitors/:midUpdate monitor — assistants, prompts, schedule, alerts
DELETE/projects/:id/visibility/monitors/:midDelete monitor
POST/projects/:id/visibility/monitors/:mid/scanTrigger manual citation scan
GET/projects/:id/visibility/monitors/:mid/scansList scan history
GET/projects/:id/visibility/monitors/:mid/scans/:sid/resultsGet scan results per assistant
GET/projects/:id/visibility/summaryPer-project rollup
Keyword Rank Tracker
GET/projects/:id/ranksList tracked keywords + current rank + 30-day history
GET/projects/:id/ranks/keywordsList tracked keywords
POST/projects/:id/ranks/keywordsAdd a tracked keyword
DELETE/projects/:id/ranks/keywords/:keywordRemove a tracked keyword
GET/projects/:id/ranks/summaryTop wins this week + drop alerts rollup
GET/projects/:id/ranks/suggestionsAuto-suggest keywords from project + GSC
POST/projects/:id/ranks/fetchForce a rank refresh for the project
Google Search Console
GET/projects/:id/search/overviewClicks, impressions, CTR, position (28d)
GET/projects/:id/search/queriesTop queries
GET/projects/:id/search/pagesTop pages
GET/projects/:id/search/index-coveragePage indexing buckets from URL Inspection API
GET/projects/:id/search/index-coverage/issuesFAIL-bucket URLs with example fixes
GA4
GET/projects/:id/ga4/statusConnection status + bound property
POST/projects/:id/ga4/authorizeStart OAuth — returns Google consent URL
POST/projects/:id/ga4/propertiesList connectable GA4 properties for the account
POST/projects/:id/ga4/connectBind a GA4 property to the project
DELETE/projects/:id/ga4/connectDisconnect GA4
POST/projects/:id/ga4/refreshForce a GA4 metrics refresh
GET/projects/:id/ga4/pagesGA4 top pages + next-best-actions
Recommendations
GET/projects/:id/recommendationsList active recommendations across monitors
GET/projects/:id/recommendations/:rule_id/:target_kind/:target_idPer-rule detail (cache-or-generate)
POST/projects/:id/recommendations/:rule_id/:target_kind/:target_id/regenerateForce a fresh AI generation
POST/projects/:id/recommendations/:rule_id/:target_kind/:target_id/applyApply the suggested fix
GET/projects/:id/agent/recommendationsAgent-consumable feed (GSC index FAIL buckets, monitor issues, AEO gaps)
Analytics API (x-api-key · read-only · paid plans)
GET/projects/:id/analytics/overviewOne-call snapshot: health (AEO score nested), visibility, search, traffic, ranks; each surface nullable (?period_days)
GET/projects/:id/analytics/search/overviewGSC clicks, impressions, CTR, position + daily series
GET/projects/:id/analytics/search/queriesTop search queries (?limit)
GET/projects/:id/analytics/search/pagesPer-URL performance (?sort, ?limit)
GET/projects/:id/analytics/search/index-coverageGoogle index buckets + sparklines
GET/projects/:id/analytics/traffic/pagesGA4 per-page sessions, revenue, AI referrals
GET/projects/:id/analytics/visibility/summaryPer-monitor AI Visibility rollup (score/citation rate/SoV under latest_scan)
GET/projects/:id/analytics/visibility/monitors/:mid/scans/:sid/resultsPer-prompt, per-assistant results
GET/projects/:id/analytics/health/summarySite-health + AEO score, issue counts
GET/projects/:id/analytics/health/monitors/:mid/scans/:sid/issuesIssues for a scan (severity, category, fix)
GET/projects/:id/analytics/ranksTracked keywords + position history (?days)
Verification Receipt (public)
GET/verification/:project_id/:post_idPublic sanitized truth report for a published post. No auth — gated to status=published.
Automation Status
GET/projects/:id/automationRead-only rollup of generation, publish, monitor, and rank automation tracks
Jobs
GET/jobs/:job_idPoll job status
GET/projects/:id/jobsList project jobs

Analytics API · response shapes

Each /analytics/* response below is the exact shape the live API returns. Three conventions trip up first-time integrators:

  • AEO readiness lives inside health. The overview reports it as health.aeo_score — there is no top-level aeo object.
  • Surfaces can be null. In /overview, each of health, visibility, search, traffic, and ranks is null until that source is connected and has data — normalize defensively.
  • List endpoints are not cursor-paginated. They return { items, count } (visibility results return a bare array); there is no next_cursor/total and no server-side severity/category filters.
GET/projects/:id/analytics/overview

One-call snapshot. AEO is health.aeo_score (no top-level aeo). Every surface is null until its source is connected.

overview.json
{
  "project_id": "prj_8fa21c",
  "period_days": 28,
  "health":     { "health_score": 92, "aeo_score": 78, "urls_checked": 184,
                  "critical": 0, "warning": 3, "info": 9 },
  "visibility": { "visibility_score": 61, "citation_rate": 0.34, "share_of_voice": 0.22 },
  "search":     { "clicks": 12431, "clicks_prev": 11705, "impressions": 402118,
                  "ctr": 0.031, "position": 14.2 },
  "traffic":    { "sessions": 18904, "engaged_sessions": 12880,
                  "key_events": 311, "revenue": 4820.50, "ai_referrals": 842 },
  "ranks":      { "tracked": 48, "top_10": 12, "wins_this_week": 3 },
  "generated_at": "2026-05-29T14:02:11Z"
}
GET/projects/:id/analytics/search/overview

GSC clicks, impressions, CTR, position. The daily time series is the daily field. connected is false until Search Console is linked.

search-overview.json
{
  "connected": true,
  "property_url": "https://acme.com/",
  "period_days": 28,
  "clicks": 12431, "impressions": 402118, "ctr": 0.031, "position": 14.2,
  "clicks_prev": 11705, "impressions_prev": 389220, "ctr_prev": 0.030, "position_prev": 15.1,
  "daily": [
    { "date": "2026-05-01", "clicks": 402, "impressions": 13200, "ctr": 0.030, "position": 14.8 }
  ]
}
GET/projects/:id/analytics/search/queries

Top queries for the most recent refresh. Capped by ?limit (default 25, max 100). Not cursor-paginated.

search-queries.json
{
  "items": [
    { "query": "ai seo audit tool", "clicks": 312, "impressions": 8400, "ctr": 0.037, "position": 6.1 }
  ],
  "count": 25
}
GET/projects/:id/analytics/search/pages

Per-URL performance with previous-period values and deltas. ?sort = clicks | clicks_delta | clicks_loss | position_delta | position_loss; ?limit max 200.

search-pages.json
{
  "items": [
    {
      "kind": "post", "target_id": "post_4f2a",
      "url": "https://acme.com/blog/aeo-guide", "title": "The AEO Guide",
      "clicks": 312, "impressions": 8400, "ctr": 0.037, "position": 6.1,
      "clicks_prev": 280, "impressions_prev": 8010, "ctr_prev": 0.035, "position_prev": 7.2,
      "clicks_delta": 32, "position_delta": 1.1
    }
  ],
  "count": 50
}
GET/projects/:id/analytics/search/index-coverage

Google index buckets + 30-day sparklines. severity is info | warning | critical | neutral — only indexed (live on Google) is info.

index-coverage.json
{
  "connected": true,
  "property_url": "https://acme.com/",
  "buckets": [
    { "bucket": "indexed", "severity": "info", "count": 184, "sparkline": [180,181,184], "examples": [] },
    { "bucket": "crawled_not_indexed", "severity": "warning", "count": 12, "sparkline": [10,11,12], "examples": [] },
    { "bucket": "excluded_noindex", "severity": "warning", "count": 31, "sparkline": [31,31,31], "examples": [] }
  ],
  "total_inspected": 227,
  "rollup_days": 30,
  "quota": { "used_today": 14, "daily_cap": 2000 },
  "last_synced_at": "2026-05-29T06:00:00Z"
}
GET/projects/:id/analytics/traffic/pages

Per-page GA4 metrics with previous-period values + ai_referrals (ChatGPT / Claude / Gemini). Returns { items, count } — not cursor-paginated.

traffic-pages.json
{
  "items": [
    {
      "target_id": "post_4f2a",
      "url": "https://acme.com/blog/aeo-guide", "path": "/blog/aeo-guide",
      "matched": true,
      "sessions": 2104, "engaged_sessions": 1502, "engagement_rate": 0.714,
      "key_events": 41, "revenue": 980.00,
      "sessions_prev": 1788, "engaged_sessions_prev": 1290, "engagement_rate_prev": 0.702,
      "key_events_prev": 33, "revenue_prev": 740.00,
      "ai_referrals": 156, "ai_referrals_prev": 92,
      "source_counts": { "google": 1402, "chatgpt.com": 98, "claude.ai": 41 }
    }
  ],
  "count": 37
}
GET/projects/:id/analytics/visibility/summary

Per-monitor AI Visibility rollup. Headline metrics live under each monitor latest_scan; best_score/worst_score summarise across monitors. No top-level score, no by_assistant.

visibility-summary.json
{
  "has_monitor": true,
  "best_score": 61,
  "worst_score": 54,
  "monitors": [
    {
      "monitor_id": "vis_2a91", "name": "Brand prompts", "enabled": true,
      "schedule": "weekly", "assistants": ["chatgpt", "claude", "gemini"],
      "last_scan_at": "2026-05-27T09:00:00Z", "next_scan_at": "2026-06-03T09:00:00Z",
      "latest_scan": {
        "scan_id": "vscan_88c1", "visibility_score": 61,
        "citation_rate": 0.34, "share_of_voice": 0.22, "accuracy_flags": 2
      }
    }
  ]
}
GET/projects/:id/analytics/visibility/monitors/:mid/scans/:sid/results

Per-prompt, per-assistant results. Returns a plain JSON array (no items envelope). response_accurate is reserved and currently always null.

visibility-results.json
[
  {
    "scan_id": "vscan_88c1", "created_at": "2026-05-27T09:01:12Z",
    "assistant": "chatgpt", "prompt_id": "pr_01",
    "prompt_text": "best ai seo tools 2026",
    "answer_text": "…",
    "cited": true, "text_cited": true, "domain_cited": true,
    "position": 2, "matched_alias": "VectraSEO",
    "matched_source": { "url": "https://acme.com/blog/aeo-guide" },
    "sources": ["https://acme.com/blog/aeo-guide"],
    "competitors_cited": ["arvow.com"], "response_accurate": null,
    "model": "gpt-…", "cost_usd": 0.0021, "error": null
  }
]
GET/projects/:id/analytics/health/summary

Per-monitor site-health rollup. health_score, aeo_score, and issue counts live under each monitor latest_scan. No monitor → { has_monitor: false, monitors: [] }.

health-summary.json
{
  "has_monitor": true,
  "monitors": [
    {
      "monitor_id": "mon_3c1", "domain": "acme.com", "enabled": true,
      "last_scan_at": "2026-05-29T05:00:00Z", "next_scan_at": "2026-05-30T05:00:00Z",
      "latest_scan": {
        "scan_id": "scan_5b2", "finished_at": "2026-05-29T05:03:41Z",
        "urls_checked": 184, "health_score": 92,
        "issue_counts": { "critical": 0, "warning": 3, "info": 9 },
        "aeo_score": 78,
        "aeo_issue_counts": { "critical": 1, "warning": 4, "info": 6 }
      }
    }
  ]
}
GET/projects/:id/analytics/health/monitors/:mid/scans/:sid/issues

Every issue from a scan. Returns { items, count } — not cursor-paginated, and there are no severity/category filter params (filter client-side).

health-issues.json
{
  "items": [
    {
      "scan_id": "scan_5b2", "rule_id": "missing_meta",
      "severity": "warning", "category": "seo",
      "url": "https://acme.com/pricing", "url_hash": "…",
      "message": "Page is missing a meta description.",
      "recommendation": "Add a 140-160 char description summarising the page.",
      "evidence": {}
    }
  ],
  "count": 47
}
GET/projects/:id/analytics/ranks

Tracked keywords under items, each with a history array of { date, position, source }. top_wins_this_week carries the previous-position / jump deltas. ?days default 30, max 90.

ranks.json
{
  "project_id": "prj_8fa21c",
  "window_days": 30,
  "fetched_at": "2026-05-29T06:00:00Z",
  "schedule": { "cadence": "daily", "interval_hours": 24,
                "last_run_at": "2026-05-29T06:00:00Z", "next_run_at": "2026-05-30T06:00:00Z" },
  "items": [
    {
      "keyword": "answer engine optimization",
      "current_position": 6, "last_fetched_date": "2026-05-29", "current_source": "gsc",
      "history": [
        { "date": "2026-05-23", "position": 9, "source": "gsc" },
        { "date": "2026-05-29", "position": 6, "source": "gsc" }
      ]
    }
  ],
  "top_wins_this_week": [
    { "keyword": "answer engine optimization",
      "current_position": 6, "previous_position": 9, "jump": 3 }
  ]
}
[ CH_05.02 / SITE_MONITORING ]

Continuous SEO health checks

Monitors crawl your sitemap on a schedule (or on demand), run 42 SEO health rules plus 12 AEO readiness checks against every URL, and roll results up into 0–100 SEO health and AEO readiness scores. When new critical or warning issues land on a scan, VectraSEO emails your configured recipients.

Creating a monitor

  1. 01Open your project and go to Monitors → New Monitor.
  2. 02Enter your sitemap URL (e.g. https://yoursite.com/sitemap.xml). If you only have a root URL, VectraSEO will try common sitemap locations.
  3. 03Pick a schedule: daily or weekly. An hourly EventBridge rule enqueues due monitors automatically.
  4. 04Optionally add email recipients for issue alerts — fires when new critical or warning issues appear on a scan.
  5. 05Hit Run Scan to kick off the first crawl manually. Scans cover up to 200 URLs and usually complete in 1–3 minutes.

The 54 checks

RULE_ID
SEVERITY
CHECKS
broken_status
CRITICAL
Flags any URL returning a 4xx or 5xx HTTP status code.
redirect_chain
WARNING
Flags URLs that redirect more than twice before hitting a final 200.
spa_placeholder
CRITICAL
Flags SPA routes that return placeholder HTML without the real content — bots see an empty page.
duplicate_initial_html
WARNING
Flags groups of URLs serving byte-identical initial HTML.
missing_meta
WARNING
Flags pages missing a title, meta description, or canonical link.
metadata_quality
WARNING
Flags duplicate, too-short, too-long, or weak title/description/H1 combinations.
canonical_quality
WARNING
Flags canonicals that are inconsistent, non-HTTPS, off-domain, redirected, or noindex.
og_twitter_tags
WARNING
Flags pages missing Open Graph or Twitter Card meta tags used for link previews.
heading_structure
WARNING
Flags pages with zero or more than one <h1> heading.
viewport_meta
WARNING
Flags pages missing <meta name="viewport"> for device-width mobile rendering.
image_alt
INFO
Flags <img> elements shipped without an alt attribute.
image_seo
INFO
Flags generic image filenames, missing dimensions, lazy LCP-image risk, and suspicious alt text.
noindex_in_sitemap
WARNING
Flags pages listed in the sitemap but marked noindex.
x_robots_tag
CRITICAL
Flags HTTP X-Robots-Tag headers that noindex or restrict search appearance.
robots_txt
CRITICAL
Flags robots.txt rules that block sitemap URLs, plus missing sitemap discovery hints.
sitemap_hygiene
WARNING
Flags sitemap entries that are non-HTTPS, redirected, parameterized, fragmented, or not final.
internal_links
WARNING
Flags internal links to broken, redirected, noindex, or non-final URLs in the scanned set.
hreflang
WARNING
Flags invalid, missing-self, unsuccessful, or non-reciprocal hreflang annotations.
mixed_content
WARNING
Flags HTTPS pages that load scripts, images, or stylesheets over HTTP.
slow_response
WARNING
Flags slow origin response times, with critical severity above the 3-second threshold.
performance_static
INFO
Flags static Core Web Vitals risk signals such as page weight, script count, and render blocking.
thin_content
INFO
Flags indexable pages with very little visible text content.
structured_data
WARNING
Flags missing, broken, or incomplete schema.org JSON-LD.
html_lang
WARNING
Flags pages missing a valid html lang attribute.
meta_refresh
WARNING
Flags meta refresh redirects that can confuse crawlers and users.
meta_viewport_scaling
WARNING
Flags viewport settings that disable user zoom or scaling.
link_text_quality
WARNING
Flags vague link labels such as "click here" that hide destination intent.
crawlable_anchors
WARNING
Flags links that are not crawlable anchors with usable href values.
doctype
INFO
Flags pages missing an HTML doctype declaration.
charset_declaration
INFO
Flags pages missing an early character-set declaration.
duplicate_ids
INFO
Flags duplicate element IDs that break labels, anchors, and assistive technology.
frame_title
INFO
Flags iframes without descriptive title attributes.
form_labels
INFO
Flags form controls without accessible labels.
button_link_name
INFO
Flags buttons and links without accessible names.
image_input_alt
INFO
Flags image inputs without alt text.
heading_order
INFO
Flags heading-level jumps that make document structure harder to parse.
tabindex_positive
INFO
Flags positive tabindex values that create unexpected keyboard order.
landmark_main
INFO
Flags pages missing a main landmark.
broken_links
CRITICAL
Probes page links and flags genuinely broken internal and external destinations.
merchant_listing
WARNING
Flags product pages missing merchant-listing structured-data fields.
soft_404
WARNING
Flags 200-OK pages that look like not-found or unavailable content.
duplicate_metadata
WARNING
Flags duplicate titles and descriptions across scanned pages.
aeo_snippet_eligibility
WARNING
Checks whether the page has extractable answer-like copy for AI summaries.
aeo_answer_structure
WARNING
Checks for concise answer blocks near headings and key questions.
aeo_entity_clarity
WARNING
Checks whether brand, organization, and topic entities are named clearly.
aeo_question_coverage
INFO
Checks whether likely user questions are answered directly on the page.
aeo_supporting_evidence
WARNING
Checks for citations, sources, or evidence that support factual claims.
aeo_freshness_signals
INFO
Checks for visible update dates and machine-readable freshness signals.
aeo_author_attribution
INFO
Checks for author, publisher, or organization attribution.
aeo_canonical_consistency
WARNING
Checks whether canonical and citation-target signals agree.
aeo_content_demarcation
INFO
Checks whether main content is clearly separated from navigation and boilerplate.
aeo_speakable_schema
INFO
Checks for optional speakable or answer-friendly structured data.
aeo_llms_txt
INFO
Checks for llms.txt discovery and basic readability.
aeo_crawler_access
WARNING
Checks whether robots.txt blocks common AI answer-engine crawlers.

Health score formula

The score starts at 100 and decays as issues pile up. Weights are tuned so a handful of criticals tank the score faster than a long tail of info noise.

formula.txt
score = max(0, 100 − (critical × 15) − (warning × 5) − (info × 1))
[ EXAMPLE_A ]
2·crit + 5·warn + 12·info
=
33
[ EXAMPLE_B ]
0·crit + 2·warn + 3·info
=
87
[ EXAMPLE_C ]
0·crit + 0·warn + 0·info
=
100

Issue response shape

Individual issues from /monitors/:mid/issues include the rule ID, severity, URL, a short message, a recommendation, and optional technical evidence.

issue.json
{
  "id": "iss_01H...",
  "monitor_id": "mon_01H...",
  "scan_id": "scan_01H...",
  "rule": "broken_status",
  "severity": "critical",
  "url": "https://yoursite.com/products/legacy",
  "message": "Returned 404 Not Found",
  "recommendation": "Either restore the page or add a 301 redirect to the replacement URL.",
  "evidence": {
    "status_code": 404,
    "response_time_ms": 182,
    "final_url": "https://yoursite.com/products/legacy"
  },
  "first_seen_at": "2026-04-12T09:14:22Z",
  "last_seen_at": "2026-04-13T09:14:22Z"
}
[ CH_05.03 / CMS_ADAPTERS ]

Supported CMS platforms

VectraSEO publishes directly to seven CMS options, including Zapier for the long tail. Configure your CMS type and credentials in project settings.

ADAPTER_01
WordPress
<wordpress>

Publishes via the WordPress REST API. Featured images are uploaded to your WordPress media library automatically and attached to the post.

[ CREDENTIALS ]
site_urlusernameapp_password
[ SETUP ]
  1. 01Go to your WordPress admin → Users → Profile → Application Passwords.
  2. 02Enter a name (e.g. "VectraSEO") and click Add New Application Password.
  3. 03Copy the generated password — it will only be shown once.
  4. 04In VectraSEO project settings, enter your site_url, username, and the application password.
Requires WordPress 5.6+ with Application Passwords enabled. Your WordPress site must have HTTPS and the REST API accessible at /wp-json/wp/v2.
ADAPTER_02
Wix
<wix>

Uses the Wix Headless CMS API. VectraSEO creates a draft post and automatically publishes it in a single flow.

[ CREDENTIALS ]
api_keysite_id
[ SETUP ]
  1. 01In your Wix dashboard, go to Settings → API Keys and create a new key with Blog permissions.
  2. 02Copy your API Key and Site ID (found in Settings → General under "Site ID").
  3. 03Paste both values into VectraSEO project settings.
The API key needs Blog → Posts read/write permissions. Wix handles slug generation from the post title.
ADAPTER_03
Shopify
<shopify>

Publishes to your Shopify store's blog via the GraphQL Admin API. Featured images use Shopify's native article image field.

[ CREDENTIALS ]
shop_domainblog_id
[ SETUP ]
  1. 01Install VectraSEO from Shopify Admin and approve the write_content permission.
  2. 02Find your Blog ID: go to Online Store → Blog posts, click your blog, and copy the numeric ID from the URL.
  3. 03Enter shop_domain and blog ID in project settings. The OAuth access token is stored server-side and is never shown in the form.
Shopify publishing uses the OAuth token from the installed app. If publishing fails, reopen VectraSEO from Shopify Admin and confirm the app is connected.
ADAPTER_04
Squarespace
<squarespace>

Publishes directly to a Squarespace blog collection via the Squarespace API. Posts are published immediately (not as drafts).

[ CREDENTIALS ]
api_keysite_idcollection_id
[ SETUP ]
  1. 01In your Squarespace site, go to Settings → Developer API Keys and generate a new API key.
  2. 02Find your Site ID in Settings → General.
  3. 03Find your Collection ID: go to Pages, click your blog page, and note the ID.
  4. 04Enter all three values in VectraSEO project settings.
Requires a Squarespace Business plan or higher for API access. The API key needs content management permissions.
ADAPTER_05
Blogger
<blogger>

Publishes via the Google Blogger API v3. Posts are published immediately with tags applied as labels. Featured images are embedded in the HTML body.

[ CREDENTIALS ]
api_keyblog_id
[ SETUP ]
  1. 01Go to the Google Cloud Console and enable the Blogger API v3.
  2. 02Create an API Key under Credentials (restrict it to the Blogger API for security).
  3. 03Find your Blog ID: open your Blogger dashboard, go to Settings, and copy the numeric blog ID from the URL.
  4. 04Enter the API key and blog ID in VectraSEO project settings.
The API key must have Blogger API v3 enabled in Google Cloud Console. Posts are published as the blog owner.
ADAPTER_06
Zapier
<zapier>

Sends post data to a Zapier webhook, letting you route content to any of Zapier's 6,000+ app integrations. Payloads include an action field (publish, update, or delete) plus full post data.

[ CREDENTIALS ]
webhook_url
[ SETUP ]
  1. 01In Zapier, create a new Zap and choose Webhooks by Zapier as the trigger.
  2. 02Select Catch Hook and copy the generated webhook URL.
  3. 03Paste the webhook URL into VectraSEO project settings.
  4. 04Set up your Zap's action steps (e.g. post to Ghost, Notion, email, Slack).
  5. 05Test by publishing a post from VectraSEO — the payload will appear in Zapier for mapping.
The webhook receives full post data including title, seo_title, body_html, slug, meta_description, excerpt, tags, images (CloudFront URLs), and project context. Use the action field to distinguish between publish, update, and delete events.
ADAPTER_07
Custom API
<custom_api>

Publishes to any REST endpoint. Configurable authentication, path, and retry logic with exponential backoff on server errors.

[ CREDENTIALS ]
endpoint_urlapi_key
[ SETUP ]
  1. 01Ensure your target API accepts POST requests with a JSON body (see payload format below).
  2. 02Enter your endpoint_url (base URL, no trailing slash) and api_key in project settings.
  3. 03Optionally set auth_header (defaults to Authorization: Bearer) and publish_path (defaults to /posts).
  4. 04Your API should return JSON with id and url fields.
VectraSEO retries up to 3 times with exponential backoff (2s, 4s, 8s) on 5xx errors. 4xx errors fail immediately. The payload includes separate reader and SEO metadata: title is the natural post/H1 title, seo_title is the search-result title, meta_description is the search snippet, and excerpt is the reader-facing summary. Images are sent as base64-encoded data. Requests use HTTP/2 with a 120-second timeout.
[ CH_05.04 / CUSTOM_API ]

Publishing to any endpoint

The Custom API adapter lets you ship posts to any REST endpoint. VectraSEO POSTs JSON with the following payload shape:

POST /posts — payload.json
{
  "title": "Post Title",
  "seo_title": "Search Result Title",
  "body_html": "<p>Full HTML content...</p>",
  "slug": "post-title",
  "tags": ["seo", "blogging"],
  "meta_description": "Useful search snippet for this post.",
  "excerpt": "Reader-facing post summary.",
  "author": "Author Name",
  "images": [
    {
      "filename": "image.png",
      "data": "<base64-encoded>",
      "alt": "Alt text"
    }
  ],
  "published_at": "2026-04-05T00:00:00Z",
  "status": "published"
}

Configuration fields

FIELD
REQ
DESCRIPTION
endpoint_url
YES
Base URL of the target API (e.g. https://api.mysite.com)
api_key
YES
Authentication key sent with each request
auth_header
opt
Header name for API key. Default: Authorization (Bearer prefix).
publish_path
opt
POST path appended to base URL. Default: /posts
[ END_OF_MANUAL ]
[ NEED_HELP? ]

Can't find what
you're looking for?

Reach out to the team. We answer every email and we read every bug report.