Methodology

MaplePolls is a rolling aggregate of every Canadian political poll we can responsibly verify. This page is the long-form explanation of how a poll becomes a row in our table, how we average them, what we throw out, and where the limits are. It is written for readers who want to check our work — every claim here is reproducible against the code and the source registry.

1. What MaplePolls is

MaplePolls aggregates publicly published Canadian polling — we are an aggregator, not a pollster. We do not field surveys; we read other firms' releases, store the headline vote-intention numbers, and average them. The site covers the federal jurisdiction plus every province and is published in English and French. The team is anonymous: we are individual Canadians who built and run the site in our spare time, and we keep our names off the page so the focus stays on the data and the sources behind it.

2. How polls are collected

A scheduled pipeline pulls each pollster's index every few hours. The fetcher uses whatever access method the pollster makes available — an RSS feed where one exists, an HTML scrape of the press-release page where it doesn't, and pdftotext extraction of the linked public PDF where a pollster (like Nanos or Mainstreet) publishes the numerical tables only inside a PDF. For each article a scheduled extractor reads the relevant text — plus the PDF body when one is available — and returns a structured object: jurisdiction, field dates, sample size, margin of error, and party shares. The extractor does not invent numbers; it pulls them out of the article or PDF. Every poll row in our table carries a `source_url` link to the article it came from, so any number we publish can be cross-checked against the pollster's original release. For pollsters whose own pages publish numbers only as chart images (currently EKOS and Ipsos), we fall back to the community-maintained Wikipedia election-page mirror, which transcribes the same releases into structured tables.

3. What gets rejected

Every extraction passes through a validator before it can land in our database. A poll is rejected when its named-party shares do not sum to between 70 % and 115 % — the low end allows for an Other or Undecided share that we leave unmapped, the high end catches duplicate or mis-extracted rows. A poll is rejected when its field-end date is older than one year (a stale comparison reference, not the real fieldwork) or more than seven days in the future (a misread publication date). Party identifiers that don't match a canonical code for that jurisdiction are dropped, never guessed — a label we don't know becomes no row, not a row attributed to a party. The extractor is explicitly forbidden from deriving a number from a delta: a phrase like "the PCs are down 13 points" is not a number, and we will not subtract from a prior week to fabricate one. A poll's jurisdiction is the population it actually sampled, not every horse-race question it asked: a BC provincial survey's federal cross-question is a Quebec subsample of the federal vote, not a federal poll, and is logged-then-skipped rather than averaged in. When a pollster publishes the same vote-intention question on multiple bases — all respondents, decided + leaners, decided only — we take the decided-voters basis. Decided + leaners is the fallback when no decided-only table exists; all-respondents is used only when it is the only table published. Standardising on decided is what keeps direct-scraped rows comparable with the Wikipedia mirror rows and with the broader cross-pollster average.

4. The rolling average

The published share for each party is a weighted average over the trailing 28 days. Before a poll enters the average, its party shares are proportionally renormalized to sum to 100 % across the parties it lists (effective July 8, 2026), so a pollster that breaks out an “other/undecided” bucket is compared on the same basis as one whose numbers already total 100 %. Each poll's weight is the square root of its sample size multiplied by an exponential decay term with a 14-day half-life: a one-week-old poll counts roughly 60 % as much as a brand-new one, a two-week-old poll about 37 %. The "±N aggregate margin" label is not any single pollster's margin of error; it is computed from the Kish effective sample size of the weighted pool and gives a rough sense of how tight the average is given how many recent polls support it. The "as of {date}" line shows the field-end of the most recent poll in the average, not the timestamp of the last refresh — so on a week when no new polls are published, the line honestly reads through the most recent input rather than implying fresh data arrived.

5. Margin of error

We show the pollster's reported margin of error verbatim. When the pollster doesn't state one — some online-panel surveys decline to compute a classical MoE on principle — the cell is left blank. We do not derive a margin of error from the sample size, because most modern Canadian polls aren't simple random samples and the textbook 1/√n approximation would misrepresent their precision. A blank MoE column on our polls table means "this pollster didn't state one," not "we don't know."

6. Sources

Every pollster we read, the access method we use, and the current ingestion status. This list is a snapshot of the registry in SOURCES.md at the repository root; the source of truth lives there.

PollsterAccessStatus
Abacus DataRSSIntermittent fetch issues — our collector has had recent difficulty reading this source
Nanos ResearchRSS + CTV mirrorIntermittent fetch issues — our collector has had recent difficulty reading this source
Liaison StrategiesHTML scrapeActive
Research Co.RSSActive
LégerRSSIntermittent fetch issues — our collector has had recent difficulty reading this source
Angus Reid InstituteRSSActive
EKOS PoliticsWikipedia mirror + RSSCovered via Wikipedia mirror
IpsosWikipedia mirror + RSSCovered via Wikipedia mirror
Mainstreet ResearchHTML + PDF extractionActive
Pallas DataRSSActive
Spark InsightsHTML scrapeIntermittent fetch issues — our collector has had recent difficulty reading this source
Innovative ResearchRSSActive
PollaraRSSActive
Forum Research(unconfigured)Not configured
Campaign Research(unconfigured)Not configured

Status is derived live from scrape_log over a 14-day window. The Access column is static configuration: the protocol we use to read each pollster.

7. Corrections

When we find a bad row — a fabricated number, a mis-classified jurisdiction, a wrong basis — we delete it and write a migration that records why. The deletion is logged internally; material corrections (anything that moves a published average) are noted in the weekly digest so the change is visible to the readers who follow the average over time. The repository is private; the migration history is not yet public. If you spot something that looks wrong, the feedback form in section 8 is the fastest way to flag it.

See the live corrections log and weekly audit on our data-integrity page →

8. Contact

Methodology questions, corrections, missing pollsters, mistranslations, accessibility issues — all of them land in the same inbox. Open the feedback form below and the message comes straight to the author.

Open the feedback form ↗

MaplePolls is independent and non-partisan. Party and pollster names are trademarks of their respective owners, used for identification and news reporting only.

Keep MaplePolls free and independent
Your support keeps the data flowing, the analysis sharp, and the ads away.
Support on Patreon
Get the numbers every Saturday
Federal standings, poll-by-poll breakdowns, and AI analysis — free in your inbox.
Newsletter language
© MaplePolls 2026 — Data from Canadian pollsters
Not affiliated with any political party
MaplePolls is independent and non-partisan. Party and pollster names are trademarks of their respective owners, used for identification and news reporting only.
5469446 · 2026-07-19