Gravity Forms Product Options

Gravity Forms Product Options attaches a Gravity Form to a WooCommerce product so customers configure it on the product page: options, personalisation text, measurements, uploaded artwork. Pricing fields in the form change the price as they are filled in, and every choice travels through the cart, the order, the emails and My Account. Each ordered item gets one Gravity Forms entry that carries the order and the full amount paid.

Overview

↑ Back to top

You build the form in Gravity Forms, using its Product, Option, Quantity and Shipping fields wherever a choice should change the price, and any other field type for what the customer needs to tell you. You attach that form to a product from the product’s own Gravity Forms tab. From then on the product page shows the form above the add-to-cart button, a price breakdown that follows the customer’s choices, and WooCommerce’s own button adds the configured item to the cart.

Store-wide defaults decide how every configured product behaves; any product can override any of them. Validation is Gravity Forms’ own, so required fields, conditional logic and field rules behave exactly as they do in a standalone form.

Requirements

↑ Back to top
  • WordPress 6.0 or newer
  • WooCommerce 9.0 or newer
  • Gravity Forms 2.6 or newer, any licence tier (tested with 2.9)
  • PHP 7.4 or newer

Gravity Forms is required: the plugin renders, validates and stores forms through Gravity Forms’ own API and does nothing when it is not active.

Installation

↑ Back to top

After activating, open WooCommerce > Settings > Products > Gravity Forms to review the store-wide defaults, then attach a form to a product from the Gravity Forms tab of its product data panel.

Usage

↑ Back to top

Building a form for a product

↑ Back to top

Any Gravity Form works. Three points make the difference between a form that collects information and one that prices the product:

  • Product fields add an amount. A Single Product field with a base price of 5 adds 5 to the product price when it is present. A Drop Down or Radio Buttons product field lets the customer choose between priced variants.
  • Option fields attach to a product field and add or remove an amount per choice. A negative price on a choice is how a discount is expressed: “Bulk discount, -3” takes 3 off.
  • Quantity fields multiply their product field. A Total field is optional: while the price breakdown is on, the plugin hides it on the product page, since it would only show what the options add next to a total that includes the product.

Everything else, text, choices, dates, addresses, uploads, is collected and shown with the order without affecting the price. Conditional logic, multi-page forms and required fields all work as usual.

Attaching a form to a product

↑ Back to top

Open the product and, in the product data panel, choose the Gravity Forms tab.

Gravity Form lists your active forms. Choosing one attaches it; choosing “No form” detaches it and the product sells as before. Variable products carry the form on the parent; every variation shows it.

Below the selector, every store default appears with a checkbox. Ticking one lets you override that setting for this product alone; leaving it unticked keeps the product on the store default, and the default’s current value is shown beside it. A product therefore never silently drifts from the store: what it does differently is exactly what is ticked.

Store defaults

↑ Back to top

WooCommerce > Settings > Products > Gravity Forms holds the defaults, organised into groups. The same groups appear on the product tab.

Master switch

Enable product options turns the whole plugin on or off. It is off when the extension is first installed, so nothing changes on your store until you switch it on. While off, products behave as if no form were attached: nothing renders, nothing is priced, nothing is validated. Product configuration is kept.

Price display

  • Show the price breakdown adds three rows under the form: base price, what the options add, and the total. They update as the customer makes choices.
  • Breakdown position puts the rows after the form or before it.
  • Base price label, Options label and Total label are the words on those rows.
  • Hide the WooCommerce price removes the product’s own price display, for products whose price only makes sense once configured. Text before the price and Text after the price frame it instead, for example “From” and “depending on options”.
  • Confirm the price with the server asks your store for the exact figure after each change. The browser estimate is instant but knows nothing about tax display, currency switchers or pricing filters; the server does. Leave it on unless you are chasing a performance problem.

Form display

Show the form title and Show the form description print the form’s own title and description above it. Off by default, since the product already has a name.

