CGPI98.7wk▼ -1.4%since July▼ -1.3%weekly · data through Aug 9
Data catalog
Everything we publish, and how to get it
Four datasets come off one weekly collection run: an aggregate price index, the item-level panel underneath it, the pack-size changes that panel reveals, and the coverage matrix that tells you where the numbers exist. Each is documented below the way a data buyer needs it — unit of observation, coverage, history, cadence, lag, delivery and licence. The published index begins July 2026: this is a young, high-frequency panel, not a long back-history, and we price and describe it accordingly.
The panel behind every dataset
13
cities, coast to coast
22
retailer banners
~160
active stores
50
basket items
9
categories
Every dataset on this page is a different cut of that one panel, so the coverage caveats are shared: Walmart and Costco are not in the panel and Giant Tiger carries only part of the basket. Prices are read from publicly accessible retailer websites — online list prices, which can differ from the shelf. See the full coverage matrix →
The datasets
1. Canadian Grocery Price Index (CGPI)
Free · CC BY 4.0
The published headline series and every cut beneath it, plus the dollar cost of a fixed 50-item basket. The headline and the nine category sub-indices are ONE estimator, so the headline can be rebuilt from the categories exactly: a direct fixed-base matched-model Jevons versus the week of 2026-07-13 = 100, with price relatives formed within a single store, so category levels are comparable with each other.
Unit of observation
One row per week × city × banner × category, plus the aggregate rows where any of those dimensions is NULL.
Coverage
13 cities · 22 banners · ~160 stores · 50-item basket · 9 categories. Walmart and Costco are not covered; Giant Tiger is partial.
History
Weekly from July 2026 (methodology v2). Roughly seven to eight weekly points deep as of this quarter. We publish week-over-week and since-inception change only — there is no year-over-year figure anywhere on this site, because the record cannot yet support one.
Cadence & lag
Collected every Thursday 08:00 UTC with an automatic Friday catch-up; weeks end Sunday. JSON is available same week. The free CSV pack is monthly on a 14-day delay.
Delivery
JSON via the free /api/public/index (no key, CORS-open, ~60 requests/min). Monthly CSV pack below. A citable page per series at /series/<id>.
Licence
CC BY 4.0. Attribution required. Redistribution or resale of the underlying data requires a licence.
Key fields
date, city, retailer, category, index_value, basket_cost_cad, pct_change_wow, item_count, total_items — defined field by field in the data dictionary.
The microdata the index is computed from: every observed price for every basket item at every tracked banner and city, week by week. Regular and sale prices are carried alongside the effective price actually charged, where the chain publishes them. Promotional capture varies by chain and is documented in the methodology.
Unit of observation
One row per canonical product × banner × city × observation.
Coverage
13 cities · 22 banners · ~160 stores · 50-item basket · 9 categories. Walmart and Costco are not covered; Giant Tiger is partial. Each observation carries its store’s city and province and links to one of the 50 canonical basket products.
History
Weekly. Observations are append-only and run back through the pilot collection that preceded the July 2026 index inception; only July 2026 onward is quality-gated for publication. Because the index is recomputed from the full observation history, a correction propagates through the whole record instead of leaving a step in the series.
Cadence & lag
Weekly, same week — licensees do not wait out the 14-day delay that applies to the free CSV packs.
Delivery
JSON via /api/v1/prices with a bearer key; up to 10,000 rows per request with offset paging, filterable by product_id, city, banner and date range. Bulk historical extracts on request.
Licence
Commercial licence only. Not covered by CC BY 4.0, and not redistributable.
Key fields
observed_at, regular_price, sale_price, effective_price, unit_price, package_size, in_stock, is_on_sale, plus canonical product linkage (product_id, name, category, subcategory, basket weight, brand, store-brand flag) and store geography. The store-brand flag is three-state: it identifies private label on about 75% of rows and is null, meaning unknown, on the rest.
Pack-size reductions detected by comparing a retailer product's package size across consecutive weeks, then testing whether its unit price moved the way a genuine shrink implies. Events that fail that mirror test are graded down rather than dropped, so you can see the evidence instead of trusting a label.
Unit of observation
One row per detected size-change event: retailer product × change date.
Coverage
The same panel, restricted to products whose package size parses cleanly and whose listing persists across weeks. Confidence is graded high / medium / low from how closely the unit-price rise mirrors the size cut.
History
Weekly since the panel began. Expect thin counts by construction: a young panel has had few opportunities to observe a size change, and we would rather report a short, clean event list than pad it with suspect swaps.
Cadence & lag
Recomputed weekly alongside the price run; the API defaults to a 90-day event window.
Delivery
JSON via /api/v1/shrinkflation with a bearer key, filterable by banner, date range and minimum confidence. A free, human-readable summary lives at /shrinkflation.
Licence
Commercial licence for the event feed. The published summary page is free to read and cite with attribution.
Key fields
pct_size_change, pct_unit_price_change, confidence, and a flag of ok, suspect_unit_mismatch, suspect_swap or suspect_tiny, alongside the product, banner and dates.
How much of the basket each banner × city cell actually priced in a given week, and therefore which cells published and which were suppressed. This is the dataset that lets you audit our numbers rather than take them on faith — it is deliberately free for exactly that reason.
Unit of observation
One row per banner × city × week (item_count of total_items).
Coverage
Up to 22 banners × 13 cities. Banner lineups are genuinely regional, so a sparse row is usually geography rather than a collection failure. A cell publishes only above the 60% floor, and cannot win a cheapest-store call-out below 48 of 50 real prices.
History
Weekly from July 2026, matching the index it qualifies.
Cadence & lag
Weekly, published with the index run; the CSV slice ships in the monthly pack on the same 14-day delay.
Delivery
Rendered at /coverage; JSON via /api/public/index?level=banner, where item_count and total_items appear on every row; CSV in the coverage slice of the free pack.
Licence
CC BY 4.0. Attribution required; no redistribution or resale.
Key fields
date, city, retailer, item_count, total_items, and the derived above-/below-floor status.
The research tier: a monthly snapshot of the index in five flat files, published on a 14-day delay, free for journalists, academics and policy researchers under attribution. No signup, no key. For the live same-week series, use the free /api/public/index endpoint instead; for the per-item panel, see pricing.
Basket cost is the sum of each matched item's most recent observed effective price (sale price when on sale, otherwise regular) within that banner that week; cheapest-banner rankings are restricted to near-complete baskets (≥48/50 matched items) because missing items deflate basket cost. Observations are append-only; the index is recomputed from the full observation history under versioned normalization code, and the superseded v1 fixed-base series remains available via the API. See methodology for the full specification.
Data dictionary — index rows
These are the columns you get from /api/public/index and from the CSV pack. The NULL semantics matter more than usual here: the dimension columns encode aggregation level by being empty, so filtering them out silently discards the national and all-banner series.
Field definitions and null semantics for GroceryPulse index rows.
Field
Type
Meaning
Null semantics
date
date (ISO)
Week-ending Sunday of the reporting week, bucketed in Canadian local time. One row per series per week.
Never null. Published rows are floored at 2026-07-19.
city
text
City the cell covers, e.g. Toronto, Montreal, Saskatoon.
NULL = national aggregate (all 13 cities).
retailer
text
Banner key the cell covers, e.g. metro, freshco, saveonfoods.
NULL = aggregate across every banner in that geography.
category
text
Basket category slug, e.g. dairy, produce, bakery.
NULL = all groceries (the headline, all-category series).
index_value
numeric
Headline rows (category NULL): direct fixed-base matched-model Jevons, on the same estimator as the category rows, versus the week of 2026-07-13 = 100, with price relatives formed within a single store.
Never null on a published row. Headline levels are NOT comparable across series; category levels ARE comparable with each other (change since July 2026).
basket_cost_cad
numeric
Dollar cost of the 50-item basket for this cell, using each item's most recent effective price (sale price when on sale). This is the metric that IS comparable across cities and banners.
Null where too few items priced to state a cost.
pct_change_wow
numeric
Percentage change in index_value versus the prior published week.
NULL on a series' first week — there is no prior week to link to.
item_count
integer
Basket items actually priced in this cell this week (real prices, not imputed).
Null only on legacy rows written before coverage stamping.
total_items
integer
Items in this cell's basket slice — 50 for an all-category cell, fewer for a single category. item_count / total_items is the coverage ratio the 60% publication floor is applied to.
Null only on legacy rows written before coverage stamping.
Two reading rules that catch most first-time users. Headline city and banner levels are rebased to 100 in each series' own entry week, so a city reading 103 and another reading 101 tells you nothing about which is more expensive: compare basket_cost_cad in dollars instead. Category sub-index levels are the exception. They are all measured against the week of 2026-07-13 = 100, so they can be compared with each other as change since July 2026. And there is no year-over-year column, because the published record starts in July 2026.
Licensing, stated plainly
Free CSV packs and the public index
Published under CC BY 4.0. You may chart it, quote it, model with it and publish the results, including commercially, provided you attribute GroceryPulse. What you may not do is redistribute or resell the underlying data — republishing the series as a dataset, or reselling it inside a product, needs a licence.
Attribution line: “Source: GroceryPulse Canadian Grocery Price Index. Research led by Sung Ha Hwang, Co-founder and Research Director.”
The per-item panel and event feed
The basket-level price panel and the shrinkflation event feed are commercial-licence only. They are not covered by CC BY 4.0, are not redistributable, and are served against a bearer key with per-seat terms. Evaluation extracts and trial keys are available — the panel is small enough that we would rather you test it on your own question than take our word for it.
The CGPI panel is shared with Dalhousie University’s Agri-Food Analytics Lab, and the index has been cited by CBC, National Post, the Winnipeg Free Press, TVA Nouvelles and Le Journal de Québec.
Evaluating the data?
Start with the free endpoint and the coverage matrix — between them they answer most diligence questions without a call. If you need a city, banner or basket item we do not cover, or a historical extract, write to sales@grocerypulse.ca.