This document describes how the extension collects storefront signals and how those signals are used to drive the evaluation model.
Signals are collected from two sources:
- Content script (
content.js) — DOM and page markup signals, collected in the active tab - Background script (
background.js) — Text-based merchandising signals, derived from page content
Both sources feed into the evaluation pipeline: scorecards, patterns, findings, and confidence scoring.
Collected by detectSignals() in content.js. The script builds a single searchable string (haystack) from:
document.title,document.body.innerText,document.documentElement.innerText- All
<script>and<script type="application/ld+json">text content - All
<script src="...">URLs - Full
document.documentElement.outerHTML
Each signal category is detected by running regex patterns against this haystack.
| Signal | Detection method |
|---|---|
| Loyalty | Regex for vendor domains/identifiers: LoyaltyLion, Smile.io, Yotpo, Stamped, Okendo, Loyalty Genie |
| Quizzes | Regex for: Octane AI, Typeform, Jebbit, Interact, RevenueHunt, Prehook |
| Wishlists | Regex for: Swym, Wishlist Plus, generic "wishlist" / "add to wishlist" |
| Reviews | Regex for: Yotpo, Judge.me, Okendo, Stamped, Loox, Trustpilot, Reviews.io |
| Signal | Detection method |
|---|---|
| Pixels | Script/URL patterns for Meta (fbq, connect.facebook.net), Google (gtag, googletagmanager.com), TikTok (ttq, analytics.tiktok.com), Pinterest (pintrk, ct.pinterest.com), Snapchat (snaptr, sc-static.net), Klaviyo onsite |
| Affiliates | Regex for: Impact, ShareASale, CJ Affiliate, Rakuten, Refersion, Grin, Aspire |
| Signal | Detection method |
|---|---|
| ESPs | Regex for: Klaviyo, Mailchimp, Omnisend, Drip, ActiveCampaign, Sendlane, Postscript |
| SMS | Regex for: Attentive, Postscript, SMSBump, Yotpo SMS |
| Popups | Regex for: Justuno, Privy, Popupsmart, Wheelio, Spin-a-Sale, Wisepops, Optimonk |
Detected via regex on the haystack:
- Dollar thresholds:
free shipping over $X,spend $X for free shipping, etc. (valid range: $0–$1000) - Item thresholds:
free shipping on N+ items,buy N+ items for free shipping(valid range: 2–50 items) - Unconditional:
free shipping on all orders,always free shipping,free shipping on every order
Collected by fetchTextSignals() in background.js. Runs regex against the page content string (passed from the content script).
| Signal | Pattern (simplified) |
|---|---|
| bundles | bundle, build your bundle, mix and match, kit |
| subscriptions | subscribe & save, subscription, delivery every, autoship |
| upsells | frequently bought together, pair with, complete the look, you may also like |
| urgency | limited time, selling fast, low stock, ends tonight, while supplies last |
| installmentMessaging | afterpay, klarna, affirm, shop pay installments, sezzle |
| samples | sample pack, trial size, starter kit |
| gifting | gift card, gift guide, gift set |
These are boolean flags; the function returns true if any match is found.
summarizeSignals() aggregates counts for scoring:
- totalDetections — Sum of all detected tools/offers
- reviewCoverage — Number of review platforms
- retentionCoverage — Loyalty + ESPs + SMS
- acquisitionCoverage — Pixels + affiliates
- personalizationCoverage — Quizzes + wishlists
- onsiteConversionCoverage — Popups + shipping offers
buildStoreTheme() uses signals to infer traits:
- retention-led — Any loyalty, ESP, or SMS detected
- offer-led — Text signals for subscriptions or bundles
buildPatterns() maps signals to merchandising patterns:
| Pattern | Source |
|---|---|
| Bundle merchandising | textSignals.bundles |
| Subscription motion | textSignals.subscriptions |
| Cross-sell pattern | textSignals.upsells |
| Urgency cues | textSignals.urgency |
| Installment messaging | textSignals.installmentMessaging |
| Guided selling | signals.personalization.quizzes |
| Social proof | signals.personalization.reviews |
| Lead capture | signals.emailSms.popups |
Signals contribute to experience, growth, and confidence scores:
- Experience score — Review coverage, personalization coverage, upsells, bundles, shipping, installment messaging
- Growth score — Acquisition coverage, retention coverage, onsite conversion coverage, subscriptions, urgency
- Confidence score — Increases with
totalDetections(capped contribution)
Signals drive strengths, gaps, and opportunities:
- Reviews — Presence = strength; absence = gap + “Strengthen social proof” opportunity
- Email/SMS — Presence = strength; absence = gap + “Improve owned-channel capture” opportunity
- Upsells — Absence + low variant depth = “Add cross-sell surfaces” opportunity
- Bundles — Absence + large catalog (non-premium) = “Test bundles or kits” opportunity
┌─────────────────────────────────────────────────────────────────┐
│ Content Script (content.js) │
│ - collectPageData() │
│ - detectSignals() → personalization, channels, emailSms, │
│ shippingOffers │
│ - pageContent (text) │
└────────────────────────────┬────────────────────────────────────┘
│ chrome.runtime.sendMessage
▼
┌─────────────────────────────────────────────────────────────────┐
│ Background Script (background.js) │
│ - handleScan() │
│ - fetchTextSignals(pageContent) → bundles, subscriptions, etc. │
│ - buildEvaluation(metrics, signals, ..., pageContent) │
│ - summarizeSignals(), buildPatterns(), buildScorecards(), │
│ buildFindings(), buildConfidence() │
└─────────────────────────────────────────────────────────────────┘
- Heuristic, not authoritative — Detection relies on string matching; tools may be present but not detected (e.g., custom domains, minified code).
- Single-page snapshot — Signals come from the page where the scan was initiated; tools on other pages (e.g., checkout) are not captured.
- No runtime verification — Scripts may be loaded but not active; we only detect presence in markup/text.
- Text signals are broad — Phrases like “bundle” or “subscription” can match marketing copy even when no actual bundle/subscription feature exists.