Migrating from MarkupSEO or Seo Maestro
Field-name mapping, template API swap ($page->seo to $page->seoneo), running the migration script, testing, and uninstalling the legacy module.
Before you start
Migration takes about 20 minutes on a typical site. The steps below work for both MarkupSEO and Seo Maestro. Read through the whole page before starting — the order matters.
Step 1 — Install SEO NEO alongside the existing module
Don't uninstall MarkupSEO or Seo Maestro yet. Install SEO NEO first (see Installation), then run both in parallel briefly while you migrate content and update templates.
During migration you may see two tabs both labelled SEO. SEO NEO adds a NEO badge by default so editors can tell them apart. You can also change the tab label in module config.
Step 2 — Add SEO NEO fields and copy data
Add seoneo_tab to each template that needs SEO NEO. From version 1.1.0, saving the template auto-inserts the remaining SEO fields.
Copy legacy field values into the SEO NEO fields at your own pace. For one-off bulk tasks (copying summary to seoneo_description, bulk noindex on login pages, etc.), use Tracy Console with a site-specific script or the ProcessWire API directly.
Disable auto-inject on whichever module is not yet authoritative for frontend output. Running both with auto-inject enabled produces doubled meta tags in the page source.
Step 3 — Rewrite template API calls
Both legacy modules expose SEO data via $page->seo. SEO NEO uses $page->seoneo. The namespace shape mirrors Seo Maestro, so the rewrite is usually a find-replace.
From Seo Maestro
// Full render
echo $page->seo; → echo $page->seoneo;
echo $page->seo->render(); → echo $page->seoneo->render();
// Per-group partials (namespace shape is identical)
echo $page->seo->opengraph->render(); → echo $page->seoneo->opengraph->render();
// or: $page->seoneo->og->render()
echo $page->seo->twitter->render(); → echo $page->seoneo->twitter->render();
From MarkupSEO
// Full render
echo $config->seo->render(); → echo $page->seoneo->render();
// Value getters
echo $config->seo->title; → echo $page->seoneo->title;
echo $config->seo->description; → echo $page->seoneo->description;
Step 4 — Field name mapping
| Old field (MarkupSEO / Seo Maestro) | SEO NEO field |
|---|---|
seo_title / seomaestro_title | seoneo_title |
seo_description / seomaestro_description | seoneo_description |
seo_keywords | seoneo_keywords |
seo_canonical | seoneo_canonical |
seo_noindex / seomaestro_robots_noindex | seoneo_noindex |
seo_nofollow / seomaestro_robots_nofollow | seoneo_nofollow |
seo_og_image / seomaestro_opengraph_image | seoneo_og_image |
seo_og_type | seoneo_og_type |
seo_author | seoneo_author (optional — add to templates that need per-page authors) |
If your old templates use different field names, the Field mapping section in module config lets you point each role at any field name. See Configuration.
Step 5 — Test on a staging environment
View a representative sample of pages and check the rendered <head> source on each. Confirm title, canonical, og:image, hreflang, and noindex behaviour.
Step 6 — Uninstall the legacy module
Once testing is complete, uninstall MarkupSEO or Seo Maestro. Old fields remain on the page tree until you remove them manually from Setup > Fields.
If your old module handled sitemap, redirects, or analytics, install recommended companion modules before uninstalling — see Why SEO NEO.
Common gotchas
- Double meta tags in source. Disable auto-inject on one module during migration.
- Seo Maestro value getters return null after migration. Replace
$page->seo->opengraph->imagewith$page->seoneo->og->image. - MarkupSEO's
$config->seothrows an error. Replace all references with$page->seoneo.
See also
- Why SEO NEO — feature comparison table.
- Installation — full install steps.
- Template API — the
$page->seoneosurface.
Last updated