How to Create a Filterable Data Table in WordPress

The fastest way to add a filterable data table in WordPress, one your visitors can search, sort, and drill into, is to collect your data with Gravity Forms and surface it with TableCrafter. No custom development, no shortcode soup. Here is exactly how to do it. 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. Airtable has over 450,000 organization customers worldwide (Airtable, 2024).
What "filterable data table" actually means in WordPress?
A filterable table lets visitors narrow rows without leaving the page: typing into a search bar, selecting a status from a dropdown, or setting a date range. Visible rows update after each filter change, either client-side in the browser or via a server-side query, depending on the table's processing mode.
WordPress does not ship this natively. Page builders like Elementor display static HTML tables but offer no filtering. Most table plugins expect a CSV paste or manual data entry inside their own editor. If your data lives in Gravity Forms entries, duplicating it into a separate plugin means it goes stale the moment a new entry is submitted.
TableCrafter takes a different path: it reads directly from your Gravity Forms entries and renders a live, interactive table. Filters, search, and pagination all run against the real entry data. No syncing. No exports. No duplication.
Technically, TableCrafter filters at two levels. For smaller data sets, logic runs client-side in JavaScript, AND-combining a global search term with all active per-column filters simultaneously. For larger data sets with server-side processing enabled, each filter change triggers an AJAX request returning only matching rows for the current page. The same AND semantics apply at both levels: a row must pass every active filter to remain visible.
What Are the Requirements before you start?
- WordPress 6.0 or higher
- Gravity Forms 2.5 or higher (the commercial form plugin)
- PHP 7.4 or higher
- TableCrafter installed (free from wordpress.org/plugins/tablecrafter-wp-data-tables/)
TableCrafter works exclusively with Gravity Forms entries. It does not import CSV files, connect to Google Sheets, or read from external APIs. If your data lives in Gravity Forms, you are in the right place.
Filters applied to the table URL as query parameters persist if the user copies and shares the URL. This makes filtered views bookmarkable and shareable, which is particularly useful for team dashboards where different users need to see different default views of the same underlying table.
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.
How Does Step 1, Install TableCrafter Work?
Go to Plugins > Add New in your WordPress admin, search for gravity-tables, and install the free plugin. Activate it. You will see a new TableCrafter menu item appear in the left sidebar.
The free version includes all the filtering features covered in this guide. Pro adds inline editing and bulk operations, which are covered at the end.
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 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.
How Does Step 2, Create a table in the admin builder Work?
Navigate to TableCrafter > Tables > Add New. The table builder opens in a tabbed interface.
- Form: Select the Gravity Forms form whose entries you want to display. TableCrafter reads all submitted entries for that form.
- Columns: Drag the fields you want to show as columns. Each field from your form appears in the left panel, drag it into the column list on the right. Reorder by dragging. Remove a column by clicking the trash icon.
- Filters: This is the tab where filtering is configured. It is covered in detail below.
- Display: Set the default number of rows per page, enable or disable the global search bar, and choose a default sort column.
- Permissions: Control which WordPress user roles can view the table. Leave empty for public access.
Save the table. TableCrafter assigns it a numeric ID, visible in the table list and the URL of the edit screen. If this is your first table, the ID is 1.
How Does Step 3, Embed the table with a shortcode Work?
Open any page or post and add the shortcode:
[tablecrafter id="1"]
Replace 1 with your actual table config ID. Publish the page and visit it, you will see the table with your Gravity Forms entries, a search bar at the top, and sortable column headers. The filtering controls you configured in the builder appear above the table.
You can embed the same table on multiple pages using the same shortcode. Each instance is independent, visitors filtering on one page do not affect another.
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 Step 4, Configure filtering options Work?
This is the core of making a table visitors can actually use. TableCrafter offers several filter types, each suited to different field types. All of these are available on the free plan.
Global search bar Free
Enabled by default. A single text input renders above the table and applies a case-insensitive substring match across every visible column simultaneously. A row remains visible only when at least one cell contains the typed term; rows where no cell matches are hidden. The search is debounced at approximately 300 milliseconds, meaning the filter waits briefly after each keystroke before executing, which prevents a new query on every character entered. The debounce is especially important for server-side-processed tables where each query triggers an AJAX round-trip.
The global search bar AND-combines with every other active filter on the table. If a visitor selects "Status = Open" from a dropdown filter and also types a name in the search bar, only rows that satisfy both conditions are shown. This AND logic is enforced by the combined filter service, which evaluates per-column filters first (as typically more selective) before checking the global term against all cells.
When URL pre-filtering is enabled, active filter state is reflected in the URL via gt_col_-prefixed parameters, making filtered views bookmarkable and shareable. When localStorage persistence is enabled, the browser stores the search term under gt-filters-{table_id} and restores it on the next visit; URL-supplied values take precedence. Toggle off "Show search bar" in the Display tab to disable it.
Per-column dropdown filters Free
For columns that contain a limited set of values, status fields, categories, dropdown choices from your Gravity Forms form, you can add a dropdown filter. In the Filters tab, click Add Filter, select the column, and choose type "Dropdown". TableCrafter automatically populates the filter options from the distinct values present in your entries.
This works well for fields like: project status (Open, In Progress, Done), department, product category, or driver name. Visitors pick one value from the dropdown and the table immediately narrows to matching rows.
Multi-select filters Free
When visitors need to filter by more than one value at once, such as showing entries from three of five locations simultaneously, add a Multi-Select filter on that column. In the Filters tab of the table builder, click Add Filter, select the column, and choose type "Multi-Select". TableCrafter scans the current cached row set to collect distinct values, splitting comma-separated cell contents to recover individual values from multi-value fields. Each distinct value appears as a selectable option in the filter control, ordered alphabetically. The distinct value list reflects actual data, so values with zero matching rows are excluded automatically.
The filter applies OR logic within a single multi-select control: a row is shown if its cell contains any one of the selected values. Across separate filter controls on the same table, the logic switches to AND: a row must pass every active filter simultaneously to remain visible. This is consistent behavior across all filter types in TableCrafter.
When URL pre-filtering is enabled, the selected values are encoded as gt_col_{column_id} query parameters so a pre-filtered URL can be shared directly. If localStorage persistence is enabled in the Display tab, the browser stores the selection under gt-filters-{table_id} and restores it on the next visit, with URL parameters taking precedence over locally stored state.
Date range filter Free
For any column mapped to a date field, add a "Date Range" filter type in the Filters tab. Two date picker inputs labeled "From" and "To" appear above the table. Both bounds are optional: From-only shows entries on or after that date, To-only shows entries on or before it, and both together shows the inclusive range. The filter compares at the calendar-day level, expanded to the full day: a cell at 23:59:59 on the To date is included, and 00:00:00 on the From date is also included.
The filter service tries the column's configured display format first, then a fallback chain covering ISO 8601, MM/DD/YYYY, DD/MM/YYYY, YYYY/MM/DD, and common variants, then PHP's strtotime() for RFC and ISO strings with timezone offsets. Date cells from Airtable (ISO 8601) and Gravity Forms (the format set in the field settings) both parse correctly without manual per-column configuration.
The date range filter AND-combines with all other active filters on the table: a row must fall within the date range and pass every other active condition simultaneously. Date filter state is reflected in URL parameters when URL pre-filtering is enabled, making date-bounded filtered views bookmarkable. This is particularly useful for load trackers and order management tables where teams routinely share date-scoped views.
Text search per column Free
If the global search bar is too broad for your use case, add a per-column text filter. In the Filters tab of the table builder, click Add Filter, select the column, and choose filter type "Text". TableCrafter renders a small text input directly beneath that column's header cell in a dedicated filter row, output as a second <tr> element with class gt-column-filters inside the table header group. Visitors type into the input and only that column is searched, leaving all other columns completely unaffected. The filter applies a case-insensitive substring match, so typing "acm" matches cells containing "Acme", "ACME Inc.", and "subacme" without requiring an exact string. The input field's name attribute is gt_col_{column_id}, which corresponds directly to the URL parameter format used for pre-filtering.
Column filter state is reflected in the page URL as ?gt_col_{column_id}=value when URL filtering is enabled. A visitor filtering the Company column to "Acme" can copy the URL and send a pre-filtered view directly. When localStorage persistence is enabled, the browser stores all active values under gt-filters-{table_id} and restores them on the next page load; URL-supplied values take precedence over stored ones. Multiple per-column text filters AND-combine with each other and with the global search bar.
Advanced filter panel
Combining multiple filters is supported out of the box. If a visitor selects "Status = Open" from a dropdown and also types a name in the search bar, the table applies both filters together, showing only rows that match all active conditions. Filters are AND-combined by default.
Live Search
Instant cross-column text search. Updates as the visitor types with debounce to avoid excess queries.
Dropdown Filter
Auto-populated from real entry values. Ideal for status fields, categories, and any enumerated column.
Multi-Select
Pick several filter values at once. Rows matching any selected value are shown.
Date Range
Two date pickers scope entries to a time window. Works with any Gravity Forms date field.
How Does Step 5, Enable server-side pagination for large datasets Work?
If your form has hundreds or thousands of entries, loading all of them into the browser at once creates a slow, heavy page. TableCrafter handles this with server-side pagination. Instead of sending all rows to the browser and filtering there, each page request fetches only the rows for the current page, and applies all active filters at the database level.
To enable it, go to the Display tab and turn on "Server-side processing". Then set your rows-per-page default (25, 50, 100 are common choices). When a visitor applies a filter, TableCrafter runs a query against the Gravity Forms entries table with a WHERE clause for that filter value, returning only matching rows for the current page. The total matching count appears in the pagination controls.
For tables under a few hundred rows, client-side filtering (the default) is faster because it avoids a round-trip for each filter change. Switch to server-side processing once your entry count makes page load noticeably slow.
How Does Step 6, Add a column visibility picker Work?
Free The column visibility picker lets visitors show or hide individual columns without affecting anyone else's view. It appears as a "Columns" button above the table. Visitors click it to get a checklist of all columns and toggle any off. This is particularly useful for wide tables, load trackers with 10+ columns, or employee directories where some viewers want fewer fields.
Enable it in the Display tab by toggling "Show column picker". The visitor's selection is stored in their browser session, so it persists across page reloads until they clear it.
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.
How Does Real-world examples Work?
Here are a few concrete use cases where filterable tables built with TableCrafter replace custom development work:
Load tracker for a trucking company
Gravity Forms captures each load: driver name, origin city, destination city, departure date, expected delivery date, current status (Pending, In Transit, Delivered), and cargo weight in pounds. TableCrafter surfaces the submitted entries as a live, sortable table with three filter controls configured in the Filters tab: a dropdown filter on the driver field populated automatically from distinct driver names in the entry data, a dropdown filter on the status field showing the three status values, and a date range filter on the departure date using From and To date pickers.
Dispatchers arriving at the page select the current week in the From and To inputs, then pick a driver from the dropdown. Both filters AND-combine, so only loads matching the selected driver and date range appear. For smaller fleets (under a few hundred entries), filtering is instantaneous with the full row set loaded client-side. For larger operations, enabling server-side processing in the Display tab means each filter change fetches only matching rows via AJAX, keeping the page responsive as the entry count grows.
With URL pre-filtering enabled, a dispatcher can share a pre-filtered view: a URL ending in ?gt_col_driver=Johnson>_col_status=In+Transit opens with both filters applied on arrival. With the Pro license, dispatchers can also click a status cell inline to update it without leaving the table.
Employee directory
HR uses a Gravity Forms entry per employee. TableCrafter renders the directory with a department dropdown, a location dropdown, and a live search on name and title. No custom code. No database table to maintain outside WordPress.
Order management view
A B2B sales team tracks wholesale orders in Gravity Forms with fields for order number, customer account, account manager, product line, order date, and status (New, Processing, Shipped, Invoiced, Closed). TableCrafter renders submitted entries as a filterable table with four filter controls: a dropdown on status, a dropdown on account manager, a date range on order date, and a per-column text input on order number. The order number input lets team members jump to a specific order without affecting any other column. All four filters AND-combine.
The column picker is enabled so each team member can hide columns irrelevant to their role; a warehouse coordinator might hide invoice fields, an account manager might hide weight and dimensions. Column visibility is stored via localStorage and persists across page reloads. With the Pro license, account managers can update order status inline by clicking the cell, and bulk fill lets them update status across multiple selected rows at once without leaving the table.
How Does Pro features for interactive tables Work?
The free plugin handles all the filtering and display described above. The Pro license at tablecrafter.com adds editing and management capabilities on top of that foundation:
- Pro Inline editing: Click any cell to edit it and save back to the Gravity Forms entry without leaving the table.
- Pro Bulk fill: Select multiple rows and set a field value across all of them at once, useful for batch status updates.
- Pro Entry duplicate: Clone an existing entry as a starting point for a new one.
- Pro Column role visibility: Show certain columns only to admins and hide them from standard users, same table, different view based on WordPress role.
- Pro Email alerts: Trigger a notification email when a cell value is changed inline.
- Pro Data bars: Render numeric columns as visual progress bars so high/low values are instantly scannable.
What Is Quick reference: shortcode and filter setup?
Once your table is built and saved, embedding it is a single line:
[tablecrafter id="1"]
For a table where you want the search bar disabled and only the per-column filters active, configure that in the admin builder, the shortcode itself does not need extra attributes for standard configurations. The builder is where filter types, column order, pagination settings, and permissions all live.
Find your table config ID under TableCrafter > Tables. It appears in the ID column of the table list, and in the URL when you open the edit screen: /wp-admin/admin.php?page=gravity-tables&action=edit&id=1.
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.
Frequently Asked Questions
What does "filterable data table" actually mean in WordPress?
A filterable table lets visitors narrow down rows without leaving the page. That might mean typing a name into a search bar, picking a status from a dropdown, selecting a date range, or combining several of those filters at once. Every time a filter changes, the visible rows update, either instantly in the browser or via a fast server-side query.
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.
Try TableCrafter Free
Install from WordPress.org and have a filterable, searchable table on your site in under ten minutes. The free version includes live search, dropdown filters, date ranges, multi-select, column picker, CSV export, and pagination, no license required.