Cart

  • Let customers edit their choices from the cart adds an “Edit your choices” link under the item on the classic cart page. It reopens the product with their answers filled in. Editing replaces the original line decides whether saving replaces that line or adds a second one.
  • Reset the form after adding to cart clears the form when the product page reloads after an add, for stores where customers configure several items in a row.
  • Quantity from a form field lets a Number or Quantity field decide how many. Sets the cart quantity makes the line quantity follow the field. Reduces stock by that amount keeps the line at the quantity the customer entered but reduces stock by the field’s value per unit, for products sold by the piece but stocked by the metre or the sheet. Quantity field names the field.
  • Weight field, Length field, Width field and Height field map form fields to the parcel WooCommerce rates shipping on. A made-to-measure product is shipped at its configured size rather than the product’s default, so shipping rates come out right. The mapped field can be a Number field with a calculation, so a weight derived from the customer’s measurements (width × height × thickness × density) works without the customer ever typing a weight.
  • Image field uses an uploaded image from a File Upload field as the item’s thumbnail in the cart.

Field ids belong to one form, so field mappings are usually set on the product rather than store-wide. The store-wide pickers offer only fields present in every form.

Order summary

These settings decide which of the customer’s answers appear under the product in the cart, the checkout, the order, the emails and My Account.

  • Visible fields with a value is the default: every field the customer could see and filled in. Hidden fields, admin-only fields, layout fields and the total stay out.
  • Every field with a value, hidden ones included adds hidden and admin-only fields, for stores that use them to carry data staff need to see.
  • Only the fields selected below limits the summary to a chosen list.
  • A template using merge tags replaces the list with one line you write, using Gravity Forms merge tags such as {Engraving:1} or {all_fields}.

Pricing values read the way a customer expects: “Ribbon +$2.00”, “Bulk discount -$3.00”, “Gift box: +$5.00”. Uploaded files show by name and open in a new tab.

Entries

  • Create a Gravity Forms entry per ordered item is on by default. Each item that carried a form gets one entry.
  • Create the entry when the order is placed is the usual choice. When the item is added to the cart creates it earlier, which suits stores that use Gravity Forms add-ons to react to configurations; the entry is then linked to the order at checkout. With that choice, Keep entries for items removed from the cart decides whether abandoning a configured item leaves its entry behind.
  • Send the form notifications sends the form’s own notifications once per item, and Only when the order reaches decides which order statuses trigger them. The default, Processing and Completed, means a failed or cancelled payment never sends a “thanks for your order” from the form.

Every entry carries the order number, the order item, the product, the base price and the full line total paid, and its payment status follows the order: Paid, Pending, Failed, Cancelled or Refunded.

Structured data

A configurable product has no single price, and search engines quoting the base price as the price mislead shoppers. Structured data price can publish a range instead: Publish a price range adds low and high prices, Publish a price range and drop the single price removes the single price too. Lowest price and Highest price set the bounds; left empty, the product’s own price is used for both.

Finding the products that carry a form

↑ Back to top

There is no separate list inside the extension. Products in WooCommerce gains a dropdown next to the other filters: choose With a Gravity Form, Without a Gravity Form, or a specific form, then Filter. Attaching, swapping or detaching a form happens on each product’s own Gravity Forms tab, which also links straight to the form in Gravity Forms.

Filtering orders by product options

↑ Back to top

There is no separate list of orders inside the extension: the WooCommerce orders list already has the columns, the search, the bulk actions and the status views. Instead, the list gains a dropdown next to the other filters. Choose With product options to keep only the orders that carried a form, or pick a specific form to narrow down further. On each order, every configured item shows its answers and a link to the Gravity Forms entry it created.

Placing a product’s form on another page

↑ Back to top

The shortcode [gfpo_product id="123"] prints the add-to-cart form of product 123, options included, wherever it is used. [gfpo_product sku="MUG-01"] finds the product by SKU. The product must be purchasable.

Multi-page forms

↑ Back to top

