The Problem
FluentCart is built for fixed-price products. That's great for most stores, but some of us need the customer to choose their own price:
- Donation platforms (like ours)
- Tip jars for content creators
- Charity fundraisers
- “Name your price” digital products
Before Ghost Products, the workaround was ugly: create a dummy product in the catalog, set a placeholder price, then override it at checkout with hooks and hidden form fields. It worked, but it meant maintaining invisible products, syncing variation IDs between environments, and bridging request data through multiple FluentCart hooks. Every new donation type meant another variation, another constant, another thing that could drift.
What Ghost Products Change
Ghost Products (docs) let you define items entirely in code. No catalog entry. No variation. No admin UI to keep in sync. You hook into fluent_cart/cart/validate_custom_item, and FluentCart hands you the item — you set the price, title, and metadata, and it processes the order normally.
The entire server-side implementation is one PHP class.
The Architecture
Here's the flow:
→ FluentCart fires validation hook
→ Your code sets the price → FluentCart charges via Stripe
→ Done
Three pieces to build:
- PHP handler — validates the amount and constructs the line item
- Frontend JS — builds the checkout URL with the user's chosen amount
- Hook registration — wires it up in WordPress
Step 1: The Ghost Product Handler (PHP)
This is the core. When FluentCart sees is_custom=true in the checkout request, it fires the fluent_cart/cart/validate_custom_item filter. Your handler receives the item, sets the price from the request params, and returns it.
Here's a simplified, generic version:
Key points:
- Prices are in cents. FluentCart works in cents internally —
$25.00→2500. is_custom => truetells FluentCart this is a ghost item.payment_typecontrols whether FluentCart creates a one-time charge or a subscription.other_infois a flexible metadata bag — FluentCart stores it as JSON on the order item.repeat_intervalinother_infocontrols subscription frequency (monthlyoryearly).
Step 2: The Frontend (JavaScript)
FluentCart exposes an instant_checkout URL that skips the cart page and goes straight to payment. Your frontend just needs to build this URL with the right parameters:
That's it. FluentCart intercepts the URL, fires your validation hook, and renders the Stripe checkout with the custom amount. Your amount input can be anything — a text field, a slider, preset buttons.
Step 3: Register the Hook
In your plugin's bootstrap (or functions.php if you're keeping it simple):
What About Subscription Renewals?
This was our biggest concern. If the item doesn't exist in the catalog, will renewals break?
They don't. FluentCart stores the full order item (including price) when the subscription is created. Stripe handles recurring billing from the stored amount. The ghost product hooks only fire on initial checkout — renewals replay the stored data. We've verified this in production with monthly and annual subscriptions.
What We Deleted
After migrating to Ghost Products, we removed ~1,400 lines of code and 4 entire PHP classes that existed solely to bridge custom amounts into FluentCart's catalog-based checkout. No more environment-specific product IDs, no more variation constants, no more cart-fill services.
Tips If You Build This
- Set a floor. Always validate a minimum amount server-side — don't rely on frontend validation alone.
- Use
other_infofor metadata. Need to track a donor's name, a campaign ID, or any custom context? Put it inother_info. It persists on the order item and is available in all post-purchase hooks. - Start with one-time payments. Get that working first, then add subscription support. The subscription plumbing is straightforward once the basics are solid.
- Log everything during development. Ghost products are invisible by design — there's no admin UI to inspect. Good logging in your validation handler saves hours of debugging.
Is Pay-What-You-Want Checkout on FluentCart's Roadmap?
As of February 2026, it's not. But honestly, with Ghost Products available, a dedicated pay-what-you-want checkout feature isn't necessary. The hooks give you full control over pricing, and you can build exactly the UI your use case needs — whether that's a donation form, a tip jar, or a “name your price” product page.
PIFster is a community-driven charitable giving platform where donors vote on which charity receives the community's pooled donations each month. We run on WordPress with magic link authentication, gift memberships for donor acquisition, and a gamified referral engine. If you're building something similar, we'd love to hear about it.

