Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Statamic Offers Laravel Package

goldnead/statamic-offers

Statamic Offers is a Laravel package that adds offer management to Statamic CMS. Editors can create and organize offers in the control panel, while developers can surface them in Antlers templates for promotions, deals, or listings.

View on GitHub
Deep Wiki
Context7

Product Decisions This Supports

  • Offer catalogue and packaging: v1.18.0 makes offers first-class objects in the funnels map (type: offer, id = handle, number = seats accepted in the period). Product can now decide what an offer is and where it appears in a funnel without inventing an application-side registry. This is the packaging layer: naming, tiers, launch offers, and which offer a given funnel step points at.
  • Capacity as a go-to-market lever: The seat count attached to an offer turns scarcity into a configurable, addressable attribute rather than a hard-coded campaign hack. Decisions about cohort caps, beta waitlists, "first 100 customers" launch offers, and limited-seat upsells can be made in the funnel map and reasoned about by non-engineers. Caveat for the pricing owner: "seats accepted in the period" needs a written definition — billing period vs. campaign window vs. calendar month — before anyone promises a cap in marketing copy.
  • Funnel composition and experiment design: Because offers are referenceable objects, roadmap questions become answerable: which offer sits at which funnel step, what happens when a step is exhausted, and can two funnels point at the same offer without duplicating its definition. This is the substrate for A/B tests on offer placement rather than only offer price.
  • Build vs. buy: Still tips toward buy/extend. The package now owns basket maths, subscriptions, checkout, coupons, setup fees, bumps, and the funnel-to-offer mapping. Every one of those is a bespoke build avoided; the marginal cost is accepting the package's object model.
  • Complements, not replaces, the "due today" work: Basket::firstPaymentCent() (the v1.15.0 capability) remains the single source of truth for the checkout figure across trials, coupons, setup fees, and bumps. The funnel/offer layer decides what is presented; firstPaymentCent() decides what is charged today. Keep these two concerns separate in roadmap discussions — conflating them is how display/booking drift returns.
  • Platform dependency as a decision input: The release requires statamic-brand-context ^1.17. That is a real constraint on your CMS/upgrade calendar and couples content-driven marketing pages to the billing surface. Worth an explicit decision, not an incidental one, especially if you run Statamic for landing pages and campaign microsites.
  • Reconciliation and reporting: netCent() semantics remain untouched; both the v1.15.0 payment figure and this release's offer mapping are additive. Finance-facing reporting keeps its existing meaning while checkout display and funnel composition gain dedicated, auditable surfaces.

When to Consider This Package

Adopt (or keep) it when:

  • You sell subscriptions and/or one-off checkouts in Laravel and need trials, coupons, setup fees, and order bumps to interact predictably.
  • You need the displayed price and the booked price to be provably the same number, sourced from the package rather than application-layer arithmetic.
  • You run funnels with more than one offer — or intend to — and want offers addressable by handle rather than duplicated per landing page.
  • You want seat-limited launches, cohorts, or waitlists expressed as configuration, not as a bespoke counter in your app.
  • You already run Statamic (or are willing to adopt statamic-brand-context ^1.17) and want content-managed funnel/offer pages backed by the same model as billing.
  • You want to avoid re-deriving billing or offer rules across checkout controllers, emails, funnel pages, and invoice previews.

Look elsewhere or proceed with caution when:

  • Your billing model is usage-based or metered with post-paid invoicing; a "first payment" concept may not map cleanly.
  • Your marketing stack is not Statamic-based. The new hard dependency is a poor fit if it drags in a CMS you do not run — evaluate the cost honestly rather than vendoring around it.
  • You need multi-currency tax-inclusive display beyond what the basket abstraction covers — validate the tax/rounding path yourself.
  • You have existing custom overrides of basket totals; the trial-takes-the-discount-slot rule will conflict with any internal policy that expects coupons to stack on trials.
  • You need guaranteed seat enforcement across concurrent checkouts. The release describes offers as objects the funnel map can point at; it does not describe a reservation or oversell-prevention mechanism. Treat seat counts as capacity intent until you have verified enforcement under load.
  • You are not prepared to treat pricing and offer rules as product decisions owned jointly with finance/marketing — the package will enforce its model whether or not your go-to-market copy agrees.

Adoption checklist: pin the version; upgrade statamic-brand-context to ^1.17 in the same change window and smoke-test content pages; add a regression test asserting firstPaymentCent() equals the amount recorded by Subscriptions::start()/Checkout::start() across trial, coupon, setup-fee, and bump combinations; add a second test that each funnel-mapped offer handle resolves and reports the expected seat count; document the trial-vs-coupon precedence and the definition of "period" for seat acceptance in your pricing policy; and flag any funnel step whose offer can be exhausted, so the depleted-state UX is designed rather than discovered.

How to Pitch It (Stakeholders)

To executives: Two releases land the same theme — making money-facing surfaces consistent with the system that actually bills. v1.15.0 closed a checkout-integrity gap: customers were shown a "due today" figure that differed from what was charged, a direct driver of support load, refunds, and lost trust; Basket::firstPaymentCent() makes the displayed amount the same calculation the billing engine uses across paid trials, coupons, setup fees, and bumps, and it is additive with no migration. v1.18.0 extends the same principle to what we sell and where: offers become real, referenceable objects in the funnel map, so marketing can define an offer — including a seat cap — once and point any funnel step at it. Practically, that means faster campaign setup, no divergent offer definitions across landing pages, and a configurable lever for limited-seat launches. Two costs to note: the release hard-requires statamic-brand-context ^1.17, so it is coupled to our CMS upgrade calendar; and seat counts should be treated as capacity intent until engineering confirms enforcement under concurrent checkout.

To engineering: v1.18.0 adds offers to the funnels map as addressable objects — type: offer, id = handle, number = seats accepted in the period — and takes a hard dependency on statamic-brand-context ^1.17, so schedule the upgrade with the CMS change rather than after it. This is additive to the v1.15.0 payment work: Basket::firstPaymentCent() still mirrors the charging path of Subscriptions::start() and Checkout::start() (a paid trial replaces the main line price and consumes the payment's single discount slot, so coupons do not stack; otherwise basket minus coupon, plus setup fee and ticked bumps), and netCent() semantics are unchanged. Actions: adopt firstPaymentCent() for every "due today" surface (checkout, cart summary, confirmation emails) and delete locally reimplemented totals; add a parity test against the booked amount — the motivating staging case was 65 EUR displayed vs. 45 EUR booked, and 37 EUR vs. 27 EUR with a 10 EUR coupon; resolve offer handles through the funnels map instead of hard-coding offer data; add a test per funnel-mapped offer handle and seat count; and verify what "accepted in the period" means in code and whether concurrent checkouts can exceed number. Flag any product policy that expects coupons to stack with trials, and any funnel step with a finite seat count that lacks a designed depleted state, before rollout.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin