CGPI98.7wk -1.4%

Whitepaper · v1.3 · 2026-08-10

Also available: methodology summary · free data packs · commercial tiers

GroceryPulse Canadian Grocery Price Index (CGPI)

A real-time alternative food-price dataset for macro, rates, and consumer-sector analysts

Version 1.3 (2026-08-10) Sung Ha Hwang · Co-founder and Research Director GroceryPulse Research · hello@grocerypulse.ca · grocerypulse.ca


Abstract

Grocery prices are among the most closely watched household costs in Canada, but the advertised prices shoppers actually see week to week are not published anywhere in a standardized, comparable form. GroceryPulse measures exactly that, through weekly collection of a standardized 50-item basket of essential grocery products from 22 banners (six retailer families, roughly 160 active stores) across 13 Canadian cities, publishing a matched-model Jevons price index (methodology v2) with same-week availability.

This paper describes the data, the index construction, the quality-control protocol, and the commercial API product. It is intended as reference documentation for subscribers evaluating GroceryPulse as an alternative-data input to price monitoring and consumer-sector research.


1. Why another price index?

1.1 The measurement gap

Official consumer price statistics measure transaction prices: what shoppers actually paid at the till, drawn largely from retailer scanner data. That is the right instrument for measuring realised inflation, and it is the authoritative one.

It is not, however, a measure of what a shopper sees on the shelf. Advertised prices, and the promotional cycles that drive them, are a distinct and separately interesting quantity, and no Canadian source publishes them in a standardized, comparable, weekly form.

1.2 The transparency gap

Where item-level price data does exist it is generally not public. Users cannot audit, decompose, or reproduce a food price series from its underlying observations. Private replication by bank economics teams and research shops is common but expensive and fragmented.

1.3 The granularity gap

Published food price series are national and provincial. There is no public city-level, retailer-level, or banner-level breakdown, all of which matter for regional consumer-spending models, retail competitive analysis, and store-footprint work.

GroceryPulse is designed to address these three gaps: a weekly, transparent, granular measure of advertised grocery prices.


2. Data coverage

2.1 Cities (13)

Vancouver, Calgary, Edmonton, Saskatoon, Winnipeg, Toronto, Ottawa, Montreal, Quebec City, Moncton, Halifax, Charlottetown, St. John's.

Together these cities represent approximately 55% of Canadian grocery spend and all ten provinces.

2.2 Retailer banners (22 active, six retailer families)

Loblaw Companies — Loblaws, No Frills, Real Canadian Superstore, Atlantic Superstore, Dominion, Maxi, Provigo, Fortinos, Wholesale Club, Your Independent Grocer.

Empire Company — Sobeys, FreshCo, IGA, Safeway, Foodland, Thrifty Foods.

Voilà (Empire online) — collected as its own banner; the Voilà storefront also carries Farm Boy products.

Metro Inc. — Metro, Food Basics, Super C.

Independents / regionals — Save-On-Foods (Pattison), Giant Tiger.

Coverage spans the three largest Canadian grocery parents (Loblaw, Empire, Metro), Empire's Voilà online storefront, and two regional players (Pattison's Save-On-Foods, Giant Tiger), totalling roughly 160 active stores. Giant Tiger is a general merchandiser and stocks only part of the basket — see §7.5. Walmart Canada and Costco are not currently covered — see §7.2.

2.3 Basket (50 items, 9 categories)

Category Weight Products
Dairy 15% 2% milk 4L, butter 454g, eggs 12pk, cheddar 400g, Greek yogurt 750g, …
Meat & poultry 19% Chicken breast, ground beef, pork chops, bacon, deli ham, …
Bakery 8% Whole-wheat bread, bagels, tortillas, …
Fruits 10% Bananas, apples, strawberries, grapes, oranges
Vegetables 10% Potatoes, onions, tomatoes, broccoli, lettuce
Pantry 12% Rice 2kg, pasta, canned tomatoes, cooking oil, flour
Frozen 8% Frozen pizza, ice cream, frozen vegetables
Beverages 7% Coffee, orange juice, cola 2L, bottled water
Household 9% Paper towel, dish soap, toilet paper, laundry detergent