Page navigation works as it does in Gravity Forms. Each page is validated as the customer moves forward, and the item is added to the cart only when the last page is submitted and valid. Each page change is a page load, as with any non-AJAX Gravity Form; AJAX page changes are on the roadmap.

Variable products

↑ Back to top

Attach the form to the parent. The breakdown’s base price follows the variation the customer selects, and the form total is added to it.

Use cases

↑ Back to top

Personalised gifts

↑ Back to top

A Text field for the engraving, a Single Product field for a gift box at 5, an Option field for a ribbon at 2. Leave the defaults alone. The customer sees the price move as they tick options, and the order shows exactly what to engrave and what to pack.

Made-to-measure blinds

↑ Back to top

Number fields for width and height, a Calculation-based Product field for the price per square metre, and the same Number fields mapped to Width field and Height field so shipping is rated on the real parcel. Map a “Weight (kg)” Number field to Weight field when weight varies too.

Printed artwork with an upload

↑ Back to top

A File Upload field for the artwork, mapped to Image field so the cart shows the customer’s own image. Set Create the entry to when the item is added to the cart if a Gravity Forms add-on needs to see the upload before checkout.

Bulk pricing by the piece

↑ Back to top

A Quantity field mapped to Quantity from a form field as Sets the cart quantity, and an Option field with a negative-priced “Bulk discount” choice shown by conditional logic above a threshold.

Keeping the confirmation email honest

↑ Back to top

Turn on Send the form notifications and leave Only when the order reaches on Processing and Completed. The form’s confirmation goes out when the order is paid, and never when a card is declined.

FAQ

↑ Back to top

The form does not appear on the product page.

↑ Back to top

Check three things: the master switch is on, the form is active in Gravity Forms and not in the trash, and the product’s Gravity Forms tab has it selected. On a variable product the form belongs on the parent.

The price does not change when I tick an option.

↑ Back to top

Prices come from Gravity Forms’ pricing fields only. A Checkbox field is not an Option field: recreate the choice as an Option field attached to a Product field, with a price on each choice. The Total field is optional.

Can an option reduce the price?

↑ Back to top

Yes. Give the choice a negative price. The unit price never goes below zero.

Why is there no Edit link in my cart?

↑ Back to top

The link appears on the classic cart page. The Cart block renders item details as plain text, so the link cannot be shown there; customers can still remove the item and configure it again.

A customer changed their choices but the order shows the old ones.

↑ Back to top

Editing replaces the line only when Editing replaces the original line is on. With it off, saving adds a second line and the first stays.

Do hidden fields appear on the order?

↑ Back to top

Not by default. Switch Fields shown in cart and order to “Every field with a value, hidden ones included” if staff need them.

The entry shows a payment of 25 but the customer paid 50.

↑ Back to top

Entries record the full line total, quantity included, at the moment the order is placed; 50 for two items at 25 is correct. Refunds later change the payment status, not the amount.

Does it work with the Cart and Checkout blocks and HPOS?

↑ Back to top

Yes. Orders placed through the Checkout block get their entries and item details like any other, and the plugin declares compatibility with High-Performance Order Storage.

Does it work with WooCommerce Subscriptions?

↑ Back to top

Yes for the parent order and for renewals: each renewal order gets its own entries. Subscription switches are treated as new orders.

What happens if I change the form after customers added items?

↑ Back to top

Items in a cart carry a fingerprint of the form they were configured with. If the form’s fields changed since, checkout asks the customer to remove and re-add the item rather than placing an order whose choices no longer match the form.

What happens if I deactivate the plugin?

↑ Back to top

Nothing is deleted. Products keep their form and overrides, orders keep their item details, entries stay in Gravity Forms. Reactivating returns everything to where it was.

Developer documentation

↑ Back to top

Filters

↑ Back to top

gfpo_product_form_id
Filters the form id attached to a product. Receives the id (zero for none) and the product id the configuration lives on. Return a different id to attach a form programmatically, for example by category.

