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

Global tabs (wb-custom-tabs posts)
WBProduct Tabs Studio
Post title and content; published tabs, since only those are renderedThe same fields on a global tab. Drafts are imported as drafts.
Tab slugTab key, verbatim
No tab slugA 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.
PositionExplicit priority. A position of 0 or an empty value becomes automatic placement.
NicknameAdmin label, shown in lists and pickers instead of the customer-facing title
Specific productsThe "Specific products" rule
Categories, tags and brands assigned to the tab postThe 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
Per-product rows (wb_custom_tabs)
WBProduct Tabs Studio
Title and contentThe same, on a tab row belonging to that product
Slug, or noneThe slug as the tab key, or a best-effort key derived from the row's position, named in the report
PositionExplicit priority, kept as an absolute number
NicknameAdmin label
Options (wb_cptb_*)
WBProduct Tabs Studio
Hide tab headingHeadings hidden
Which WooCommerce default tabs are enabledThe 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 itRendering mode set to raw
Default tab positionIgnored; each tab's own stored position is kept instead. A line in the report says so.

Step by step

  1. Back up the database, or work on staging first.
  2. Install and activate Product Tabs Studio.
  3. Deactivate the WB plugin. Do not delete it yet.
  4. Check a few product pages, including one with a tab written for that single product.
  5. Products → Tabs Tools & Health → Migrate: Dry run, read the report, then Migrate, then Verify.
  6. 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.