Guide

SEO metadata extraction

--assisted-crawl fetches the rendered page behind each post, so the titles, meta descriptions, OpenGraph tags and hreflang alternates a plugin renders — and the REST API never exposes — leave with the content. The same pass records the site's own marketing wiring into metadata.json.

The --assisted-crawl option enables extraction of SEO metadata by crawling actual page URLs. This is useful when:

  • RankMath, Yoast, or other SEO plugins are installed
  • SEO data is not exposed via WordPress REST API
  • You need accurate <title> tags and meta descriptions

Extracted SEO Fields

Field Source
seo_title <title> tag content
meta_description <meta name="description">
meta_keywords <meta name="keywords">
og_title <meta property="og:title">
og_description <meta property="og:description">
og_image <meta property="og:image">
canonical_url <link rel="canonical">
lang <html lang="..."> or <meta http-equiv="Content-Language">
hreflangs <link rel="alternate" hreflang="..."> (all language variants)

Usage Example

 1# Export with SEO metadata extraction
 2wpexportjson export --url https://example.com --assisted-crawl -f markdown
 3
 4# Combine with path filter for specific sections
 5wpexportjson export --url https://example.com --path-filter=/blog/ --assisted-crawl -f markdown
 6
 7# With authentication for protected sites
 8wpexportjson export --url https://example.com --auth-user admin --auth-pass secret --assisted-crawl
 9
10# Exclude specific SEO tags from extraction
11wpexportjson export --url https://example.com --assisted-crawl --exclude-tags 'meta:description,og:title'
12
13# With rate limiting to prevent server overload (500ms delay between requests)
14wpexportjson export --url https://example.com --rate-limit 500 -f markdown
15
16# Resume interrupted export (checkpoint is saved automatically)
17wpexportjson export --url https://example.com --resume -f markdown

Site-level marketing metadata

--assisted-crawl also reads the home page once and records the site's marketing wiring into metadata.json under marketing, so a migration can configure the target instead of re-entering it by hand:

 1{
 2  "marketing": {
 3    "verification": {
 4      "google-site-verification": "abc123",
 5      "facebook-domain-verification": "fb456"
 6    },
 7    "social_profiles": {
 8      "facebook": "https://facebook.com/example",
 9      "instagram": "https://instagram.com/example"
10    },
11    "og_site_name": "Example Site",
12    "og_image": "https://example.com/wp-content/uploads/2024/05/social.jpg",
13    "twitter_site": "@example",
14    "favicon": "https://example.com/favicon-192x192.png",
15    "apple_touch_icon": "https://example.com/apple-touch-icon.png",
16    "theme_color": "#0f172a"
17  }
18}

The theme's palette

marketing.colors carries the palette by role — primary, secondary, accent, text, background, link — so a migrated site arrives in its own colours rather than the target theme's defaults.

It is read from the CSS custom properties a theme declares (block themes, Elementor, GeneratePress 3.x). A theme that declares none has not stopped having a palette: classic themes write their colours as ordinary rules, so the roles are then taken from body (background and text), a (link), the header or navigation rule (primary, falling back to theme_color, which is the brand colour by definition) and the button rule (accent).

WordPress core's own --wp--preset--color--* properties are never read: they are Gutenberg's defaults, identical on every site, and recording them would say something false about this one. The background and text pair is contrast-checked before it is emitted — two rules that cannot be a page's real body pair are two different contexts read as one, and nothing is recorded rather than a guess.

Favicon, apple-touch-icon and logo are read from the document's <link rel=...> tags (the largest declared favicon size wins), social profiles from <header> and <footer> links, and relative paths are resolved to absolute URLs. Everything is best-effort: a value the site does not declare is omitted rather than invented. Tracking identifiers (GA4, GTM, Meta Pixel, Hotjar, Clarity, …) are recorded separately under analytics.