Weights are calibrated to the StatCan Food purchased from stores sub-basket using the most recent published weight-share release, renormalized to 100%.

2.4 Collection cadence and observation volume

Prices are collected weekly, on Thursdays, with an automatic Friday catch-up run for any city below 90% store coverage. The published series begins June 2026 — the v2 quality baseline; an earlier March–June 2026 pilot is retained for continuity under series=v1 (see §3.1). Reporting weeks are bucketed by Canadian local time (America/Toronto) and end on Sundays.

Tier Volume
Per weekly cycle up to ~8,000 store-item price points (≈160 active stores × 50-item basket; lower where items are unmatched)
Per year (steady state) on the order of 400,000
Fields per observation 12 (price, sale price, unit price, pack size, in-stock, sale flag, store-brand flag, retailer SKU, banner, store ID, city, timestamp)

Data is stored append-only in PostgreSQL 15 (Supabase) with partitioning readiness on observed_at.


3. Index construction

3.1 Primary index: matched-model weighted Jevons (methodology v2)

The CGPI uses two estimators. The headline (all-items) index is chained week over week. The nine category sub-indices are compared directly with a fixed base week, the week of 2026-06-01 (week ending Sunday 2026-06-07), a change adopted 2026-08-10. Both are matched-model weighted Jevons forms.

Headline (all-items): chained. For each reporting week t, each city c, and each banner b, the headline series is built from week-over-week links:

link(c, b, t) = exp( Σ over i ∈ S(t) of w̃ᵢ · ln(Pᵢ,t / Pᵢ,t−1) )
I(c, b, t)    = I(c, b, t−1) × link(c, b, t)

where S(t) is the set of basket items priced in both week t and week t−1, and w̃ᵢ are the basket weights renormalized over S(t) for each link. Links accumulate into the published level. Because each link is computed over the same matched set in both weeks, week-over-week changes are same-composition by construction. Each headline series equals 100 in its own entry week: a headline level reads as "change since that series entered the panel", not "change since a common base date", and headline levels are not comparable across cities or banners. The headline carries 44 to 47 of the 50 basket items in a typical week, so churn in the matched set stays small relative to the basket; its published path has been verified against a direct matched-pair computation.

Category sub-indices: direct fixed-base (adopted 2026-08-10). The nine category sub-indices are not chained. Each week t is compared directly with the base week b, the week of 2026-06-01, over the items priced in both:

I(t) = exp( Σ over p of w̃ₚ · mean over store cells of ln(Pₚ,cell,t / Pₚ,cell,b) ) × 100

Every price relative is formed within a single store, never across stores or banners. Log relatives are averaged per basket product, so a widely stocked product does not out-vote its basket weight, and the per-product means are weighted by basket weight, renormalized over the products that matched. Within each product, the top and bottom 10 percent of store-level relatives are trimmed before averaging, which removes residual slot-occupant and price-basis switches that survive the quarantine. Nothing accumulates across weeks: the level at week t depends only on the base week and week t, a matching error in one week affects that week only, and re-running any week reproduces its published value.

The categories use a different estimator because chaining fails at their sample size. Each category chains over only 4 to 7 items whose matched set churns week to week, and sale-price bouncing amplifies the effect: an item's price fall can enter one link while its recovery falls out of the next, leaving the level permanently displaced. This is chain drift in the sense of the ILO/IMF Consumer Price Index Manual. In the published record, the nine chained category paths weighted together read roughly +0.5% between 2026-06-07 and early August 2026 while the headline read −2.0% over the same window, and individual category paths contained moves (household −15.8% in one week, frozen +36% in two months) that were sample changes, not price changes. The headline does not share this failure mode: the same churn averages out over its 44 to 47 items. The discrepancy was flagged by an institutional reader on 2026-08-08 and the correction was adopted on 2026-08-10; during the revision the published headline rows were verified byte-identical.

