Blog
How does a free scan choose the platform it shows?
· WebVitalist
WebVitalist chooses the platform on a free scan from the HTML and response headers of that fetch. This note is dated October 22, 2026 and states the rule the scan page uses.
How a match is scored
The guess runs only after a fetch completes. It reads the HTML, the response headers, and the final URL after redirects. Only the first 400,000 characters of the HTML are searched. The headers are searched in full, each as a name: value line. None of the signals that ship read the final URL.
Each signal has a name, a kind, and a weight. The kinds are ecommerce, cms, framework, and hosting. A match adds that signal’s weight to its name inside its kind. The same name can match more than once, and those weights add. Shopify can match in the HTML and in the headers, at weight 3 each. Wix can do the same as a CMS.
Inside one kind, the name with the highest score is kept. When two names in the same kind end on the same score, the one that appears earlier in the signal list is kept. A later name replaces it only when its score is strictly higher. When WordPress and Webflow both match at weight 3, the CMS kept is WordPress.
Three ecommerce names imply a CMS, and only when no CMS matched. WooCommerce implies WordPress. Wix Stores implies Wix. Squarespace Commerce implies Squarespace. The implied CMS receives the ecommerce score. A CMS signal, even a lower one, is kept. When WooCommerce and Duda both match, the CMS stays Duda, and the label is Duda (WooCommerce).
Confidence uses the highest of the ecommerce, CMS, and framework scores after any implication. Hosting is not part of that maximum. A score of 3 or more is high. A score of 1.5 or more is medium. Otherwise the confidence is low. HTML that contains cdn.shopify.com and no other signal is Shopify, and the confidence is high. HTML that contains woocommerce and no CMS signal is labeled WordPress (WooCommerce), and the confidence is high, because the implied WordPress score is 3. A Remix match at weight 2 is medium. A Vue match at weight 1 is low. A Cloudflare header alone is low, because hosting is excluded from the maximum.
The signals, in the order a tie uses, are:
- Shopify, ecommerce, HTML, weight 3
- Shopify, ecommerce, headers, weight 3
- WooCommerce, ecommerce, HTML, weight 3
- Magento, ecommerce, HTML, weight 3
- BigCommerce, ecommerce, HTML, weight 3
- PrestaShop, ecommerce, HTML, weight 3
- Squarespace Commerce, ecommerce, HTML, weight 2
- Wix Stores, ecommerce, HTML, weight 2
- WordPress, cms, HTML, weight 3
- Webflow, cms, HTML, weight 3
- Wix, cms, HTML, weight 3
- Wix, cms, headers, weight 3
- Squarespace, cms, HTML, weight 3
- Framer, cms, HTML, weight 3
- HubSpot CMS, cms, HTML, weight 2
- Ghost, cms, HTML, weight 3
- Drupal, cms, HTML, weight 3
- Joomla, cms, HTML, weight 3
- Craft CMS, cms, headers, weight 3
- Duda, cms, HTML, weight 2
- Carrd, cms, HTML, weight 2
- Notion, cms, HTML, weight 1
- Next.js, framework, HTML, weight 3
- Nuxt, framework, HTML, weight 3
- SvelteKit, framework, HTML, weight 3
- Astro, framework, HTML, weight 3
- Gatsby, framework, HTML, weight 3
- Remix, framework, HTML, weight 2
- Angular, framework, HTML, weight 2
- Vue, framework, HTML, weight 1
- React, framework, HTML, weight 1
- Hugo, framework, HTML, weight 3
- Jekyll, framework, HTML, weight 3
- Laravel, framework, headers, weight 2
- Ruby on Rails, framework, HTML, weight 1
- Cloudflare, hosting, headers, weight 1
- Vercel, hosting, headers, weight 2
- Netlify, hosting, headers, weight 2
- WP Engine, hosting, headers, weight 2
- Kinsta, hosting, headers, weight 2
- GitHub Pages, hosting, headers, weight 2
- AWS, hosting, headers, weight 1
- Fastly, hosting, headers, weight 1
- Nginx, hosting, headers, weight 0.5
- Apache, hosting, headers, weight 0.5
A Shopify marker that begins only after 400,000 characters is ignored. Each match stores the signal name and the first 60 characters of the matched text. A generator meta tag, when one is present, is listed first. Duplicate evidence lines are removed. At most 12 evidence lines are stored. A WordPress theme slug, or a Shopify theme name, is stored when the HTML contains it. The scan badge does not show the evidence or the theme.
What the scan shows
The scan result shows chips for ecommerce, then CMS, then framework. A name that already appeared is not repeated. The badge title, when those chips exist, is Confidence: followed by high, medium, or low. When none of those three is set, the badge text is Unknown platform, and that badge does not add a confidence title. Hosting alone, such as Cloudflare, still takes that path.
A separate short label is used on the social card for a scan permalink. If both ecommerce and CMS are set and they differ, the label is the CMS, then the ecommerce in parentheses, as in WordPress (WooCommerce). Otherwise the label uses ecommerce, then CMS, then framework. When all three are empty and hosting is set, the label is Custom site on that host, as in Custom site on Cloudflare. When a framework is set and the main name is a different one, the label joins them with a middle dot. When the main name is the framework, hosting is not added. HTML that contains __NEXT_DATA__ and a Vercel header is stored as Next.js on the framework and Vercel on hosting. The label is Next.js. The social card prints that label and shortens it to 28 characters. When the label is longer, it keeps 27 characters and ends with an ellipsis.
What the guess does not change
The platform is stored beside the technical result. It is not one of the weighted checks, and it does not change the integer score. The guess reads the fetched HTML and headers. It does not open a browser, so markup that appears only after client-side rendering is not a signal unless that markup was already in the fetched HTML. A fetch that fails is stored without a platform. Showing a completed scan again uses the platform stored on that row.