The power chain
InComm offers
An offer is the unit of value InComm sells us. It has a number, a dollar value, a catalog scope, and clip rules. Everything a member spends traces back to one.
Anatomy of an offer
| Field | Meaning |
|---|---|
Number | The InComm offer number, for example 12000205. This is the join key used everywhere. cards.OfferNumber stores it as a plain string. |
Value | The offer value in cents. 9200 means $92. |
| Purse | The short label InComm gives the offer's balance bucket, for example 92Produce26. One purse per offer, set at creation, locked afterward, max 20 characters in the portal form. Redemption data reports balances per purse (marketBasket.purses[].description), so this label is how you recognize the offer inside transaction data. |
OfferType | SPEND (a balance to spend) or DISCOUNT. Almost everything we run is SPEND. |
Status | APPROVED, SUBMITTED, UPDATED, ARCHIVED, CANCELLED. |
PrimaryCatalog | A comma-separated list of catalog tags, for example X-PersonalCare,X-Supplements or OREGON1,OREGON2. This defines what the offer can buy. See Inclusion vs exclusion. Note: the combined length of all tags on one offer has a character limit at InComm, which is why newer exclusion catalogs get short tags like X-BB and X-CLN instead of descriptive names. |
PrimaryUpc | A literal UPC list. Used instead of catalogs for small brand offers, for example a Flonase $8 offer. |
| Clip rules | ClipLimit, CustomerLimit, OfferLimit, PurchaseLimit govern how often the offer can be clipped and used. |
| Windows | DistributionStart/End (when we may clip it) and OfferStart/End (when it works at the register). |
Real examples
Live production offers, so you can recognize the shapes:
| Number | Name | Value | Model |
|---|---|---|---|
12000205 | OR Produce $92 - UNL - Jun 26 x Dec 30 | 9200 | Inclusion (OREGON1,OREGON2) |
12000203 | Grocery $244 - UNL - May 26 X Dec 28 | 24400 | Exclusion (X-PersonalCare,X-Supplements,...) |
12000201 | GusNIPfreshfrozen $25 - UNL - Feb 18 X Dec 30 | 2500 | Inclusion (GusNIPFroz,GroFresh) |
12000196 | Haleon Flonase $8 - UNL - Feb 19 X Dec 31 | 800 | UPC list (no catalogs, PrimaryUpc only) |
Offer 12000204 is named "Nutrition Essentials $140" but carries Value = 6000, which is $60. Names are typed by humans and drift when offers get repurposed. When the dollar amount matters, read Value, never the name.
Reading an offer name
The name should tell you the model. "Nutrition Essentials" with X- catalogs is an exclusion offer. "OR Produce $92" with plain catalogs is an inclusion offer.
- Read the offer name. It should say inclusion or exclusion, or make it obvious.
- If it does not, read the catalog tags on the offer.
- Exclusion catalog tags start with
X-. Inclusion tags do not.
Offers attach to banners
Each offer is enabled at specific retail banners through the incommoffer_x_banner join table. A banner is a retail brand, for example Safeway or Jewel-Osco. In our database banners are rows in the retailers table. See Gotchas.
Requesting a new offer
If the client wants something we do not already have, we go to InComm:
| Request | Cost | Timeline |
|---|---|---|
| New dollar value of an existing APL (for example a $42 Grocery when we only have $50) | About $1,500 | About 1 to 2 weeks |
| A brand-new APL | More. Scoped per request. | Longer. Depends on the APL. |
The two words mean the same thing: the UPC list behind an offer. "APL" is the business word, "catalog" is the portal and database word. Existing APLs include ATF, Grocery, and Nutrition Essentials. A new dollar value reuses the APL, so it is cheap and fast. A new APL is a new list, so it is not.
We pay InComm per card or per transaction. In exchange we get real-time, item-level catalog enforcement at the register. That trade is the reason the InComm path exists at all.
What you can and cannot change
Offers live on InComm's side, but they are not read-only for us. Every portal save calls InComm's sponsor-offer API, and our database updates only if InComm accepts the change. Three layers:
| Layer | Fields |
|---|---|
| Never changes | Number (system-generated), OfferType, purse name, the catalog-vs-UPC-list mode, and the secondary catalog fields (locked, and unused anyway). |
| Editable any time, applied live at InComm | Name, tags, description, verbiage, print text, terms, all four limits (offer, clip, customer, purchase), banners, the primary UPC list, and the primary catalogs (the pencil icon on the edit page). |
| Editable only while the offer is SUBMITTED | The four dates (DistributionStart/End, OfferStart/End). A SUBMITTED offer is still being set up, so corrections to the money fields are possible in that window too, before the offer goes live. |
Value is fixed | One offer, one value, for the life of the offer. That is InComm's model: each offer is a purchased artifact with its dollar amount baked in, at about $1,500 per offer. The edit form technically accepts a new value and our API forwards it as a deferred newValue field, but nothing relies on that path. A new dollar amount means requesting a new offer. |
- Offers cannot be deleted. InComm's API has no delete for offers (promo codes do have one). Retire an offer by archiving and stopping its use.
- Approve moves SUBMITTED to APPROVED through a dedicated InComm call.
- Sync (per-offer or the "Sync Incomm Offers" button) pulls status and clip counts back from InComm. The list view's "No. of Clips" is populated only by sync, so sync before you trust it. The list's "Start Date" column is
OfferStart, not the distribution date.
For the day-to-day workflows built on this (judging an offer's age, swapping old catalogs, checking a UPC), see Catalog operations.
From offer to member
Approved offers become products. Products attach to programs. Programs order cards for members. The offer itself never touches a member directly. The clip does. See The clip lifecycle.