Inspiration
Many Canadians want to buy Canadian products, but it's hard to do in practice. A maple leaf on the box doesn't tell you who owns the company, and "Product of Canada" is a entirely different claim from "Made in Canada".
According to the Canadian Federation of Independent Business, when consumers spend in small Canadian retail businesses, 66 cents of every dollar stays. This is vastly better than the 8 cents metric when consumers buy from online giants. This is the local multiplier effect.
With gas stuck at $180 and groceries 27% higher than five years ago, Canadians are being asked to pay more and care more at the same time.
Buying Canadian means reinvestments in your community, money that comes back to you. But that is not in the best interest of the corporations.
It is no coincidence that labels on where products are source are kept vague with statements like “Made in Canada” or “Product of Canada”. This makes buying Canadian convoluted and tedious.
We strive to find a more transparent method for consumers to understand what they are buying, while not sacrificing convenience so instead of another site to remember, NorthBound works along side you in your everyday online shopping.
A tool that confidently says "this is Canadian" when it's wrong is worse than no tool at all, so NorthBound was built to say "we don't know" whenever the evidence isn't there.
What it does
We wanted a tool that shows the Canadian option right at the moment you're browsing. NorthBound is a tool that displays high-quality, fact checked products that are Canadian equivalents.
When you shop on Amazon.ca, Indigo, Canadian Tire, Well.ca, Simons, Lee Valley or Shopify stores, it shows Canadian alternatives right on the page:
- Product pages: a small panel shows who really owns the brand, and Canadian alternatives with links and prices.
- Search results: if you search "cheddar crackers", it suggests Canadian brands before you've picked one, when changing your mind is easiest.
"Canadian" isn't treated as a yes/no answer. Each brand is judged on four separate questions: Canadian-owned, Canadian-founded, headquartered in Canada, made in Canada. Each one can independently be "unknown". Every claim links to its source.
In more niche cases where we didn't have previously human-confirmed data, we utilized AI to provide our best suggestion(s). Results are ranked by a fixed, transparent formula: similarity, how Canadian it is, and price. Sliders let you re-weight these parameters instantly.
Alas, when we can't find a trustworthy Canadian alternative, the panel stays hidden. The popup then explains why: no alternative exists, the listing didn't have enough information, or the AI's suggestions failed verification.
How we built it
- Extension (TypeScript, Chrome Manifest V3): the extension reads product details from each page in order of reliability: structured product data first (JSON-LD, microdata, OpenGraph), then site-specific code for Amazon and Shopify. The panel is drawn inside a Shadow DOM so store stylesheets can't break it. The extension never calls the API itself: all lookups go through its background worker, so the store page can't see that traffic.
- API (Node, Express, Zod): one lookup pipeline. It finds the brand, checks ownership, searches for alternatives, scores and ranks them, and decides whether to say nothing.
- Data (Tiger Cloud / TimescaleDB Postgres): 1,404 Canadian brands, 1,250 US brands and 2,431 curated US → Canadian brand pairings. Brand names are matched with strict fuzzy matching (
pg_trgm, similarity ≥ 0.6), so "Starbucks Coffee" is treated as unknown rather than linked to the wrong company. Search pages use full-text search. - AI (Gemini API):
- turning messy listing titles into structured product details
- suggesting Canadian brands when the curated database has nothing
- a yes/no check that rejects mismatches, like conditioner offered for shampoo
- Hallucination firewall: every AI suggestion has to pass checks before it's shown. It must cite a source, can't link to a made-up domain, must use HTTPS, must point to a live page, and the facts are re-read from the store's own page. Ownership never comes from the model: it's always checked against the curated database.
- A second database for AI results: AI suggestions that pass every check are saved in a separate schema (
ai_fallback) for 30 days. Repeat lookups are then fast and cost nothing, and the curated tables stay read-only. - Store searches run in the browser: stores block server traffic, so the server sends the AI's suggestions back to the extension. The extension searches the stores from your own browser, and the server saves only results that answer a suggestion it actually made.
- Retailer fallback: for things like electronics, where no Canadian product exists, we suggest buying the same item from a Canadian-owned store.
Challenges we ran into
- AI that makes things up. Early AI suggestions included brands that don't exist and links to search pages instead of products. The answer was a set of checks the AI can't get around, with automated tests for each one.
- Fake data leaking into real results. Our placeholder AI, used for testing, suggested Green Beaver deodorant for everything: sprinkles, hoodies, air fryers. Those suggestions got saved to the shared database and kept coming back. We stopped saving placeholder results there and made the code ignore them once a real AI is configured.
- The AI check rejecting good answers. Our database matches brand to brand, so the AI was asked things like "is Dare Foods a substitute for Goldfish crackers?" It kept answering that it couldn't tell, because that's a brand, not a product, and rejected almost everything. Telling the AI when it's judging a whole brand fixed this, and it still correctly rejects a tortilla-chip company as a cracker substitute.
- Saved results attached to the wrong products. Saved AI results were reused for any product from the same brand in the same broad category, so iOGO yogurt and Kawartha ice cream ended up with unrelated suggestions. Now a saved result is only reused when the product title closely matches.
- Small CSS rules that broke everything. One CSS rule written in the wrong order silently undid the panel's positioning. It still drew, but at the bottom of the page where nobody saw it.
Accomplishments that we're proud of
- Having a final version that we could actually use in our day-to-day lives
- The product grows as people use it more by having a separate dataset with newly found AI matches for products, then being checked by real humans, ultimately growing the verified dataset
- Sliding the weights re-ranks results instantly in the browser, and the same inputs always give the same order
- 88 automated tests, covering every AI check, scoring edge cases and the saved-results logic
- A real dataset of more than 2,400 curated brand pairings, live on Tiger Cloud.
- A goose in a shopping basket (cute UI)
What we learned
- Various new technologies including Tiger Cloud, Gemini API, etc
- Learning how Chrome Extensions work, how databases connect to extensions
- Saved results are shared state: when the rule for reusing them is too loose, the bad results get reused too
- Data-analysis: Learning more about how we use code to interpret data from sets
What's next for NorthBound
- Product-level matches: More specific matches for certain non-food related categories
- Better categories: Our limited number of categories are too broad if we want it to be a published product (yogurt and ice cream ended up as "condiments"), which hurts matching results
- Speed: New lookups take 20–30 seconds because of the AI calls. We plan to look into maximizing efficiency
- More stores, and more: Walmart, Loblaws/PC Express, Sobeys and Firefox, plus a French interface.
Built With
- express.js
- gemini-api
- node.js
- python
- tiger-data
- typescript
