Passer for Craft CMS

Free for content · Pro for the rest

Move the whole site, not the easy half

Craft's own wp-import is good, and it stops halfway. It does not handle WooCommerce, SEO metadata, redirects, menus, widgets or forms — and it reads WordPress over the REST API only. Passer fixes the source layer first, then the six domains that live in it.

Passer

Four ways in, one mapping

A site being moved off WordPress is very often one that is half-broken: behind Basic auth, with /wp-json/ blocked by a security plugin, on a host that will not open a port, or existing now only as a .sql file on someone's laptop. Every source produces the same records, so the mapping you build does not change with the connection you happen to have.

bash
MySQL database    Everything                      A live database, a tunnel, or a restored dump
WXR export file   Content, terms, users, comments  No credentials, no network, works on a dead site
REST API          What REST exposes               Easiest to set up, weakest data
wp-cli over SSH   Everything                      A shell, but no database port

# A WXR export cannot see widgets, because WordPress does not export
# wp_options. Passer greys that phase out and says why, rather than
# importing nothing and reporting success.

Features

The data these domains live in — wp_options for menus and widgets, wp_postmeta for SEO, the wc_* tables for commerce — is barely exposed over REST at all. Passer reads them where they actually live.

WooCommerce → Craft Commerce

Products, variations, attributes, categories, coupons, customers and orders — reading legacy post-based orders or High-Performance Order Storage, whichever this shop uses.

  • Orders arrive as history, keeping the totals the customer was actually charged
  • Anything that does not reconcile is reported, not quietly adjusted

SEO that survives a plugin switch

Yoast, Rank Math, All in One SEO, SEOPress and The SEO Framework. Template variables are expanded, so a title stored as %%title%% %%sep%% %%sitename%% arrives as a title.

  • On a site that switched plugins and never cleaned up, Passer takes whichever plugin has more data for that post

Redirects that point at entries

Redirection, Rank Math, All in One SEO, Safe Redirect Manager, Simple 301 Redirects, the EPS plugin, and a pasted .htaccess.

  • Destinations are resolved through the ID map to the imported content, so a redirect points at the entry rather than at a URL the migration is about to change

Menus, widgets and forms

Menu items that point at posts become relations, not frozen URLs. Widgets with real content are imported; the ones that are configuration are described rather than faked. Contact Form 7, Gravity Forms, WPForms, Ninja Forms and Formidable, with their stored entries.

  • What cannot come across — conditional logic, payment gateways, captcha keys — is listed explicitly rather than silently dropped

Content that arrives intact

Gutenberg blocks are parsed properly, not regexed. Classic content gets the treatment WordPress applies at render time and never stores — paragraphs from double newlines, and bare URLs turned into links. ACF values are read through their field definitions, repeaters and flexible content included.

  • A block nothing handles keeps its rendered markup rather than vanishing, and is named in the report
  • A shortcode with no handler is left in place, because it marks something that needs a decision

Read-only by construction

The database source attempts a write on connect and refuses the credentials if it succeeds. A migration has no business holding write access to the site it is reading, and the failure mode if it does is unrecoverable.

Nothing is required

Passer hard-requires none of the plugins it writes to. SEOmatic, Retour, FreeNav, Formie, Verbb Comments and Craft Commerce are all preferred destinations — and every one has a fallback that needs nothing but Craft.

  • The wizard shows you what it found before you commit to a plan

Detection by evidence

Analyse finds plugins by the traces they left — a table, an option, a meta key — not by asking WordPress which plugins are active. A plugin deactivated last year still has all its data, and that data is exactly what needs migrating.

Seven phases, every one re-runnable

A real migration is never run once: it is run against a copy, examined, corrected, and run again over weeks while the WordPress site is still being edited. Every WordPress record that became something in Craft goes into the ID map, so a second run updates rather than duplicating.

bash
connect → analyse → plan → provision → test-import → run → report

php craft passer/migrate/analyze --plan=1         # what's in the source
php craft passer/migrate/provision --plan=1 -d    # dry-run the content model
php craft passer/migrate/run --plan=1 --provision # provision, then migrate
php craft passer/migrate/run --plan=1 --phases=seo,redirects
php craft passer/migrate/resume 7                 # continue an interrupted run
php craft passer/migrate/report 7

Frequently Asked Questions

The questions worth answering before you migrate anything.

Start with the content, buy the rest when you need it

Lite is free and covers content from a WXR export or the REST API. Pro is $99 with a $79/year renewal, and adds the database and wp-cli sources plus WooCommerce, SEO, redirects, menus, widgets and forms.