All documentation
Reference
Technical FAQ
Implementation-level questions developers ask when building with Gravity Tables.
Different from the home FAQ (which answers “should I buy this?”), these are the questions developers ask while implementing.
Performance#
How many entries can a single table handle?#
Tested up to 50,000 entries on shared hosting with PHP 8.1 and 4GB RAM. Pagination is server-side; only the current page’s rows hit the client. Beyond ~50k, use the Top-N display setting (top_n_count / top_n_column, shipped in 4.2.54) to cap the rendered set, or split into per-period tables. Virtual scrolling for 10,000+ visible rows is on the 4.3 roadmap.
Does it cache anything?#
Yes, three layers:
- WordPress object cache (1-minute TTL on entry queries). Respects
wp_cache_flush(). - In-memory request cache (per-request). Same query within a request returns the cached result.
- Browser cache for static assets (
.js,.css,.svg) with the standard WordPress cache-busting query string.
Cache invalidation: edits + new entries flush the WP object cache for the affected table immediately. Manual flush via Tables → System → Flush cache or wp gt flush-cache.
Does auto-refresh hit the database every interval?#
Yes. Each refresh runs the configured query plus filter state. On heavily-trafficked pages with auto_refresh="true", dial the interval up to 60-300 seconds to spread load.
Compatibility#
Does it work with WPML / Polylang?#
Yes. Gravity Tables uses standard WordPress translation hooks (__(), esc_html__()) and a .po text domain. Field labels translate via Gravity Forms’ own translation flow.
Does it work with WooCommerce?#
The plugin works alongside WooCommerce, they don’t conflict. For WooCommerce-product-as-table use cases, see Posts Table Pro (different data source).
Does it work with Elementor / Gutenberg / Bricks / Beaver / Divi?#
Yes. The shortcode renders inside any page builder that supports WordPress shortcodes (all of them do). Native Gutenberg block shipped in v4.1.60, drop it from the inserter, pick a table from the sidebar dropdown, see the live preview right in the editor. Native Elementor widget shipped in v4.1.61 alongside. See the embed-and-customize sprint release post for the full story.
Does it work with caching plugins (WP Rocket, W3 Total Cache, LiteSpeed)?#
Yes. The plugin emits standard cache-control headers. For pages with auto_refresh="true", exclude them from full-page cache via the caching plugin’s exclude list, auto-refresh polls the database each cycle, which a fully-cached page bypasses.
Data model#
Where does the data live?#
In your WordPress database, in the standard Gravity Forms tables (wp_gf_entry, wp_gf_entry_meta). Gravity Tables doesn’t create its own entry tables.
It does create:
wp_gt_tables, table configurations (which form, which columns, settings)wp_gt_audit, audit log (only ifaudit_log="true"is used somewhere)wp_gt_export_audit, export log (only ifaudit_exports="true"is used)
These are created on plugin activation, removed on uninstall.
Can I query the entries directly via SQL?#
Yes, they live in wp_gf_entry and wp_gf_entry_meta, governed by Gravity Forms. The Gravity Tables config table (wp_gt_tables) is separate and just stores rendering preferences.
Are entries soft-deleted or hard-deleted?#
Bulk delete via Gravity Tables uses GFAPI::delete_entry(), which is the standard Gravity Forms delete (entries move to trash, then are purged on the next cron). Behavior is consistent with deleting from the GF admin entries screen.
Security#
Is the inline editing safe?#
Every edit goes through:
- Nonce verification (rotated per page load)
- Capability check (does this user have edit access for this column?)
- Per-row permission check (does this user own the row, if
filter_by_user="true"?) - Gravity Forms validation (does the new value pass the field’s rules?)
All four happen server-side. Client-side UI is for UX only, bypassing the UI doesn’t bypass the checks.
Is data sent to your servers?#
No. The plugin sends nothing to wpgravitytables.com or to TableCrafter. All data stays in your WordPress database. There are no analytics pings, no opt-out telemetry, no “anonymous usage statistics”.
The only exception: Freemius licence verification pings Freemius’s servers (their domain) periodically with your domain + licence key. That’s required for licence enforcement.
CSV / Excel injection?#
Cells starting with =, +, -, or @ get a ' auto-prefix on CSV export so Excel renders them as text instead of evaluating as formulas. Standard defense against CSV-injection attacks.
API#
Is there a REST API?#
Yes, /wp-json/gt/v1/. Endpoints:
GET /tables/{id}/entries?filter=...&page=..., paginated entries (server applies the same role + per-user gates)POST /tables/{id}/entries/{entry_id}/edit, inline edit (requires nonce + capability)POST /tables/{id}/bulk, bulk actionPOST /tables/{id}/export, start an export jobGET /audit?table_id=..., audit log entries (admin-only)
All endpoints require WordPress authentication (cookies or application passwords).
Can I extend the bulk actions?#
Yes, see PHP hooks → bulk action registration.
Can I subscribe to inline edits from JavaScript?#
Yes, see JavaScript events.
Common gotchas#
My table renders but is empty#
Most likely cause: an active filter narrowed the results to zero. Check filter_by_user="true" (does the current user have any entries?) or hard-coded filter parameters. Append ?gt_debug=1 to see the query the plugin actually ran.
My export is missing rows#
Exports respect active filters. If you have filter_by_user="true" on the table, the export will only include the current user’s rows (which is usually the intended behavior). To export all rows regardless of user filter, use the admin entries-export from Gravity Forms directly.
The “Add New Entry” button isn’t showing#
Three layers gate it:
allow_add="true"set in the shortcode- Current user has the
gravityforms_create_entriescapability - Current user has any custom capability set in
add_permissions
All three must be true. Use ?gt_debug=1 to see which check failed.
Related#
- Home FAQ, evaluation questions
- Troubleshooting, diagnosing specific errors
- Hooks, extending behavior