Gravity Forms to WooCommerce in one click, plus the hooks for any integration after that
v4.1.30 shipped a built-in WooCommerce integration: map four GF fields onto product title / price / SKU / description, then click the cart row-action to create a draft WC product. v4.1.31 followed with the public entry-lifecycle hooks that make any other integration just as straightforward to build.
- Per-table field mapping: GF field → WC product title, regular price, SKU, description
- Cart row-action button on each entry; click to create the WC product as a draft
- WooCommerce-active conditional, the integration only loads when WC is detected
- New hooks: gravity_tables_entry_created and gravity_tables_entry_deleted
- Numeric column sort now sorts by value (1, 2, 10) not lexicographic (1, 10, 2) for number/currency/calculation fields
A pair of versions about the same thing seen from two angles. v4.1.30 ships a specific integration, Gravity Forms to WooCommerce, that closes a real use case for WP-and-WC stores. v4.1.31 ships the public action hooks that make any equivalent integration (Stripe, Square, FluentCRM, your own bespoke listing system) just as cleanly buildable.
Together they make the integration story explicit: here’s one we built; here’s how to build the rest.
v4.1.30, WooCommerce integration#
The use case has come up enough times to be worth shipping native: you collect product details through a Gravity Form (vendor application, product submission, inventory upload), and you want each approved entry to become a WooCommerce product without re-typing every field.
How it works#
Per-table, you map up to four Gravity Forms fields onto WooCommerce product attributes:
| WC product attribute | Gravity Form field example |
|---|---|
| Title | product_name |
| Regular price | price (currency or number) |
| SKU | sku |
| Description | description (paragraph, rich-text) |
The mapping lives in the table settings, one configuration per table, not per entry.
Once mapped, every row in the table gets a 🛒 row-action button. Click it, and a draft WooCommerce product is created using wc_get_product / WC_Product->save(). The product is saved as draft status by default, so it lands in your products list for review and adjustments before going live.
Why draft, not publish#
Going from “submitted via form” to “live in the store” without an admin pass is two steps too far. Form submitters might typo, mis-categorise, or not include images. A draft creation flow gives you a 30-second review window per product before you publish.
For sites that want one-click straight-to-publish, a gravity_tables_wc_product_status filter lets you override the default status, see the hooks doc for the snippet.
Activation conditional#
The whole integration is only loaded when WooCommerce is active. The module’s bootstrapping checks class_exists('WooCommerce') before doing anything else; sites without WC see no UI surface, no JS, no CSS, nothing. WC’s absence is invisible, no broken-button placeholders, no error notices.
What this replaces#
Two old patterns this closes:
- The “custom-CSV-export-then-WC-import” loop, export entries, hand-edit a CSV to match WC’s import schema, run WC’s importer. 30 minutes per import, fragile every time WC’s schema changes.
- Per-form Zapier integrations, $20/mo per integration, two services to keep alive, a webhook to debug the day it breaks.
The native flow is one click per entry, no recurring cost, and the data stays in your WordPress install end-to-end.
v4.1.31, Entry lifecycle hooks (and a numeric-sort fix)#
The WC integration didn’t need new hooks, it implements a row-action, which has its own pre-existing extension point. But the broader question is: what about every other “when an entry is created / deleted, do X” integration?
v4.1.31 ships two stable, public action hooks:
do_action('gravity_tables_entry_created', $entry_id, $form_id, $context);
do_action('gravity_tables_entry_deleted', $entry_id, $form_id, $context);
These fire after the entry is committed to the database, on every path that creates or deletes one, frontend Add Entry, CSV import, REST endpoint, bulk action, manual admin operation. The $context argument is a small array indicating the source: ['source' => 'frontend' | 'import' | 'rest' | 'bulk' | 'admin'].
Why these and not the existing GF hooks#
Gravity Forms ships its own gform_after_submission hook, but that fires only on form-frontend submissions. Entries created by other paths, CSV import, REST PUT, admin “Add Entry”, bulk re-creation, bypass it entirely.
If you’ve ever written code that “should fire whenever an entry exists” and discovered that bulk imports skip your hook, this is the fix. gravity_tables_entry_created fires regardless of how the entry got there.
Example: send new entries to FluentCRM#
add_action('gravity_tables_entry_created', function ($entry_id, $form_id, $context) {
if ($form_id !== 'leads') return;
$entry = GFAPI::get_entry($entry_id);
if (function_exists('FluentCrmApi')) {
FluentCrmApi('contacts')->createOrUpdate([
'email' => rgar($entry, 'email'),
'first_name' => rgar($entry, 'first_name'),
'tags' => ['new-lead', 'source:' . $context['source']],
]);
}
}, 10, 3);
10 lines, fires regardless of how the entry got there, includes the source as a tag so you can see in FluentCRM whether the lead came from the form, an import, or the REST API.
And the numeric-sort fix#
Same release, separate fix: numeric columns (number, currency, calculation field types) now sort by their numeric value instead of lexicographically. So a column of values 1, 2, 10, 100 sorts as 1, 2, 10, 100 instead of 1, 10, 100, 2.
Implementation note: a CAST(... AS DECIMAL) clause is added to the ORDER BY for number-typed fields, leaving text columns to sort lexicographically as before. Mixed-content columns (text mostly with stray numbers) are unaffected, they stay text-sort.
If you have a price-sorted product table that’s been silently wrong since launch, this is the fix.
Upgrade path#
Both features ship enabled by default. No configuration required.
- WooCommerce integration: only appears when WC is active. Map fields per-table from Tables → [Table Name] → Settings → WooCommerce.
- Lifecycle hooks: just
add_action('gravity_tables_entry_created', ...)in your child theme or a custom plugin. No registration step. - Numeric sort: applies automatically to number/currency/calculation field types. No setting, no migration. If a previously-sorted-wrong table now sorts correctly, that’s the fix.
Related#
- Hooks,
gravity_tables_entry_createdandgravity_tables_entry_deleteddocumented in full - Integrations, the WooCommerce card now reflects this native integration (was “Compatible”, now “Native”)
- Build a CRM lead dashboard, the FluentCRM example pattern from this post lives natively in the CRM guide
- Build a moderation queue, the lifecycle-hook pattern for status-machine workflows