Methodology
How these numbers are made
Data as of . Last computed 2026-09-23 19:22 Central. Everything on this page is printed from the code that computes the readings, not written out beside it.
The short version
Every night a job on a machine inside KwickPOS reads the order, menu and store tables of the restaurants running KwickPOS, computes one value per metric per geography per day, and writes it to a small SQLite file this website reads. A value is published only when the sample behind it clears a fixed threshold. Nothing is estimated, interpolated, smoothed, seasonally adjusted or forecast, and no number on this site was typed in by a person.
Medians are the headline statistic everywhere. A median is unmoved by a handful of very large or very small tickets, which is what you want from a figure computed over thousands of independently priced menus. Where a mean is stored beside it, the page says which one it is showing.
Read a correction into any of this and tell us: hello@kwick365.com. If a figure here is wrong, it will be corrected and the correction said out loud, not quietly re-run.
Where the numbers come from
Five read-only sources, all of them the KwickPOS network’s own operational data. Nothing is bought, scraped, surveyed or modelled from someone else’s published figures.
| Source | What one row is | What it produces |
|---|---|---|
| Menu index | One restaurant, and one menu item with its listed price | Every price index; the restaurant, cuisine and metro counts |
| Online orders | One completed online order: total, tip, fees, discount, channel, item lines | Online ticket, tip rate and incidence, items per order, orders per restaurant, hour/weekday/channel/ordered-ahead shares |
| In-store day totals | One restaurant, one day: order count and dollar total rung up in store | In-store ticket, in-store orders per restaurant, restaurants trading in store |
| Store master | One restaurant: name, city, state, ZIP, live/closed status | Geography and the live-restaurant filter applied to everything above |
| Public ratings | One restaurant’s Google rating and review count | Median rating and the share rated 4.5 or better |
A restaurant counts as live, and therefore counts at all, only if it is trading, is a real food business, and is not a demo, test, dealer or non-food account. The filter is a single expression shared byte-for-byte with KwickEat, the consumer directory built from the same store master, so the two sites can never disagree about which restaurants exist.
What this sample is, and what it is not
It is the independent restaurants that run KwickPOS — 1,957 of them as of the latest build, most of them single-location, owner-run businesses, concentrated in Texas, Georgia, Florida, California and New York. Kwick365 reports what those restaurants sold, charged and were tipped.
It is not a probability sample of American restaurants. Nobody drew it at random; it is whoever bought a point-of-sale system from one company. It over-represents the cuisines and the states that company sells into and under-represents everything else, and it contains no chain restaurants of the kind that dominate national dollar figures. Do not read a Kwick365 number as an estimate of the American restaurant industry. Read it as: this is what 1,957 independent restaurants did, measured the same way every night, so the direction and the size of a change over time can be trusted even where the level cannot be generalised.
Survivorship. All readings are computed over the set of restaurants live in the KwickEat index on the build date; historical days therefore reflect today's surviving stores, not the stores live on that day. A restaurant that closed last winter is not in last winter’s figures either — which flatters the past slightly, because the businesses that did not make it are the ones whose numbers were falling.
No restaurant is identifiable. Nothing on this site is published per store. There is no dollar total for any geography, only medians, means, shares and counts, and no geography is offered at all below its store threshold. Two restaurants’ figures never appear as a “metro”.
When a figure is published, and when it is withheld
Every cell the builder computes is tested against a fixed threshold before it is allowed to be a number on a page. A cell that fails is stored as withheld and renders as “not enough data”. It is never interpolated from its neighbours, carried forward from yesterday, or shown as a zero.
- A reading publishes when
- the day has at least 30 restaurants and 500 orders behind it in that geography
- A price index publishes when
- at least 30 matching menu items are listed by at least 15 restaurants in that geography
- A metro exists when
- it has at least 30 live restaurants. Below that it is not offered as a geography at all — 21 metros are defined, 7 currently clear it
- A store count publishes when
- the store threshold alone is met: there are no orders behind a count of restaurants, so the order threshold does not apply to it
- A rating publishes when
- at least 30 restaurants in the geography have 50 or more Google reviews. A restaurant with fewer reviews than that is not counted as rated at all
- A cuisine appears when
- at least 5 restaurants in the geography cook it — a bucket of two is a step toward naming them
Of the 177,937 cells this site has computed, 144,440 are withheld for want of sample and are not shown as numbers anywhere, including in the API.
Outliers, and the dropped count
Two bounds are applied before any median is taken. They exist for data errors — a decimal point in the wrong place, a test transaction, a catering invoice rung through the till — not to tidy up real business. Anything outside them is excluded from the statistic and counted, so the exclusions are visible rather than silent.
- Online order amount
- kept when it is between $1.00 and $1,000.00;
anything outside is excluded and counted in
dropped - In-store ticket
- a restaurant’s own average ticket for the day (its dollar total ÷ its order count) is kept when
it is between $2.00 and $500.00;
outside that the restaurant’s whole day is excluded from the median and counted in
dropped - Impossible dates
- rows dated in the future are excluded outright — they are data-entry artefacts, not trading
- What
droppedcounts - the number of rows the bounds above removed from that one cell — orders for an online reading,
restaurant-days for an in-store reading. It is a count of rows, not of dollars, and it is never subtracted
from the sample size —
nis what the figure was actually computed over, after the bounds
13,428 rows have been dropped by these bounds across every national cell this site has computed, over 479 days.
Coverage: how to tell a thin day
A holiday, an outage or a slow Tuesday can leave a day with far fewer restaurants reporting than usual. Such a day is real and is published, but comparing against it would be misleading, so every cell carries a coverage figure and the site refuses to draw a change from a thin one.
- Coverage is
- the day’s restaurant count divided by the median restaurant count over the previous 28 published days of the same metric and geography
- Computed only when
- at least 7 earlier published days exist to compare against. Before that it is stored as NULL, which means unknown — not zero, and not “fine”. A NULL never counts as low coverage and never suppresses anything
- A day is flagged thin when
- coverage is below 50.0% of its own recent normal. The figure is still shown, badged, and is excluded from every day-over-day and year-over-year comparison on the site
The change guard
A pipeline failure can look exactly like news. So a headline national reading that moves more than 30.0% in a single day is not published that night: the page keeps showing the last good value with a notice saying it is being held, and a warning goes to the operations channel for a human to look at.
- Guarded readings
- Online order ticket, Online tip rate and In-store ticket, plus every price index
- Trigger
- a day-over-day move of more than 30.0% against the previous published day
- It clears itself when
- the new level holds: once three consecutive held days sit within 10.0% of each other, the move is a real step rather than a glitch, and the reading resumes publishing from the day the step began. A guard that needed a human to clear it would turn a real market move into a permanent gap
Geography, and what a “metro” is here
National and state figures are exact: a restaurant is in the state its store record says it is in. Metros are an approximation, and this is the weakest link in the geography.
- How a metro is assigned
- by the first three digits of the restaurant’s mailing ZIP code, against a fixed list of ZIP3 prefixes per metro. 21 metros are defined this way
- What that gets wrong
- a ZIP3 prefix is not a Census metropolitan statistical area. Some outer suburbs fall outside the prefixes listed for their metro and are counted only in the state; a prefix that straddles a metro boundary puts every restaurant in it on one side. A restaurant whose ZIP is missing or unmapped is counted nationally and by state, and in no metro at all
- Why not use MSAs
- because the store master carries a mailing address, not a Census geography, and inventing a crosswalk that is precise to the census tract from a mailing ZIP would add false precision, not remove it. The rule is stated plainly instead, so a reader can decide what it is good for
- Currently publishing
- 7 metros and 18 states have at least one published figure. A state or metro with none has no page
- National-only readings
- a reading that has never cleared its threshold for any metro on any day is not a reading having a bad day — the sample is not there to support it locally, and it never will be without more restaurants. Its page says that in words, with the largest sample a metro actually reached, rather than printing a table whose every row reads “not enough data”. Currently Online tip rate is national-only. So are 10 of the 13 dish indexes. The test is made against the data on every page load, so a reading that starts clearing the threshold locally gets its table back with nothing edited
Every reading, defined
These are printed from the same catalogue the tiles, the charts and the JSON API read, so the definition here is the one under the number.
| Reading | Unit | Definition |
|---|---|---|
Online order ticket
online-ticket |
median $ per order | The median total of a completed online order — what the guest paid, including tip and fees, after discounts. Second number: mean $ per order. |
Online tip rate
online-tip-rate |
median tip ÷ subtotal | Median tip ÷ subtotal over orders that tipped; incidence = share of orders with a tip. Second number: share of orders that tipped. |
Items per online order
online-items-per-order |
line items per order | Line items per order (not units): a single line of "3 × taco" counts once. Second number: mean line items per order. |
Online orders per restaurant
online-orders-per-store |
orders per active restaurant | Online orders ÷ stores with at least one online order that day. Second number: restaurants with at least one online order. |
In-store ticket
instore-ticket |
median of each restaurant’s average ticket | Median of each store’s average in-store ticket that day. Second number: mean of each restaurant’s average ticket. |
In-store orders per restaurant
instore-orders-per-store |
median orders per restaurant | The median number of in-store orders a restaurant rang up that day. Second number: mean orders per restaurant. |
Restaurants trading in store
instore-active-stores |
restaurants | How many restaurants rang up at least one in-store order that day. |
Restaurants in the index
network-active-stores |
restaurants | Independent restaurants live in the network on the day the index was built. |
Median Google rating
network-rating-median |
stars out of 5 | The median Google rating of restaurants in the index with at least 50 reviews. Second number: mean Google rating. |
Rated 4.5 or better
network-rating-45-share |
share of rated restaurants | The share of restaurants with at least 50 Google reviews that are rated 4.5 or higher. Second number: restaurants rated 4.5 or better. |
Online orders by hour online-hour |
share of the day's orders | The share of a day's completed online orders placed in each hour, on the POS platform's clock. A distribution, not a daily headline reading. |
Online orders by weekday online-weekday |
orders per active restaurant | Online orders per restaurant that took at least one online order, averaged by weekday. A distribution, not a daily headline reading. |
Online order channel online-channel |
share of orders | The share of completed online orders placed for pickup, delivery, dine-in or curbside. A distribution, not a daily headline reading. |
Ordered ahead online-scheduled |
share of orders | The share of completed online orders scheduled for a later time rather than as soon as possible. A distribution, not a daily headline reading. |
Restaurants by cuisine network-cuisine |
restaurants | How many restaurants in the index cook each cuisine, as classified from their menus. A distribution, not a daily headline reading. |
Hour buckets are recorded on the point-of-sale platform’s clock (US Central), not each restaurant’s local time; a page that prints an hour says so.
Every dish index’s matching rules
A price index is the median of what restaurants list a dish at on their own menus — the asking price, before any discount, tax, tip or delivery fee, and regardless of whether anyone ordered it. Items are matched by name with the regular expressions below, run against the lower-cased item name in the order shown; the first rule that matches wins. These are printed from the builder’s own rule table.
One exclusion runs before all of them: a kids’ or children’s menu item is a smaller,
cheaper product than the dish it shares a name with, so it never counts toward any index —
/\bkids?\b|\bkid'?s\b|\bchild(ren)?\b|\bjunior\b|\bjr\b/.
| Index | Counted when the name matches | Never counted when it also matches | Cuisines |
|---|---|---|---|
| Taco (single) per taco | /\btacos?\b/ |
/salad|plate|combo|dinner|\b[2-9]\s*tacos|\bdozen|bowl|kit|family/ |
Mexican |
| Burrito each | /\bburritos?\b/ |
/bowl|plate|combo|family|breakfast burrito/ |
Mexican |
| Pho (regular bowl) per bowl | /\bpho\b/ |
/kids|small|large|xl|extra|combo|family|dry|\bbanh\b/ |
Vietnamese |
| Pizza slice per slice | /\bslice\b/ |
/cake|pie slice|cheesecake|bagel/ |
Pizza, Italian |
| Large pizza per pie | /\b(large|lg|extra large|x-large|xl)\b.{0,15}pizza|\b(14|15|16|17|18|19|20)\s*"?\s*(inch)?\b.{0,15}pizza|pizza.{0,15}\b(14|15|16|17|18|19|20)\s*"?/ |
/wing|soda|knot|combo|dinner|kids?\b|family|dough|calzone|\bsub\b|hero|salad|fries|liter|\b2\s?l\b|dozen|pasta|penne|steak|ravioli|mozzarella stick|dessert|beer|special|half|slice|topping|pizzas\b|\b[2-6]\s*(large|lg)\b/ |
Pizza, Italian |
| Burger (basic) each | /\b(cheese)?burger\b/ |
/double|triple|combo|meal|slider|veggie|impossible|beyond|salmon|turkey|kids/ |
Burgers, American |
| California roll per roll | /\bcalifornia roll\b/ |
/spicy|combo|lunch|dinner|special|box|set|tempura|crunch/ |
Japanese |
| Ramen (basic bowl) per bowl | /\bramen\b/ |
/kids|combo|set|lunch|extra|add|topping|instant|spicy miso deluxe/ |
Japanese |
| Wings (10 pc) per 10 pc | /\b10\s*(pc|pcs|piece|pieces)?\b.*\bwings?\b|\bwings?\b.*\b10\s*(pc|pcs|piece|pieces)\b/ |
/\b(6|8|12|15|20|25|30|50)\s*(pc|pcs|piece|pieces)?\b|combo|family|party|boneless|meal|sandwich|shrimp|shr\b|drinks?|w\/|fries|special|platter|dinner|lunch|&|soda|fried rice|\bwith\b|\band\b|\bpizza\b|\bpc\s*\w+\s*\+|\+|#\d/ |
Wings, American, Pizza |
| Chicken fried rice per order | /\bchicken fried rice\b/ |
/combo|lunch|family|small|large|dinner|special/ |
Chinese, Thai, Japanese |
| Pad Thai per order | /\bpad thai\b/ |
/lunch|combo|family|dinner special|kids/ |
Thai |
| Coffee (regular drip) per cup | /\b(regular |drip |house |hot )?coffee\b/ |
/iced|latte|cold brew|frappe|mocha|cappuccino|espresso|large|xl|bag|beans?|\blb\b|pot|box|carafe|decaf blend|cake|affogato|dessert|ice cream|gelato|tiramisu|grounds|k-cup|pod|walnut|swirl/ |
Cafe, Breakfast, Sandwiches |
| Margarita (house) each | /\bmargarita\b/ |
/pitcher|pizza|flight|jumbo|large|premium|top shelf|cadillac|frozen flight/ |
any |
13 indexes. A dish is matched on the item’s name alone: the menus carry no structured dish taxonomy, so a restaurant that calls its pho “house special soup” is not in the pho index, and nothing pretends otherwise. Cuisine is classified from the restaurant’s own menu by the same classifier the consumer directory uses.
The calendar
The one part of this site that a person wrote rather than a job computed. It holds 109 entries on 90 days of the year, each carrying the primary page it was verified against — cdtfa.ca.gov, comptroller.texas.gov, dor.georgia.gov, floridarevenue.com, ipt.fifa.com, irs.gov, media.nfl.com, mlb.com, nationaldaycalendar.com and tax.ny.gov. The loader refuses any entry without a working source URL, so an unsourced date cannot be rendered even if someone adds one to the file. The remaining 276 days of the year are deliberately blank. The calendar.
Build schedule, revisions and history
- Rebuilt
- every night, after the menu index rebuilds. Last run 2026-09-23 19:22 Central.
- Revisions
- the last three days are recomputed every night, because an order can be completed after midnight. Days older than that are never rewritten
- History
- 479 days with something published, from June 1, 2025 to September 22, 2026. Price indexes have history only from the day they were first computed: the menu index is a snapshot with no past, so backdating menu prices would be inventing them
- Year-over-year
- shown only where 365 days of published history actually exist for that metric and geography, and never against a thin day
- Rounding
- money to the cent, shares to one decimal place, ratios to one decimal place, counts to no decimal places. Rounding happens at display time; the stored value and the JSON API carry the full precision the computation produced
What this site does on your machine
No cookies, no analytics, no advertising, no accounts, no tracking of any kind. The charts are server-rendered
SVG and work with JavaScript off. The one third party is Google Fonts: the pages load the Newsreader typeface
from fonts.googleapis.com and fonts.gstatic.com, so your browser makes a request to
Google, which necessarily reveals your IP address and user agent to them. Nothing else on the page comes from
anywhere but this site. Privacy.
Taking these numbers
Free to cite with a link. Every reading has a JSON endpoint that returns published cells only, and an embeddable chart. Terms · About Kwick365 · For restaurants
- JSON
https://kwick365.com/api/v1/reading/online-ticket/?geo=us - Chart
<iframe src="https://kwick365.com/embed/online-ticket/us/" width="560" height="360" style="border:0" title="Online order ticket — Kwick365"></iframe> - Contact hello@kwick365.com