Migrating from Advanced Custom Fields
15 min read
WPM Fields › Tools › Migrate from ACF copies what Advanced Custom Fields (ACF) holds into Mass Custom Fields:
- field groups, with their fields, settings and location rules;
- ACF options pages, post types and taxonomies;
- the saved values of posts (all post types), terms, users, comments and options pages.
The migration only reads ACF. It never changes or deletes an ACF field group, an ACF value or any other row ACF owns, so you can run it, compare both plugins side by side and deactivate ACF only when you are happy. If something goes wrong you can reactivate ACF and nothing is lost.
Before you start
- Back up the database. The migration creates tables and writes values. It does not touch ACF data, but a backup costs nothing.
- Keep ACF active while you migrate, if you can. Then ACF's own functions are used to read everything, including field groups that are saved in ACF's
acf-jsonfolder or registered in PHP. If ACF is already deactivated the plugin reads ACF's data straight from the database, which only finds groups, post types, taxonomies and options pages that were created in the ACF screens (they are stored as posts that ACF leaves in the database). - ACF Pro fields need the right plan on this site. Gallery, flexible content and clone are advanced field types. Without a plan that includes them they are listed as not included in your plan and are skipped. See Plans and licensing. Repeater, group, tab and accordion are free.
- If ACF Pro is deactivated but the free ACF is active, repeater, flexible content and clone fields cannot be read (ACF itself does not load them). The report then says None of its sub-fields can be copied. Activate ACF Pro for the migration, or deactivate ACF completely so the database reader is used.
Step by step
- Open WPM Fields › Tools and choose the Migrate from ACF tab. The page loads a report straight away: a dry run that reads ACF and writes nothing. It is refreshed every time you open the tab.
- If nothing is found, the page says No ACF data found.
- The badge in the card header says ACF active or ACF inactive, and the blue notice says either Advanced Custom Fields 6.x is active. or Advanced Custom Fields is not active; its data is read from the database.
- Read the Field Groups list. Every ACF field group has a checkbox (all ticked), a title and these badges:
Badge | Meaning |
|---|---|
Migrated | A previous run already created this group. |
Inactive in ACF | The group is switched off in ACF; it will be created switched off. |
N not copied | N fields or location rules cannot be copied. Open Details. |
The second line shows the key the new group will get, the number of fields, and how many objects have saved values, for example Key book_details · 6 fields · 120 posts, 3 users or No values stored.
- Open Details on rows with a warning badge. It lists, in plain words:
- Field "Intro" (message) is not copied: Message fields only show text and store no value.
- Location rule "block == acf/hero" is left out: Blocks are not supported as a location.
- notes such as a select with several values becomes checkboxes, a key that had to change, or No location rule can be copied, so the group gets no location and its values are not copied. Add location rules and run the migration again.
- Read the lists of Post types, Taxonomies and Options pages:
Badge | Meaning |
|---|---|
Will be created | It will be created. |
Will be created switched off | ACF registers it right now, so the copy starts switched off to avoid two registrations. Switch it on after deactivating ACF. |
Already exists | An item with that name exists here; it is left as it is. |
Cannot be copied | The message explains why (for example a reserved name). |
- Untick the field groups you do not want. Post types, taxonomies and options pages are always included.
- Click Start migration. A dialog asks Start the ACF migration? and repeats that ACF data is left untouched. Confirm with Start migration.
- The definitions are created immediately. The values are then copied in the background, in batches (see Background tasks); you may leave the page. While it runs, a progress bar named Migration progress and the text N of M objects checked update every few seconds.
- When it finishes, the card shows Migration finished (or Migration canceled) with Values of N objects were copied (M values)., a list of what was created or kept, and, if some values could not be converted, N values were skipped with the reason for each (the first 100 are listed).
Cancel, resume and run again
- Cancel migration stops after the current batch. What was already created and copied stays; the status becomes Migration canceled.
- If the background queue stops (for example the queue was cleared or WP-Cron is disabled) a Resume button appears after about five minutes without progress. It queues the batches again.
- You cannot start a second migration while one runs (A migration is already running.).
- The button reads Run migration again after the first run. See below what a second run does.
Running it twice
A second run is safe and is meant to be used, for example when editors kept working in ACF after the first run:
Part | On a second run |
|---|---|
Field groups already migrated | Kept (badge Migrated). The group and its fields are not rebuilt, so changes you made in the builder stay, and fields added in ACF afterwards are not added. |
New ACF groups | Created. |
Post types, taxonomies, options pages | Kept when they exist. |
Values | Copied again from ACF, overwriting the value in the field group table for every field that has a value in ACF. Values you changed only on this side, in fields that ACF has no value for, stay. |
Rows are updated, never duplicated: a post has one row per group.
To copy only some groups, tick only those before starting. To pick up changed field definitions, delete the migrated group in Field Groups first (this also drops its table), then migrate again.
What is copied, exactly
Names and keys
ACF | Mass Custom Fields |
|---|---|
Field group title | Field group label. The key is the title turned into a key ( |
Field name | Field key (the column name), cleaned to lowercase letters, numbers and underscores, at most 50 characters. A name that is reserved or taken gets a suffix; the report lists every rename. Values follow the rename. |
Field label | Field label. |
ACF field key ( | Kept as the field's |
Field types
ACF type | Becomes | Notes |
|---|---|---|
Text, Text Area, Number, Range, Email, URL, Password | same | The field is set to the plain storage mode, as ACF keeps passwords readable, so templates that print them keep working. See Password for the other storage modes. |
WYSIWYG | WYSIWYG | Toolbar basic or full, media upload kept. |
oEmbed | oEmbed | Width and height kept. |
Link | Link | |
Date Picker, Date Time Picker, Time Picker | same | Display format kept. |
Color Picker | Color | A color with transparency (rgba) is not supported and is skipped. |
Icon Picker | Icon | Only Dashicons carry over; media and URL icons are skipped. |
Select | Select | A select that allows several values becomes Checkboxes. |
Checkbox, Radio, Button Group | same | Choices, return value and layout kept. |
Select / Checkbox / Radio without stored choices (choices come from code) | Text (Text Area when several values) | The report explains it. |
True / False | True / false | On and off labels kept. |
Image, File | Image, File | Only the attachment id is stored. Preview size and allowed file types kept. |
Gallery | Gallery | Needs a plan with advanced field types. |
Post Object | Post object | Allowing several posts turns it into Relationship. |
Page Link | Page link | Links to archives are skipped; only posts are copied. |
Relationship | Relationship | Post types and maximum kept. An empty post type list means all public post types except attachments. |
Taxonomy | Taxonomy | Appearance (checkboxes, radio, select, multi-select as search), Save terms and Load terms kept. A taxonomy without admin screens gets a note. |
User | User | Allowed roles kept; one user unless "multiple" is on. |
Google Map | Map | Center, zoom, height kept; address, latitude, longitude and zoom values copied. |
Group | Group | Sub-fields are converted one by one. |
Repeater | Repeater | Minimum, maximum and button label kept. Pagination is not available (all rows show). Only the first 200 rows of a repeater are copied. |
Flexible Content | Flexible content | Needs a plan with advanced field types. Layouts become layouts; sub-fields of all layouts form one list, so a name used by two layouts gets the layout name as prefix ( |
Clone | Clone | Needs a plan with advanced field types. Only a clone of one field group (the whole group or some of its top-level fields) that is part of the same migration can be copied. Clones of several groups, of fields inside other fields, or of groups that are not migrated are skipped. |
Tab, Accordion | Tab, Accordion | Placement, endpoint, open and "close the other accordions" kept. They store no value. |
Message | not copied | Message fields store no value. |
Any type added by another plugin | not copied | Unknown field type, probably added by another plugin. |
A field type that cannot sit inside a group, repeater or flexible content here | not copied | This field type cannot be used inside a group, repeater or flexible content yet. |
A container whose sub-fields cannot be copied | not copied | None of its sub-fields can be copied. |
Field settings
ACF setting | Becomes |
|---|---|
Required, Instructions, Placeholder | the same options |
Default value | The field's default, only when it fits the type (text-like, numbers, true/false = on, or one of the choices). |
Max length | Validation: maximum length |
Min, Max, Step (number, range) | Validation: minimum, maximum, step |
Prepend, Append | Display: prefix, suffix |
Wrapper class, id | Display: wrapper class, id |
Wrapper width (any percent) | Display width: the nearest of 25, 33, 50, 66, 75, 100 |
Conditional logic | Conditional logic, when it is one AND group, or an OR of single rules, using |
Hide on screen | not copied |
Field group settings
ACF | Becomes |
|---|---|
Style (Standard / Seamless) | Style |
Position (After title, Normal, Side) | Position (High, Normal, Side) |
Label placement, Instruction placement | the same options |
Order (menu order) | Order |
Active | Active (inactive groups are created inactive) |
Show in REST API, Show in GraphQL | REST, GraphQL |
Description | Description |
Location rules
ACF location rules and the plugin's are both "any of these sets, each set needs all its rules". A rule without an equivalent removes its whole set, so a group is never shown in more places than it was in ACF. The report lists every rule that was left out. If no set remains, the group is created without a location and its values are not copied until you add rules.
ACF rule | Becomes |
|---|---|
Post Type, Post Template, Post Status, Post Format, Post, Page Template, Page Parent, Page, Current User Role | same rule |
Post Category, Post Taxonomy ( | the same rule with the term id on this site. The term must exist here, otherwise the rule is left out. |
Page Type | same rule, except Parent page, which is not available |
User Form (all, edit, add) | profile / edit / add, as alternatives. Register is not supported. |
User Role (a role) | User role. All becomes any user form. |
Taxonomy (a taxonomy) | Taxonomy screen. All becomes every taxonomy with admin screens. |
Attachment | All only (and a mime type where it means the same) |
Comment | All only |
Menu Item (a specific menu id) | Nav menu |
Options Page | Options page, same slug |
Current User (logged in, viewing back-end) | no rule: edit screens are always in the admin with a logged-in user |
Widget, Block, Menu (settings screen), Current User (anything else), other plugins' rules | not copied |
Operators other than | not copied |
At most 20 sets are kept from one group.
Post types, taxonomies and options pages
- Post types and taxonomies: all labels, visibility, menu, rewrite, archive, capability, REST and "supports" settings that exist in both plugins. Icons: only Dashicons carry over. A post type whose name is reserved or invalid is listed as Cannot be copied.
- Options pages: title, menu title, parent, capability, icon (Dashicons), position, description, update button and updated message. Pages registered in PHP with
acf_add_options_page()are included when ACF is active. Values are read from the option namesoptions_{field name}(or the prefix of the page's custompost_id). A numericpost_idis not supported. - When ACF is active, its own post types and taxonomies are registered right now, so the copies are created switched off (Will be created switched off) and keep working once you switch them on after deactivating ACF.
- When ACF is inactive, a post type and a taxonomy that refer to each other (the usual case) are created together in one run with their links intact: the checks know the names created in the same run, and a taxonomy keeps the post types created before it.
Values
Values are read from the standard places ACF writes them and copied into the new tables:
Object | Where ACF keeps it | Where it goes |
|---|---|---|
Posts (every post type except revisions, including pages and attachments) |
| the group's table, row type posts |
Terms |
| row type terms |
Users |
| row type users |
Comments |
| row type comments |
Options pages |
| row type options |
An object counts as having values of a group when ACF's own reference (_field_name pointing to the field key) is present. Other meta rows are never touched. Every value is converted and then checked by the new field type exactly as if it had been typed, so a value the field does not accept is skipped and listed (The value could not be converted and was skipped. or The value is longer than the column allows and was skipped.).
Conversions worth knowing:
ACF type | Conversion |
|---|---|
Date Picker |
|
Checkbox, multi Select | Stored list; values that are not among the choices are dropped |
Radio, Button Group | The value |
Post Object, Relationship, Taxonomy, User, Gallery | Ids (a URL in a Page Link becomes the post id) |
Image, File | Attachment id |
Repeater | Rows in order, max 200 |
Flexible content | Rows with their layout |
Group, Clone | Sub-values under the field |
The copied values go to the new field group tables only. They are not written to wp_postmeta.
Using both plugins at once
You can keep ACF active after migrating. The two plugins keep separate copies of the values:
- Anything an editor saves in ACF's boxes still goes to ACF's rows (
wp_postmeta). Mass Custom Fields' write bridge deliberately leaves keys that ACF manages alone, so ACF keeps working. Edits made in ACF are not visible in the new table until you run the migration again. - Anything saved in the new boxes goes to the new tables.
- If a group shows in both plugins on the same edit screen, editors see two boxes. Decide which plugin owns the fields before you let editors work again.
Before you deactivate ACF
Work through this list:
When everything matches, deactivate ACF. Its data stays in the database, so you can switch back at any time.
WP-CLI
wp wpmcf acf report
wp wpmcf acf migrate --dry-run
wp wpmcf acf migrate --groups=group_5f3a1b2c4d5e6The CLI runs the whole copy in the foreground. See WP-CLI.
Known limits
- Not migrated, and listed in the report: message fields, field types from other plugins, choice values that are not among the stored choices, repeater rows past 200, rgba colors, media and URL icons, archive URLs in Page Link, options pages with a numeric
post_id, option names with a WPML language suffix, and widget or block values. - Flexible content and clone fields are migrated (on plans that include them) with the limits above.
- Post types and taxonomies are always migrated together with the groups you pick: you cannot leave them out.
- Running the migration does not update field group definitions (see Running it twice).
Troubleshooting
"No ACF data found" although ACF is installed. ACF stores its definitions as posts. Groups defined only in an acf-json folder or in PHP are visible only while ACF is active. Activate ACF and reload the tab.
A field group got the key something_2. A group with the first key already exists. The report says so before you start.
A group migrated but no values arrived. Open its Details. No location rule can be copied... means the group has no location, so there is no table row to put values in. Add location rules in Field Groups, then click Run migration again.
The migration stays on "running". The queue is not processing. Open Tools › Scheduled Actions (WordPress) and run the wpmcf/acf/migrate action, make sure WP-Cron is not disabled, or click Resume. On servers without a working cron use wp wpmcf acf migrate.
Everything works in ACF, but the new box is empty on a post. The post had no ACF reference row (_field_name) for that field, which happens for values written with update_post_meta() outside ACF. Re-save the post in ACF, or copy the value with wpmcf_update_field().
Some values were skipped with "could not be converted". The new field type rejects what ACF stored, for example a choice that no longer exists, a deleted attachment or a post id of a trashed post. Fix the data in ACF and run the migration again.
Still stuck? Contact support