Moving from WB Custom Product Tabs
This page covers Custom Product Tabs for WooCommerce published by WB (plugin folder wb-custom-product-tabs-for-woocommerce). Two plugins in this niche share that display name, so Product Tabs Studio labels this one "(WB)" everywhere in its admin screens.
That plugin is maintained. Nothing here says you have to move. The reasons shops do are rules that combine include and exclude lists, per-product version history, and a save path that refuses to write an incomplete form.
What that plugin stores
Global tabs are posts of the wb-custom-tabs type. The tab key, the position, an admin nickname and a list of specific products are kept in the meta keys _wb_tab_slug, _wb_tab_position, _wb_tab_nickname and _wb_tab_products. Which products a tab applies to is otherwise decided by the product taxonomy terms assigned to the tab post itself: categories, tags and brands. Tabs written for a single product live in the product's wb_custom_tabs meta as a list of rows. Preferences are stored in a set of wb_cptb_* options.
Before you import anything
Activate Product Tabs Studio and deactivate the WB plugin: both the global tabs and the per-product rows are rendered from where they already are. The adapter runs only while the WB plugin is inactive, so tabs are never printed twice.
The adapter keeps the parts a customer or a stylesheet can see:
- The heading markup stays the WB markup:
<h2 class="wb_cptb_title">with the content wrapped in<div class="wb_cptb_content">. This is applied automatically by the adapter, whatever the legacy CSS setting says, and set as the setting after an import. - Stored positions are used as explicit priorities, so a tab placed before the Description tab stays before it.
- The shortcodes
[wb_cpt_product_tabs]and[wb_cpt_youtube_embed_shortcode]are re-registered as aliases of the equivalent Product Tabs Studio shortcodes, so pages and templates using them keep rendering. The aliases are only registered while the WB plugin is inactive.
What the importer maps
| WB | Product Tabs Studio |
|---|---|
| Post title and content; published tabs, since only those are rendered | The same fields on a global tab. Drafts are imported as drafts. |
| Tab slug | Tab key, verbatim |
| No tab slug | A stable key of the form wb-cptb-{id}, because the original falls back to a position-based key that changes when tabs are reordered. Every such tab is named in the report. |
| Position | Explicit priority. A position of 0 or an empty value becomes automatic placement. |
| Nickname | Admin label, shown in lists and pickers instead of the customer-facing title |
| Specific products | The "Specific products" rule |
| Categories, tags and brands assigned to the tab post | The matching include rules, matched with "any of the rules". Brand rules include child terms; category rules follow the original's own filter for that, which is off by default. |
| No terms and no products | "All products", or "Only where attached manually" when the WB option that hides unassigned tabs is on |
| WB | Product Tabs Studio |
|---|---|
| Title and content | The same, on a tab row belonging to that product |
| Slug, or none | The slug as the tab key, or a best-effort key derived from the row's position, named in the report |
| Position | Explicit priority, kept as an absolute number |
| Nickname | Admin label |
| WB | Product Tabs Studio |
|---|---|
| Hide tab heading | Headings hidden |
| Which WooCommerce default tabs are enabled | The Enabled checkboxes on the Tab order screen |
| Custom content processing (the WB default) | Rendering mode set to isolated |
| The legacy content-processing filter, when a site defines it | Rendering mode set to raw |
| Default tab position | Ignored; each tab's own stored position is kept instead. A line in the report says so. |
Step by step
- Back up the database, or work on staging first.
- Install and activate Product Tabs Studio.
- Deactivate the WB plugin. Do not delete it yet.
- Check a few product pages, including one with a tab written for that single product.
- Products → Tabs Tools & Health → Migrate: Dry run, read the report, then Migrate, then Verify.
- Once verification passes, the adapter switches off and the native data takes over. You can then delete the WB plugin: its uninstall file performs no cleanup, so its data stays in the database either way.
Going back
Rollback deletes only what the migration created: the global tabs it made and the native tab data of products it wrote. Products you edited by hand after the migration are kept and listed. The adapter is switched back on and the WB data, which was never modified, renders again.
Questions
Do I have to import to keep my tabs visible?
No. The adapter renders both global and per-product tabs as soon as the WB plugin is deactivated.
Will my stylesheet still match?
Yes. The WB heading and content markup is reproduced, so selectors on .wb_cptb_title and .wb_cptb_content keep working. If you later restyle, switch legacy CSS to "none" under Tab Settings → Compatibility.
Why did some of my tab keys change?
Only the tabs that never had a slug. The original names those by their position in the list, which shifts when tabs are added or reordered, so the import gives each one a key tied to its post id instead. Every affected tab appears in the migration report, and you can edit the key afterwards.
My tab data is stored as a serialized string. Is that read correctly?
Yes. Serialized values are decoded through a reader that rejects object and class tokens and caps the size it will process.
Will my category rules behave the same?
Yes by default. Category rules are imported with subcategories excluded, which is the original's default, and brand rules with child terms included, which is the original's behaviour for brands. Both are checkboxes you can change on the tab afterwards.