Direct answer
Store one short plain-text notice on the product and render it once through WooCommerce's documented woocommerce_before_add_to_cart_form hook. Escape the final text, preserve the buy form, and render nothing when the product, notice, or page context is uncertain.
Product Notice for WooCommerce follows that boundary. Free adds one optional 240-character product notice. Pro adds bounded category and global fallbacks while keeping each product notice authoritative.
Use a notice for a visible buying detail
A product notice works best when a shopper should see one short fact before choosing a variation, quantity, or add-to-cart action.
Examples include:
Check the size chart before ordering.Sold as a pair.This item ships separately.Color may vary between batches.Measure the doorway before ordering.
The notice is not a second product description, a popup builder, or a checkout condition. It should help a shopper make a better decision without changing whether the product can be purchased.
A notice is not a legal compliance decision
A technical display feature cannot determine whether a message is legally required, sufficient, accurate, prominent enough, translated correctly, or valid in a particular jurisdiction.
The merchant remains responsible for the wording and for any legal, safety, allergy, age, warranty, shipping, tax, or regulatory obligations. The plugin can prove only that merchant-provided plain text was stored and rendered in its supported WooCommerce location.
Do not market a visible notice as proof of compliance. Do not infer a warning from product data. Do not generate legal language.
Use the native product-form location
WooCommerce's current hook reference lists woocommerce_before_add_to_cart_form in the product add-to-cart templates. The hook runs before the form instead of replacing it.
That creates a narrow ownership boundary:
- WooCommerce owns product state, variation selection, quantity, stock, and the add-to-cart form.
- The theme owns the native
woocommerce-infopresentation. - The notice plugin owns one escaped
role="note"element. - Other extensions continue to own pricing, validation, checkout, and legal workflows.
The plugin should never copy the add-to-cart template, inject a second button, disable the form, or change cart validation. Deactivation should remove only the notice.
Keep each product in control
Free stores two small product values: an enabled flag and one plain-text notice. The product notice is the most specific merchant decision and should always win.
Pro can resolve an empty product notice in this order:
- Use the product notice when it exists and is enabled.
- Otherwise use the first configured matching category notice.
- Otherwise use the global fallback.
- Use nothing when the product explicitly disables Pro fallback.
StoreFixKit sorts category rules by category ID and uses the lowest matching configured ID. That deterministic rule avoids a hidden "last saved wins" outcome when a product belongs to several categories.
Product-level opt-out is also important. A global message should not force itself onto an exceptional product merely because it shares a broad category.
Bound the fallback system
A small notice feature should not become a rule engine. The release boundary is:
- no more than 240 characters per notice;
- no HTML, links, shortcodes, scripts, or arbitrary markup;
- no more than 25 configured category rules;
- no category lookup when a product has more than 25 category terms;
- one global fallback;
- one rendered notice per supported product request.
When category state exceeds the budget, skip the category layer and preserve the bounded global fallback. When stored text contains markup or exceeds the render limit, show nothing instead of repairing uncertain data on the storefront.
Diagnose a missing or unexpected notice
| Symptom | Check first | Safe result |
|---|---|---|
| Nothing appears | Product is published, notice is enabled, text is valid, and the theme calls the native hook | Render once or remain silent |
| Category notice appears instead | Product notice is empty and product fallback is allowed | Use the first deterministic matching category rule |
| Global notice appears instead | No valid product or matching category notice exists | Use one bounded global fallback |
| No fallback appears | Product-level opt-out, inactive Pro, invalid text, or over-budget context | Preserve the unchanged buy form |
| HTML was removed | Plain-text policy | Store and output text only |
| Notice appears twice | Theme or extension invokes the location repeatedly | Render at most once per request |
| Add-to-cart stopped working | Another component owns form or validation behavior | Notice plugin must not block purchase |
A current support report describes an incumbent notice that was configured but displayed nothing on the storefront. That establishes a concrete discoverability failure, not a universal defect in all notice plugins.
Fail passive around the rest of the store
A one-message feature should not affect WooCommerce background processing or unrelated pages. One support topic reports that an incumbent prevented WooCommerce Action Scheduler from loading. Another records an uncaught TypeError.
Those reports support a smaller implementation boundary:
- no dependency container;
- no scheduler, cron, queue, or background job;
- no storefront remote request;
- no catalog scan;
- no template override;
- no frontend CSS or JavaScript;
- no exception when a required object or function is absent.
They do not prove that the same root cause affects every version or store. The release test should verify StoreFixKit's own behavior rather than repeat an allegation.
Sanitize, validate, authorize, and escape
The WordPress Plugin Handbook's common plugin issues guide separates sanitizing, validating, and escaping. WordPress also documents common text sanitizers in its sanitizing data guide.
For a product notice:
- Verify the product-save nonce.
- Authorize the exact product edit.
- Reject autosaves, revisions, and mismatched product types.
- Remove markup and normalize one plain-text value.
- Enforce the 240-character storage limit.
- Preserve the last valid value on a forged or unauthorized request.
- Revalidate stored data before output.
- Escape the final string inside the native notice wrapper.
Pro settings belong behind the WordPress Settings API and WooCommerce management capability. License actions belong behind authenticated administrator requests, not the storefront path.
Test the promise and the boundaries
Use this release checklist:
- A valid enabled product notice renders once before the unchanged buy form.
- Empty, disabled, draft, deleted, mismatched, markup-bearing, and oversized values render nothing.
- A Free product notice remains authoritative while Pro is active.
- Product opt-out suppresses category and global fallbacks.
- A matching category notice wins over the global notice.
- Multiple matching categories resolve deterministically.
- More than 25 category rules are rejected as a category layer.
- More than 25 product terms skip category matching without failing the request.
- Forged nonce and unauthorized saves preserve the prior valid notice.
- Desktop and 390-pixel mobile layouts have no overlap, clipping, or horizontal overflow.
- Product name, description, price, stock, variation, quantity, cart, checkout, and order remain unchanged.
- Free continues when Pro is removed or the license API is unavailable.
- Update, downgrade, rollback, and uninstall preserve all WooCommerce-owned data.
Resource boundary
The Free storefront path reads two owned product-meta values and emits at most one small escaped element. If Free already resolves a valid product notice, Pro performs no category read.
Only an active Pro fallback may read the product's category terms and one small local option. The feature has no custom table, recurring job, telemetry, polling, sitewide asset, or public StoreFixKit request.
Idle products and pages incur no output. An inactive Pro license fails passive and leaves Free behavior local.
Rollback and data ownership
Disabling Free removes notice output immediately without touching the product's WooCommerce fields. Removing Pro leaves every Free product notice working.
An ordinary uninstall should preserve notice values so accidental deletion and reinstall do not erase merchant copy. Explicit cleanup may remove only StoreFixKit-owned current-product keys and Pro options. It must never remove products, categories, prices, stock, customers, carts, orders, or unrelated metadata.
A release rollback should test both directions between the baseline and current package and confirm that the same valid notice returns after reactivation.
Common mistakes
Using a popup for one sentence
It adds scripts, state, accessibility work, and interruption. A native inline note is enough for a short buying detail.
Allowing HTML because the message looks simple
Links and markup expand sanitization, styling, and security scope. Keep the first release plain text.
Making the notice a purchase requirement
That changes the product into an acknowledgement or validation system. This plugin is informational and never blocks purchase.
Letting global text override a product decision
Specific product copy and explicit opt-out must remain authoritative.
Scanning the catalog to apply rules
Resolve only the current product at request time. Do not rewrite every matching product.
Claiming a warning is legally sufficient
Visibility is a technical observation, not legal validation.
Market boundary
Current WooCommerce Marketplace offers show an existing paid warnings and notices category, including public annual offers at $29, $39, and an adjacent cart-notice offer at $49. Those are competitor offer prices. They do not prove StoreFixKit sales, the number of paying customers, or future revenue.
The hypothesis to validate is narrower: nontechnical merchants will pay for reusable category and global fallback notices after Free reliably solves the product-specific job. Measure installations, notices enabled, trial starts, successful checkouts, support load, refunds, and renewals before making a revenue claim.
FAQ
How do I add a message before Add to cart in WooCommerce?
Store one plain-text value on the product and render it once through WooCommerce's woocommerce_before_add_to_cart_form hook.
Can a product notice contain links or HTML?
No. This design deliberately accepts plain text only so a small message does not become an unsafe content builder.
Does the notice prevent a shopper from buying?
No. It is informational and does not change the add-to-cart form, validation, cart, checkout, or order.
Which notice wins when Pro is active?
The product notice wins, followed by the first deterministic matching category notice, then the global fallback. A product opt-out suppresses both fallbacks.
Does a visible product warning prove legal compliance?
No. The plugin can render merchant-provided text, but it cannot validate wording, law, placement, language, or product safety.
What happens when Pro expires?
Free product notices continue locally. Category and global fallback resolution stop applying.
Focused plugin
Use the one-job implementation.
Add one short plain-text message before a product's unchanged WooCommerce buy form, with optional bounded category and global fallbacks in Pro.