Shortcodes and filters
Reference for developers: shortcodes, hooks, template overrides, the rendering pipelines and where the data lives.
Shortcodes
[ptstudio_tabs]- Renders the whole WooCommerce tabs template for the current product. Use it when a page builder or block template has dropped the default tabs output. Optional attribute
product_id. [ptstudio_tab]- Renders one panel inline, heading and content. Identify it with
key="size-guide"orid="12"(the global tab's post id); optionalproduct_id. Returns nothing when the tab does not apply to that product, so it is safe to place in a shared template. [ptstudio_youtube]- Embeds a video from
video_id, with optionalwidthandheight. Falls back to a privacy-enhanced iframe when the oEmbed lookup returns nothing.
When data from WB Custom Product Tabs is present and that plugin is inactive, [wb_cpt_product_tabs] and [wb_cpt_youtube_embed_shortcode] are registered as aliases of the first and third.
Storage
- A product's own tabs are one post meta value,
_ptstudio_tabs, holding a JSON string. Version history is_ptstudio_tabs_history. - Global tabs are posts of the
ptstudio_tabtype, with their key, priority, heading, admin label, rules and origin in_ptstudio_-prefixed meta. - Settings are the single option
ptstudio_settings. A compiled index of published global tabs and their rules is kept in an option so a product page never has to query for them. - Every value the plugin writes is a JSON string or a scalar. The only
unserialize()call in the code base is the guarded decoder used to read other plugins' legacy data.
Resolving one product's tabs reads its post meta, that one option and the product's terms. There are no LIKE scans and no extra tables.
Rendering pipelines
Tab content passes through one of three pipelines, chosen per site under Tab Settings → Rendering and overridable per tab:
- Standard
apply_filters( 'the_content', … ), with a re-entrancy guard that falls back to the isolated pipeline if the filter is already running.- Isolated
- The content filters applied by hand, without the theme's own additions: blocks,
wptexturize,convert_smilies,wpautop,shortcode_unautop,prepend_attachment,wp_filter_content_tags, onedo_shortcodepass, then auto-embeds. This is what you want when a page builder rewritesthe_content. - Raw
do_shortcodeonly.
Panel rendering is wrapped in a try/catch. If a pipeline throws, or returns nothing for non-empty input, the failure is logged once per tab per day and the content is re-rendered with the isolated pipeline, then raw. Turning on safe mode forces the isolated pipeline everywhere.
Filters
| Filter | Arguments | Use |
|---|---|---|
ptstudio_resolved_tabs | tabs, product | The resolved tab models for a product, before they become WooCommerce tab entries. |
ptstudio_product_tabs | tabs, product, resolved | The WooCommerce woocommerce_product_tabs array after this plugin has added to it. |
ptstudio_tab_content | html, tab, product | The rendered panel content. |
ptstudio_tab_heading | html, tab, product | The heading markup printed above the content. |
ptstudio_content_pipeline | steps, mode, tab | The list of steps in the isolated pipeline. |
ptstudio_rule_types | types | The rule type registry. This is the extension point the paid tier uses. |
ptstudio_brand_taxonomies | taxonomies | Which taxonomies count as brands for rules. Defaults to product_brand, pwb-brand and yith_product_brand. |
ptstudio_tabs_filter_priority | priority | The priority this plugin uses on woocommerce_product_tabs. Default 10. |
ptstudio_locate_template | path, name | Where a template file is loaded from. |
ptstudio_allowed_html | allowed, context | The allowed HTML map used when sanitising tab content. |
ptstudio_iframe_hosts | hosts | The hosts an iframe in tab content may point at. |
ptstudio_admin_capability | capability | The capability required for settings, tools and migration. Default manage_woocommerce. |
When legacy hook mode is on, the equivalent filters of Custom Product Tabs for WooCommerce are fired as well, so theme snippets written against that plugin keep working.
Actions
| Action | Arguments | Fires |
|---|---|---|
ptstudio_after_product_tabs_saved | product id, tab set | After a product's tabs are written. |
ptstudio_product_tabs_save_aborted | reason, product id, context | When a save was refused by a guard, for example a truncated form. |
ptstudio_after_tab_saved | post id, submitted data | After a global tab is saved. |
ptstudio_migration_finished | plugin, state | After a migration run completes. |
ptstudio_panel_row_fields | tab, index, row | Inside a row of the product panel, for adding fields. |
ptstudio_tab_settings_fields | post | Inside the global tab settings box. |
Template overrides
Two templates control the panel output: tab-heading.php and tab-panel.php. Copy either into yourtheme/product-tabs-studio/ to override it. The heading template can also be sidestepped entirely by setting the heading to hidden.
No wrapper element is added around the heading and the content. WooCommerce's own panel markup already carries a class ending in the tab key, which is what CSS should hook onto.
Endpoints and capabilities
The free plugin registers no REST routes, and its custom post type is not exposed in REST. Admin operations go through admin-ajax, and every handler checks a nonce and then a capability before it does anything: manage_woocommerce for settings, tools, migration, import and export; edit_products for the search and lookup endpoints used by the editors; and edit_product on the specific product for anything that reads or writes one product's tabs. There are no endpoints available to logged-out visitors.
The ptstudio_tab post type uses WooCommerce product capabilities, so shop managers and administrators can edit tabs and other roles cannot.
The plugin source is published on GitHub in the repository product-tabs-studio.