Level semantics. Every category series, at national, city, and banner level, reads as "change since the week of 2026-06-01", so category levels are comparable with each other: across categories, across cities, and across banners. Headline levels are not; each headline series remains rebased to 100 in its own entry week and is comparable only within itself. Week-over-week change for a category is the ratio of the two published levels, so the published table always reconciles with its own columns; it is null after a missing week. Month-over-month change is computed from published levels the same way. A store or banner onboarded after the base week contributes no price relatives, and a banner cell with no base-week data publishes no category series.

Publication floor and the cost of a fixed base. A cell publishes only when at least 60% of its basket slice (and at least 2 items) is priced in both weeks being compared: the two linked weeks for the headline, the base week and the current week for a category. A fixed base has a cost, and we disclose it: as the panel's stores and product matches turn over, the share of a slice still matchable against the base week declines. A warning fires when a category's national coverage falls below 75%, and when coverage erodes the series will be re-based, with disclosure, rather than patched.

We use the Jevons (geometric-mean) form rather than Laspeyres (arithmetic-mean) for two reasons:

  1. Substitution bias. The geometric mean implicitly assumes unit-elastic substitution, which more closely reflects observed consumer behaviour than Laspeyres' zero-elasticity assumption.
  2. Symmetry. A +50% and –50% price change offset exactly under Jevons; Laspeyres is biased upward.

The Jevons form is recommended by the ILO/IMF Consumer Price Index Manual (2020) for elementary aggregates. The chained form used for the headline is the form used by Eurostat for HICP sub-indices.

Methodology change log

  • v1 (2026-03-30) — fixed-base matched-model weighted Jevons against the first complete collection week (base week 2026-03-30). Known limitations: week-over-week changes could reflect composition drift, and banners or cities onboarded after the base week never entered the series. The v1 series is frozen and remains available through the API with series=v1 for continuity.
  • v2 (2026-06-12): chained matched-model weighted Jevons with read-time normalization, in which every stored observation is re-normalized onto the canonical basis at compute time by a single versioned code path. v2 is the published series: it is computed from the full observation history, and its published history is floored to the July 2026 base (2026-06-01). The earlier March–June 2026 observations are retained under series=v1 as a pilot period and are not part of the headline series.
  • Category estimator revision (2026-08-10): the nine category sub-indices switched from the weekly chain to a direct fixed-base matched-model weighted Jevons against the week of 2026-06-01 (week ending 2026-06-07) = 100, after an institutional reader flagged on 2026-08-08 that the published category paths, weighted together, diverged materially from the headline over the same window. The divergence was driven by matched-set churn in small per-category samples, not by prices. The headline (all-items) series is unchanged; its rows were verified byte-identical through the revision. Category values previously published under the chain remain retrievable exactly as published through the point-in-time vintage archive (?asof= on /api/v1/index).

3.2 Effective-price selection

Within each retailer banner, each matched canonical basket item contributes its most recent observed effective price for the week — the sale price when the item is on sale, otherwise the regular price.

3.3 City and national aggregates