gfpo_product_config
Filters a product’s effective configuration after defaults and overrides are merged. Receives the configuration array and the product id.

gfpo_form_total
Filters the amount a form adds to the unit price. Receives the total (may be negative), the form array and the entry array.

gfpo_base_price
Filters the base price the form total is added to. Receives the base, the WC_Product and the form total.

add_filter( 'gfpo_form_total', function ( $total, $form, $lead ) {
	// A rush option adds a flat 10 regardless of quantity.
	if ( ! empty( $lead['12'] ) && 'Rush' === $lead['12'] ) {
		$total += 10;
	}
	return $total;
}, 10, 3 );

gfpo_summary_lines
Filters the lines shown under the product in the cart and on the order. Receives an array of rows (name, value, plain, id, type), the form, the entry and the configuration.

gfpo_form_output_hook
Filters the hook the form is printed on. Default woocommerce_before_add_to_cart_button.

gfpo_entry_payment_status
Filters the Gravity Forms payment status written for an order status. Receives the status string, the order status and the WC_Order.

Actions

↑ Back to top

gfpo_entry_created
Fires after an entry is created for a configured product, with the entry id, the form array, the product id and the WC_Order when known.

gfpo_settings_saved
Fires after the store defaults are saved, with the saved array.

Shortcode

↑ Back to top

[gfpo_product id="123"] or [gfpo_product sku="MUG-01"] prints the product’s add-to-cart form with the Gravity Form inside it.

REST routes

↑ Back to top

Namespace gravity-forms-product-options/v1. Every route requires manage_woocommerce.

MethodRoutePurpose
GET/settingsStore defaults
POST/settingsSave store defaults
GET/schemaSetting schema, labels, choices, active forms with their fields, order statuses

MCP tools (WordPress Abilities API)

↑ Back to top

Eight abilities are registered under gravity-forms-product-options, discoverable through wp_get_abilities(), each gated by manage_woocommerce: get-settings, list-forms, list-products, get-product-config, preview-summary, attach-form, set-product-override and set-default. List values may be passed as comma-separated strings and booleans as 1 or 0. The plugin registers abilities only; it does not run an MCP server.

Data storage

↑ Back to top
WhereKeyContents
Optiongfpo_settingsMaster switch, debug flag and every store default
Post meta_gfpo_form_idForm attached to a product
Post meta_gfpo_overridesOnly the settings the product overrides
Cart item_gfpo_form_id, _gfpo_lead, _gfpo_form_hash, _gfpo_total, _gfpo_entry_idForm, submitted values, form fingerprint, amount added, entry created at cart time
Order item meta_gfpo_form_id, _gfpo_lead (JSON), _gfpo_total, _gfpo_entry_id, _gfpo_notifiedHidden plumbing; the visible summary lines are ordinary item meta
Entry metagfpo_order_id, gfpo_order_item_id, gfpo_product_id, gfpo_base_price, gfpo_line_totalThe order link, registered with Gravity Forms so they appear in entry lists, exports and conditional logic

No custom table is created.

How the form and WooCommerce share one request

↑ Back to top

Gravity Forms is rendered without its own <form> element; its fields sit inside WooCommerce’s cart form, which is given the gform_{id} id Gravity Forms’ scripts look for. The add-to-cart button submits both at once. Gravity Forms 2.9 guards that form against submits it did not start, so a capture-phase listener lets the add-to-cart button through while leaving Gravity Forms’ own page navigation untouched. Validation runs through GFAPI::validate_form() inside woocommerce_add_to_cart_validation, and the entry data through GFFormsModel::create_lead().

Logging

↑ Back to top

With debug mode on, entry creation failures are written to WooCommerce > Status > Logs under the source gravity-forms-product-options.

Use of your personal data
We and our partners process your personal data (such as browsing data, IP Addresses, cookie information, and other unique identifiers) based on your consent and/or our legitimate interest to optimize our website, marketing activities, and your user experience.