How to Build a WooCommerce Product Catalog Table in WordPress

TableCrafter's WooCommerce Products source lets you display your product catalog as a filterable, searchable, exportable table, sorted by category, filtered by stock status, and exportable to CSV. This is particularly useful for B2B wholesale order sheets, internal inventory snapshots, and product lookup tools that the standard WooCommerce shop grid does not handle well. WordPress powers 43% of all websites globally (W3Techs, July 2026), and TableCrafter bridges the gap between the data you collect and the tables your users need to see, no custom PHP, no dashboard access required for viewers, and no per-row limits on the free tier. The free version on WordPress.org supports CSV, JSON, Google Sheets, and Excel. Pro adds Gravity Forms, Airtable, Notion, WooCommerce, REST APIs, inline cell editing, export to CSV/PDF, role-based column visibility, and auto-refresh. Every table embeds on any page with a [tablecrafter] shortcode or the native Gutenberg block. Notion databases support up to 10,000 rows per database on free plans (Notion documentation, 2025).
When to Use a Product Table Instead of the WooCommerce Shop?
The standard WooCommerce shop page is designed for retail browsing, images, prices, add to cart. A product table is better suited for:
If this step produces unexpected output, check the source data directly in the connected system. TableCrafter passes data through without modification - if a cell displays an unexpected value, the source record contains that value. Use the TableCrafter debug log (Settings > Advanced > Debug Mode) to trace the exact query sent to the source and the raw response received, which narrows the diagnosis to either a source-side or rendering-side issue.
- B2B order sheets: Buyers need to see SKU, unit price, pack size, and stock at a glance across hundreds of SKUs, then place one bulk order. A table with checkboxes or quantity inputs is far faster than navigating a shop grid.
- Internal inventory views: Warehouse staff or buyers need to see stock levels across all products, filtered by category and sorted by stock quantity, to identify what to reorder.
- Price lists: Export a current product catalog with prices to send to wholesale buyers or import into a quoting tool.
- Product lookup: Customer service staff need to quickly look up a product by SKU or name to answer customer queries.
Step 1: How Do I Select the WooCommerce Products Source?
Go to TableCrafter → Tables → Add New. In the Data Source dropdown, select WooCommerce: Products (distinct from WooCommerce: Orders). Name the table Product Catalog.
WooCommerce must be installed and active on the site for this data source option to appear in the dropdown. Once selected, TableCrafter populates the available field list automatically, covering product titles, SKUs, pricing columns, stock status, inventory levels, and category taxonomy, all drawn from your existing WooCommerce product data without requiring any external API credentials.
Give the table a clear, specific name at this stage. The name appears in any scheduled export email subject lines and in the TableCrafter admin table list, so a descriptive label like Wholesale Catalog or Internal Inventory View helps you identify the right table quickly as your site grows. You can rename the table at any time without breaking the shortcode, since the shortcode references the numeric table ID rather than the name.
This setting persists across table rebuilds. If you change the data source later, you may need to revisit this step to remap columns from the new source to the existing table configuration.
The data source connection is checked on each page load. If the source becomes unavailable - for example, if an Airtable API key is revoked or a Google Sheet is unpublished - TableCrafter displays a configurable error message rather than an empty table, so site visitors receive feedback rather than a blank page.
The shortcode accepts all column and filter settings defined in the table builder as defaults, but you can override individual parameters inline. For example, `[tablecrafter id="1" per_page="25"]` overrides the default rows-per-page setting for this specific embed without changing the saved table configuration. This lets you reuse one table definition across multiple pages with different display requirements.
Step 2: How Do I Understand Available Product Fields?
The WooCommerce Products adapter exposes these fields:
Core Product Fields
Every product in WooCommerce has a set of core identifying fields available for display. The product_id integer is the unique WordPress record identifier and is most useful as a hidden export column for ERP or purchasing system imports that require an ID reference. The product_name string is typically the first visible column in any catalog view and supports text search through TableCrafter's global search bar. The sku field is an empty string when the product has no SKU assigned, so you may want to configure the column to display N/A when blank rather than leaving an empty cell. Both product_type and status are enumerated values with a small fixed set of options, which makes them well suited for badge cell types or dropdown filters. For most catalog use cases you will want to filter to status = publish so draft and pending products do not appear to buyers.
product_id, Integer. WooCommerce product ID.product_name, String. The product title.sku, String. Stock keeping unit. Empty string if not set.product_type, Enum:simple,variable,grouped,external.status, Enum:publish,draft,pending,private.
Pricing Fields
WooCommerce stores up to three price values per product and understanding the difference between them matters when configuring catalog columns. The regular_price field holds the full non-sale price and is the right column for a List Price or MSRP display. The sale_price field is populated only when a sale is active; when no sale is running it returns an empty string rather than zero, so configure the column to display N/A or hide it when blank to avoid confusing buyers. The price field is the active selling price: it equals sale_price when a sale is running and regular_price otherwise. For a single-column price catalog, use price rather than trying to display both fields and letting the buyer work out which applies. To show both the list price and the active price together, include both regular_price and price as separate columns and label them clearly.
regular_price, Decimal. The regular (non-sale) price.sale_price, Decimal. The current sale price. Empty if not on sale.price, Decimal. The active price (sale price if on sale, otherwise regular price).
Inventory Fields
The most important inventory field to understand before configuring columns is manage_stock. When this boolean is false for a product, WooCommerce does not track stock levels for that item, and stock_quantity will return null rather than zero. Configure the stock_quantity column to display N/A or an empty string for null values to avoid showing a misleading zero to buyers. The stock_status field is always present regardless of whether stock tracking is enabled, and its three enum values make it ideal for a badge cell type: map instock to green, outofstock to red, and onbackorder to amber. Use low_stock_threshold alongside stock_quantity if you want to add a calculated column that flags products approaching reorder level, though this requires a custom column expression rather than a direct field mapping. The backorders_allowed boolean is useful in a staff-only catalog where buyers need to know whether they can place an order even when stock reads zero.
manage_stock, Boolean. Whether stock management is enabled for this product.stock_quantity, Integer. Current stock count. Null ifmanage_stockis false.stock_status, Enum:instock,outofstock,onbackorder.backorders_allowed, Boolean.low_stock_threshold, Integer.
Category and Taxonomy Fields
WooCommerce product taxonomy fields let you filter and organize the catalog by category or tag without exposing internal WordPress taxonomy IDs to buyers. The categories field returns an array of category name strings from the product_cat taxonomy. When you configure this column as a badge cell type, each category name in the array renders as a separate badge in the cell, so a product assigned to both Electronics and Accessories displays two badges side by side. This field also powers the multi-select category filter described in Step 4, with options sourced automatically from the same product_cat taxonomy so the filter list stays current as you add or remove categories in WooCommerce. The tags field works identically but draws from the product_tag taxonomy. Tags are generally more granular than categories and are better suited for keyword-style filtering, such as letting buyers narrow by material, finish, or compatibility, rather than for primary catalog navigation. Both fields support text search through the global table search bar.
categories, Array of category names. Rendered as a comma-separated list or badges.tags, Array of tag names.
Variation Fields (Variable Products)
For variable products, TableCrafter can either show a single parent row or expand to show one row per variation. Enable Expand variations in the table config to see individual variation SKUs, prices, and stock levels as separate rows.
The collapsed parent-row view is better suited for a high-level catalog where buyers browse your range without being overwhelmed by size and color permutations. Each collapsed row shows the price range across all active variations (for example, $10.00 to $25.00) and the total stock count summed across variations. The expanded view suits an internal inventory or purchasing table where staff need to know exactly how many units of a specific variant are in stock and whether that variant has its own distinct SKU. In expanded mode, each variation row carries its own sku, price, stock_quantity, and stock_status, all independently sortable and filterable. Category and tag fields in expanded variation rows reflect the parent product's taxonomy assignments, since WooCommerce does not assign taxonomy terms at the variation level.
Step 3: How Do I Configure Columns for a B2B Catalog?
A B2B product table typically needs:
This configuration interacts with any caching or CDN layer active on your WordPress installation. If you use WP Rocket, LiteSpeed Cache, or a CDN such as Cloudflare, flush the page cache after making this change to ensure the updated configuration is reflected in the cached HTML served to visitors. TableCrafter's server-side output is regenerated on the next uncached request.
product_name, Label: Product. Make it a link to the product page:/product/{slug}/or to the WooCommerce admin product edit page if this table is internal-only.sku, Label: SKU. Enable search on this column so buyers can look up by SKU.categories, Label: Category. Display Type: Badges. Set badge colour to a neutral tone.regular_price, Label: List Price. Format: Currency.price, Label: Your Price. Format: Currency. (For a single price-list table, just useregular_price.)stock_quantity, Label: In Stock. Show blank or N/A whenmanage_stockis false.stock_status, Label: Availability. Display Type: Badge. Mapinstockto green,outofstockto red,onbackorderto amber.
Step 4: How Do I Add Category and Stock Filters?
Open the Filters tab. Add a category filter:
- Source Field:
categories - Filter Type: Multi-Select
- Label: Category
- Options Source: Auto (reads from
product_cattaxonomy)
Add a stock status filter:
TableCrafter validates this configuration on save. If validation fails, the admin panel displays a specific error message identifying which field caused the problem. Correct the field value and save again without needing to restart the setup process.
After completing this step, verify the result by viewing the page as a logged-out visitor in an incognito window. This confirms the table behaves correctly for public visitors rather than reflecting admin-level permissions that may hide configuration issues during initial setup. Check both the rendered output and the browser console for any JavaScript errors.
- Source Field:
stock_status - Filter Type: Dropdown
- Label: Availability
- Default Value:
instock(pre-filter to in-stock items; buyers can clear this to see out-of-stock) - Options: In Stock (
instock), Out of Stock (outofstock), On Backorder (onbackorder)
Step 5: How Do I Enable Export?
In the Toolbar tab, enable Export to CSV. For a B2B catalog, this is one of the highest-value features, buyers often want to take the price list into their own purchasing or ERP system. The export respects the current filter state, so a buyer can filter to a specific category and export just that subset.
If you want to include fields in the export that are not visible in the table (for example, the product ID for ERP import), add those fields as Hidden Export Columns in the column settings. They will not appear in the rendered table but will be included in the CSV.
The column mapping you define here is stored as a JSON configuration in the WordPress database. You can export this configuration using the TableCrafter export tool and import it to another table or another site. This is useful when replicating a table layout across multiple pages or when migrating a table to a staging environment for testing before going live.
Step 6: How Do I Configure Access?
Decide who can see the catalog table and choose the minimum WordPress role required for access. TableCrafter enforces this restriction at two points: at render time, where the shortcode outputs nothing to users who lack the required role, and at the AJAX layer, where sort, filter, and paginate requests are rejected for unauthorized users. An unauthorized visitor who discovers the page URL will see a blank page rather than a table, and cannot retrieve the underlying product data through direct API requests. For a B2B catalog restricted to the Customer role, new buyers will not see the table until an administrator assigns them that role after account approval, which gives you a natural onboarding gate for wholesale access without any custom code.
Decide who can see the catalog table:
This step is required before the table can render data. Skipping it or entering incorrect values will result in a connection error when the table first loads. Double-check the value by pasting it directly into the field rather than typing it manually to avoid whitespace or encoding issues.
TableCrafter re-fetches this data on each page load by default. If your data source updates infrequently and your site has significant traffic, enable the built-in caching option in the table's Performance tab. This stores the fetched data for a configurable number of minutes and serves it from WordPress transients, reducing API calls to the source and improving page load time for visitors.
- Public catalog: Set Minimum role to view to None (public). Any visitor can see the table. Appropriate for published price lists.
- Logged-in buyers only: Set to Customer or a custom wholesale role.
- Internal staff only: Set to Shop Manager or Administrator.
Step 7: How Do I Place the Shortcode?
[tablecrafter id="6" filter="true" search="true" export="true"]
For a B2B order sheet where buyers need to request quantities, you can embed this table on a page alongside a Gravity Forms order form, using the product name or SKU as a lookup reference. The table gives buyers the product data they need to fill in the order form.
The shortcode supports inline attribute overrides that let you reuse one table configuration across different contexts without creating duplicate tables. For example, [tablecrafter id="6" per_page="50"] increases the row count on a full-width catalog page, while [tablecrafter id="6" per_page="10" filter="false"] produces a compact summary embed. The export="true" attribute shown above activates the CSV download button only for this specific embed, useful when you want export on the main catalog page but not on a sidebar widget. The show_pagination attribute controls whether pagination controls render at all, so you can suppress them on very small embedded previews. All column configuration, badge maps, and filter definitions come from the saved table settings and apply to every embed of the same table ID.
The configuration you set here applies to every visitor who loads a page containing this table, regardless of whether they are logged in. Role-specific overrides for columns and rows are a separate layer and do not replace these global display settings. Apply global settings first, then add role restrictions as needed for tables that serve multiple user types.
stock_quantity sort control (ascending) so buyers can sort from lowest to highest stock and immediately see what needs reordering. Combine with the in-stock filter turned off to show all products including out-of-stock. Export to CSV for the reorder report.
How Does Handling Variable Products Work?
Variable products (e.g., a t-shirt available in multiple sizes) have a parent product row and child variation rows. TableCrafter handles these in two modes:
- Collapsed (default): One row per parent product.
priceshows the price range ($10.00 – $25.00).stock_quantityshows total stock across all variations. Good for a high-level catalog view. - Expanded: One row per variation. Each variation's SKU, price, and stock is shown separately. Good for an inventory table where you need to track individual variants.
Toggle between modes in the table-level settings under Variable Products → Display Mode.
This step completes the connection between your data source and the TableCrafter table engine. Once saved, the plugin caches the connection credentials in the WordPress options table and uses them on every subsequent page load. If you update the source configuration later - for example, rotating an API key or changing a sheet URL - return to this step, enter the new value, and save again. The table updates immediately on next load without any shortcode changes.
How Does Keeping Data Fresh Work?
TableCrafter queries WooCommerce products in real time on each page load, so the table always reflects current prices and stock levels. If you use a caching plugin (WP Rocket, NitroPack), exclude the page containing the product table from page-level caching to ensure stock data is not served stale. TableCrafter's own response caching (configurable in Settings → Performance) defaults to 60 seconds for product data, which is a reasonable balance between freshness and database load.
For high-traffic sites, enabling TableCrafter's built-in transient caching is preferable to relying on full page caching for this use case. Transient caching stores the product query result in a WordPress transient for a configurable number of minutes, so the WooCommerce database query runs once and the cached result serves all subsequent requests within that window. Unlike page-level caching, transient caching still processes the shortcode on every request, which means role-based column visibility and per-user row filtering continue to work correctly. Set a shorter transient lifetime for catalogs where prices or stock levels change frequently during the day, and a longer lifetime for stable product lines where weekly updates are typical. You can also combine a moderate transient cache (5 to 10 minutes) with the auto-refresh Pro feature so the table updates on the browser side at a cadence you control, keeping stock information current without hitting the WooCommerce database on every page load.
If the result does not match expectations after saving, use the TableCrafter debug log (enable via TableCrafter Settings > Advanced > Debug Mode) to trace exactly which configuration value is being applied for the current request.
If this step produces unexpected output, check the source data directly in the connected system. TableCrafter passes data through without modification - if a cell displays an unexpected value, the source record contains that value. Use the TableCrafter debug log (Settings > Advanced > Debug Mode) to trace the exact query sent to the source and the raw response received, which narrows the diagnosis to either a source-side or rendering-side issue.
Frequently Asked Questions
How Does When to Use a Product Table Instead of the WooCommerce Shop Work?
The standard WooCommerce shop page is designed for retail browsing, images, prices, add to cart. A product table is better suited for:
What Is TableCrafter?
TableCrafter is a WordPress plugin that turns data from Gravity Forms, Google Sheets, Airtable, Notion, REST APIs, CSV files, and WooCommerce into interactive, sortable, filterable frontend tables. Embed any table on any WordPress page with the [tablecrafter] shortcode or the native Gutenberg block. No PHP or custom development required. The free version supports CSV, JSON, Google Sheets, and Excel. Pro adds Gravity Forms, Airtable, Notion, WooCommerce, REST APIs, inline cell editing, export to CSV and PDF, role-based column visibility, and auto-refresh.
Does this require PHP or developer skills?
No. TableCrafter is configured entirely through the WordPress admin interface. You choose your data source, map fields to columns, and set display preferences using point-and-click controls. Embedding uses the [tablecrafter] shortcode or the native Gutenberg block.
Is the free version sufficient or do I need Pro?
The free plugin on WordPress.org supports CSV, JSON, Google Sheets, and Excel sources with unlimited tables, rows, and columns. Pro adds Gravity Forms, Airtable, Notion, WooCommerce, REST API sources, inline cell editing, bulk row actions, export to CSV and PDF, role-based column visibility, and auto-refresh every N seconds.
Ready to try it?
TableCrafter is free on WordPress.org. Pro unlocks inline editing, role-based permissions, and advanced data sources.
The setting is stored in the WordPress options table under the table's configuration key. It does not modify the original data source and can be changed at any time without affecting the underlying records.
The shortcode accepts all column and filter settings defined in the table builder as defaults, but you can override individual parameters inline. For example, `[tablecrafter id="1" per_page="25"]` overrides the default rows-per-page setting for this specific embed without changing the saved table configuration. This lets you reuse one table definition across multiple pages with different display requirements.