For the headline, city and national aggregates chain the basket-cost-weighted mean of the constituent links (not levels). Aggregating links rather than levels means newly onboarded banners and cities enter the panel cleanly and never distort the aggregate history. Category aggregates need no separate aggregation step: the direct estimator is evaluated over the relevant store cells (every cell for the national figure, one city's cells for a city figure, one banner cell for a banner figure), and a cell with no base-week data simply contributes no relatives.

3.4 Consumer-friendly secondary: basket cost

Alongside the index, we publish a per-banner basket cost in CAD: the sum, over matched items, of each item's most recent observed effective price (sale price when on sale, otherwise regular) within that banner that week. Because missing items deflate a basket total, cheapest-banner rankings are restricted to near-complete baskets (≥48/50 matched items). This figure has no index-number properties but is highly legible for general audiences and media partners.


4. Data quality protocol

4.1 Collection

Prices are collected from publicly accessible retailer search and product pages. For Loblaw banners (Loblaws, No Frills, Superstore, Wholesale Club) we parse the __NEXT_DATA__ payload embedded in the server-rendered HTML of store-locator-scoped search results. Analogous approaches are used for the other banners, with a Playwright fallback where sites require client-side rendering.

4.2 Three-tier matching

Each retailer SKU is matched to a canonical basket item via:

  1. UPC barcode match (where available from the retailer payload).
  2. Canonical specification match — product type, variant attributes (e.g. salted butter, whole-wheat bread), and package size within a ±10% tolerance band.
  3. TF-IDF fuzzy fallback over product title, used only when UPC and spec matching both fail. Fallback matches are logged for manual review.

Each matched item then contributes its most recent effective price (see §3.2). Verified wrong-product mappings are excluded via a maintained quarantine list (§4.3).

4.3 Normalization and filters (versioned, applied at compute time)

The published index is recomputed from the full observation history under the current, versioned normalization code. A single code path re-normalizes every stored observation onto the canonical basis at compute time:

  • Basis normalization — weight-priced observations are restated per kg onto the item's canonical basis; per-each prices that cannot be restated are rejected; per-item plausibility bands reject implausible values.
  • Mapping quarantine — verified wrong-product mappings are excluded via a maintained quarantine list.
  • Statistical outlier filter — any retailer-product whose weekly median sits outside [1/3, 3]× the cross-banner product median is excluded; the filter is evaluated only where a product-week has ≥8 observations across ≥3 banners.
  • Publication floor — a city × banner (× category) cell publishes only when ≥60% of its basket slice (and ≥2 items) is priced in both linked weeks.

A data-quality remediation shipped on 2026-06-12: per-each/per-kg basis normalization, French-locale price parsing, the wrong-product mapping quarantine, and sale-price capture on Empire banners. Because observations are append-only and the index is recomputed at read time, the corrected series incorporates the full history; the superseded v1 series remains available (§4.5).

4.4 Shrinkflation tracking

Package sizes are captured at each observation, and size changes are published as shrinkflation events only after persistence verification: the new size must hold for at least 2 subsequent weeks and the old size must never reappear on that product. Weigh-by-unit items (per-kg, per-head) are excluded. Not every detected size change is shrinkflation — transient listing errors and packaging variants are filtered out by the persistence gate. 125 events have been verified to date. Verified events let users decompose nominal price changes into (a) true price movement and (b) shrinkflation.

4.5 Revision and integrity policy

Price observations are append-only: once collected, an observation is never edited or deleted. The published index is recomputed from the full observation history under the current, versioned normalization code. When methodology or normalization changes, the change is dated and documented (see the §3.1 methodology change log and Appendix B), and the superseded series remains available — the v1 fixed-base series is frozen and served through the API with series=v1. Point-in-time vintages are part of the commercial feed, so subscribers can backtest against exactly the values that were published on any given date.

4.6 Accuracy verification (two-tier)

Accuracy is verified at two tiers:

  1. Automated re-scrape checks (weekly). A stratified sample is re-queried against the live retailer sites after each run. These confirm reproducibility and mapping liveness, but they re-run the same pipeline — they are not independent evidence of accuracy.
  2. Independent browser-based spot audits. A browser agent reads prices off the retailer page the way a human shopper would and compares them with stored values. This sample is still small (70 audits to date) and predates the 2026-06-12 remediation; results will be published on the methodology page as the stratified monthly program (target N ≥ 100) accumulates.

We deliberately do not publish a headline accuracy percentage until the independent audit sample is large enough to support one.


5. What the CGPI measures, and how it differs from official food CPI

The most important thing to understand about this dataset is what it is measuring.

The CGPI measures advertised prices: the posted shelf price a shopper sees online, for a fixed basket, every week. Official consumer price statistics measure transaction prices: what shoppers actually paid at the till, drawn largely from retailer scanner data, across a much broader basket, monthly.

These are different measurements of different things. Neither substitutes for the other, and there is no reason to expect them to move identically. An advertised-price series reflects posted promotions immediately and in full; a transaction-price series reflects what shoppers actually bought, including substitution toward whatever was discounted and the quantities involved.

Attribute GroceryPulse CGPI Official food CPI
What is measured Advertised price posted online (regular and promotional both captured) Transaction price paid at the till
Price source Public retailer listings, collected first-party Largely retailer scanner data, supplemented by field and web collection
Update cadence Weekly Monthly
Geographic granularity 13 cities x 22 banners National + 10 provinces
Formula Chained matched-model weighted Jevons (headline); direct fixed-base matched-model weighted Jevons vs the week of 2026-07-13 Modified Laspeyres
Basket transparency Full item list published Weights only
Price transparency Full per-observation panel (API) Not published
Basket size 50 items several hundred representative food products (list revised monthly)
Revision policy Append-only observations; dated, versioned recomputation; superseded series retained Infrequent, annual basket re-weighting
Status Private index published by GroceryPulse Official statistic

GroceryPulse complements official statistics. It is not a substitute for them, not a forecast of them, and not a measure of the same quantity. We make no claim of predictive power over official food CPI, and will not assert one unless and until a formal study supports it.


6. Use cases

6.1 Weekly food-price monitoring (macro / consumer research)

Grocery is one of the most closely watched components of household spending, but the advertised prices shoppers actually see are not published anywhere in a standardized, comparable weekly form. Typical workflow:

  1. Subscribe to the weekly CGPI feed.
  2. Track week-over-week movement in the national index and in the nine basket categories, and observe promotional cycles as they run rather than reconstructing them afterwards.
  3. Drill into the per-observation panel to see which banners and cities are driving a move, and whether it is a change in regular prices or in promotional depth.

6.2 Consumer-sector equity research

Analysts covering Loblaw Companies (L.TO), Empire Company (EMP.A.TO), Metro Inc. (MRU.TO), and George Weston (WN.TO) can track banner-level price competitiveness week by week. Specific signals:

  • Banner basket-cost divergence → pricing-strategy shifts.
  • Category-level markup expansion or compression.

6.3 Retail competitive intelligence

Independent and regional grocers without Nielsen/NielsenIQ subscriptions can benchmark their category pricing against the Big 3 in the cities where they operate. Typical deliverable: weekly category-level competitive dashboard.

6.4 Academic and policy research

Universities, policy think tanks, and government economic research units license the full historical panel for inflation-expectations research, pass-through studies, and regional-disparity analysis.


7. Known limitations

7.1 Online-list price

All prices are collected from retailer websites. In-store shelf prices can differ, particularly for weight-priced produce and meat where online prices are often indicative. We do not yet publish a quantified online/in-store gap; the independent browser audits (§4.6) measure our fidelity to the retailer page, not the page's fidelity to the shelf.

7.2 Walmart and Costco

Walmart Canada and Costco are not currently covered. Both employ aggressive anti-bot protection (PerimeterX and CAPTCHA-gated member-only listings respectively) that make automated collection unreliable. Walmart coverage is on the Q3 2026 roadmap pending a residential-proxy or data-licensing arrangement; Costco is unlikely to be feasible without a commercial partnership.

7.3 Basket size

A 50-item basket does not capture every movement in StatCan's much larger food basket (several hundred representative products, revised monthly). The preliminary 2026 overlap shows directional agreement with StatCan monthly food-CPI changes; the overlap is still far too short for formal correlation statistics (see §8).

7.4 No quality adjustment

When a product is reformulated or a brand replaces a variant, we observe the price change but do not adjust for quality differences. Shrinkflation (pack-size reduction) is tracked explicitly and persistence-verified (§4.4); other reformulations are not.

7.5 Partial banner coverage

Giant Tiger is a general merchandiser and stocks only part of the 50-item basket. Its cells publish only where they clear the §4.3 publication floor, and it is excluded from cheapest-banner rankings whenever it matches fewer than 48 of 50 items (§3.4).

7.6 Young independent-audit sample

The independent browser-audit sample (70 audits to date) is too small to support a headline accuracy figure and predates the 2026-06-12 remediation. See §4.6 for the publication plan.


8. Historical validation (preliminary)

A formal validation study will be published once the production record is long enough to support meaningful statistics. The weekly series begins 2026-03-30 and deepens every week; with only a handful of overlapping monthly prints to date, we deliberately do not publish correlation or magnitude figures yet. The 2026-06-12 methodology v2 cutover does not interrupt the series: v2 is computed from the full observation history, its published history is floored to the July 2026 base, and the superseded v1 series remains available for comparison (series=v1).

We do not publish correlation or magnitude figures against any official series, and we make no claim of agreement with one. The production record is currently too short to support such a claim, and because the CGPI measures advertised prices while official food statistics measure transaction prices at the till, agreement should not be assumed on theoretical grounds either.

Trial and subscription users receive the weekly index series and can run any comparison they wish against published official figures themselves.


9. Commercial access

9.1 Tiers

Tier Access Price (USD)
Research Free monthly CSV data pack (national / city / banner / category), published on a 14-day delay Free (attribution required)
Commercial API Full weekly index (national / city / banner / category), full per-observation panel, point-in-time vintages, all REST endpoints, no delay $2,500 / month ($30,000 / year)

Subscriptions are billed in USD; grocery values are reported in CAD.

9.2 Delivery

  • REST API (grocerypulse.ca/api/v1/…): JSON, OpenAPI 3.1 specification. The index endpoint accepts series=v2 (default; the published series) or series=v1 (frozen fixed-base series, retained for continuity); responses carry meta.series and meta.methodology.
  • Free data pack — monthly CSV bundle (national, per-city, per-banner, per-category), published on a 14-day delay, attribution required.
  • Point-in-time panel — Parquet dumps, monthly cut (commercial tier).

9.3 Licensing

Data is licensed for internal research use. Redistribution and sub-licensing require written consent. Attribution required in published research: "Source: GroceryPulse Canadian Grocery Price Index. Research led by Sung Ha Hwang, Co-founder and Research Director."

9.4 Trial

A 14-day evaluation license is available on request. Contact hello@grocerypulse.ca.


Appendix A — Full basket

See /methodology on grocerypulse.ca for the full live basket with weights and match criteria. The basket is held constant within each reporting year; annual re-weighting occurs each January.

Appendix B — Change log

  • 1.3 (2026-08-10): Category sub-index estimator revised. The nine category series are now a direct fixed-base matched-model weighted Jevons against the week of 2026-06-01 (= 100), replacing the weekly chain, whose small per-category matched sets had accumulated composition error (flagged by an institutional reader on 2026-08-08). The restated series was published the same day, following an audit of base-week data quality. The headline (all-items) series is unchanged and was verified byte-identical through the revision. Category levels now share a common base and are comparable with each other; headline city and banner levels remain rebased in each series' own entry week and remain not comparable across series. Superseded category values remain retrievable as published via the point-in-time vintage archive (?asof= on /api/v1/index). The v2 history note in §3.1 aligned across whitepaper copies: computed from the full observation history, published history floored to the July 2026 base.
  • 1.2 (2026-06-12) — Methodology v2 cutover: the published series is now a chained matched-model weighted Jevons with read-time normalization; the v1 fixed-base series (base week 2026-03-30) is frozen and remains available via series=v1. Coverage corrected to 22 active banners (six retailer families, roughly 160 active stores). Revision policy restated as append-only observations with dated, versioned recomputation — an earlier "never revised" claim was inaccurate and has been removed. Accuracy claims replaced by the two-tier verification program (§4.6). Data-quality remediation disclosed: per-each/per-kg basis normalization, French-locale parsing, wrong-product mapping quarantine, Empire sale-price capture. Shrinkflation feed reinstated as a persistence-verified event feed (125 verified events to date).
  • 1.1 (2026-06-11) — Cadence corrected to weekly. Commercial pricing published (US$2,500 / month or US$30,000 / year, 14-day trial). Validation section rewritten to defer correlation statistics until the StatCan overlap supports them. Shrinkflation event feed temporarily removed from commercial deliverables while the detector matured.
  • 1.0 (2026-04-20) — First public release. Commercial API announced.

GroceryPulse is an independent research publisher. The CGPI is not endorsed by, affiliated with, or sponsored by Statistics Canada, the Bank of Canada, or any retailer listed in this document.

Evaluate the data

14-day trial available on request. Sample CSV and API credentials delivered within one business day.

Request trial → sales@grocerypulse.ca

We use cookies for analytics to improve your experience. Privacy Policy