Sourcemap Explorer
Guide

How to identify the CMS behind any website

Most CMSes auto-generate a `<meta name="generator">` tag, load assets from predictable paths, and set cookies with recognisable prefixes. Four checks (generator, paths, headers, cookies) are usually enough; a fifth check (sourcemap-aware extension) handles the headless cases where the visible frontend is React or Vue and the CMS lives behind an API.

By Mapree ·

5 min readChrome DevTools, Sourcemap Explorer extension

Background

Every mainstream CMS leaves fingerprints a casual observer can spot in under a minute. WordPress serves `/wp-content/` and `/wp-includes/` assets, generates a `<meta name="generator" content="WordPress 6.x">` tag by default, sets `wordpress_*` and `wp-settings-*` cookies for logged-in users, and exposes `/wp-json/` if the REST API is unlocked. Drupal uses `/sites/default/files/` and `/modules/<name>/`, sets `X-Drupal-Cache` and `X-Generator: Drupal N` headers, and generates a generator meta tag too. Shopify loads from `cdn.shopify.com`, exposes `window.Shopify` as a runtime global, and sets `_shopify_y`, `_shopify_s` and `cart` cookies. Magento serves `/pub/static/` paths, generates `X-Magento-*` headers and `frontend=` session cookies. Ghost has `<meta name="generator" content="Ghost ...">` by default and serves assets from `/ghost/assets/`. Webflow tags the `<html>` root with `data-wf-page` and `data-wf-site`. Squarespace sets `Sqsp-*` cookies, loads from `static1.squarespace.com`, and includes `<meta name="generator" content="Squarespace">`.

The fingerprints survive theming and customization because they are structural to how each CMS renders pages. A site can rename a theme directory, customize a layout, strip a generator tag — but the underlying URL paths, header surface and cookie namespaces are baked into the CMS's request-handling code and would require forking the CMS to fully erase. A four-check sweep — generator meta, asset URL paths, response headers, cookies — is enough for 90% of sites and takes under a minute. The remaining 10% are usually headless setups where the CMS lives behind an API and the visible frontend is a JavaScript framework, which calls for a different approach: identify the framework first, then look at the API requests it makes, then trace those back to the underlying CMS.

This last category — headless WordPress, headless Drupal, Sanity-backed Next.js, Contentful-backed Astro, Storyblok-backed Nuxt — is increasingly common in 2025/2026 builds, and the standard CMS-detection workflow misses them entirely if you stop at 'no `<meta name="generator">`, no `/wp-content/`, must be custom'. Sourcemap Explorer's extension reads the JavaScript dependency tree and surfaces CMS SDKs (`@sanity/client`, `contentful`, `@storyblok/react`, `@hashicorp/react-cms`) directly from the bundle, which lets you identify the CMS even when the rendered HTML carries none of the traditional fingerprints. That last layer of detection is what closes the loop on modern sites.

Why this matters

CMS identification is the foundation of most frontend audits of content-heavy sites. Knowing it's Shopify tells you the checkout architecture, the theming system (Liquid + Online Store 2.0), the app/plugin model, the payment stack (Shopify Payments + Stripe under the hood, or a third-party gateway). Knowing it's WordPress tells you to look for plugins and a theme — and that the entire `wp-admin` surface is in play if you have credentials. Knowing it's Webflow tells you there's no PHP or server-side component to audit at all because Webflow renders to static HTML, which simplifies some questions and makes others (custom code injection, reverse-engineering the page builder's logic) harder.

For security work the CMS is usually the most informative single axis. WordPress and Magento sites need plugin/extension audits because most CVEs hit the extension layer rather than the core. Shopify sites need an app review (Shopify apps run with a lot of trust). Drupal sites need a contrib-module audit. Custom-CMS sites need a different security model entirely. Knowing the CMS in the first thirty seconds tells you which threat model applies and saves you from going down the wrong path.

For content and SEO work the CMS dictates how URLs are structured, how metadata is generated, how images are served, how schema.org markup is injected. WordPress sites with Yoast or Rank Math have a specific SEO surface; Webflow and Squarespace have their own; headless setups depend entirely on the framework's metadata library (Next.js's `metadata` exports, Astro's `<MetaTags>` patterns). Recognising the CMS lets you give relevant advice instead of generic advice.

For partnerships and integrations work the CMS tells you which marketplace your integration belongs in, which authentication flow applies, and how the buyer reasons about your product. A 'Shopify app' and a 'WordPress plugin' are different products with different distribution, pricing and trust models even when they do conceptually the same thing.

Prerequisites

  • Chrome DevTools — the workflow uses View Source, the Network tab and the Application tab (for cookies). All are built into any Chromium browser.
  • Optional: Sourcemap Explorer installed, which surfaces CMS detection plus theme/plugin/app-level breakdown directly in the popup, including for headless setups where traditional fingerprints are absent.
  • Optional: a working knowledge of common CMS architectures (WordPress's plugin model, Shopify's Liquid + Online Store 2.0, Drupal's modules, Magento 2's frontend stack). Useful for interpreting what you find but not strictly required.
  • Optional: `curl` for header-only probes when DevTools is not available — `curl -I https://<site>/` returns just the response headers in two seconds.

Step-by-step

  1. 1

    Read the generator meta tag

    Press `Ctrl+U` to open the page source, then `Ctrl+F` for `<meta name="generator"`. WordPress sets it to `WordPress 6.x` by default. Drupal sets it to `Drupal N (https://www.drupal.org)`. Ghost, Hugo, Jekyll, Sitecore, Typo3, Squarespace, Joomla, Contao and many others do too. The generator tag is the easiest single signal and is present on most sites whose admins did not specifically remove it. When it is there, you have your answer in three seconds; when it is not, move on to the next step rather than concluding 'this is not a CMS'.

  2. 2

    Look at asset URL paths

    Open the Network tab, reload, and scan the URL column. `/wp-content/` → WordPress (the `/wp-includes/` companion path is also a tell). `/sites/default/files/` and `/themes/<name>/` → Drupal. `cdn.shopify.com` → Shopify. `/pub/static/version<n>/` and `/assets/themes/` → Magento. `/_next/static/` → Next.js (which tells you the frontend; the CMS, if any, lives behind it). `/prod/js/webflow/` plus `<html data-wf-page>` → Webflow. `/ghost/assets/` → Ghost. `static1.squarespace.com` → Squarespace. `cdn.contentful.com` or `cdn.sanity.io` references → headless setup with the named CMS as the backend.

    Tip: Sites behind a CDN sometimes rewrite asset paths (`/static/<hash>/` instead of `/wp-content/<hash>/`). Check the Server header (Nginx vs Apache vs LiteSpeed) and the original asset URLs in the page source as a cross-check.

  3. 3

    Check response headers on the document request

    Click the very first Network entry (the document HTML), open the Headers panel, and read down the response headers. `X-Drupal-Cache: HIT` and `X-Generator: Drupal N` → Drupal. `X-Shopify-Stage: production` and `X-Sorting-Hat-PodId` → Shopify. `X-Pingback` and a `Link: <...>; rel="https://api.w.org/"` header → WordPress. `X-Magento-Cache-Debug` and `X-Magento-Vary` → Magento. `X-Powered-By: TYPO3 CMS` → TYPO3. `X-Powered-By: Express` → not a traditional CMS, almost always Node.js with a custom framework. Server-generated headers are hard to forge and persist even when the generator meta is stripped.

  4. 4

    Inspect the cookies

    Open DevTools → Application → Cookies → click your domain. Cookie names give the CMS away. `wordpress_*`, `wp-settings-*`, `wp_*` → WordPress. `_shopify_*`, `cart`, `cart_currency`, `cart_sig` → Shopify. `Drupal.toolbar.*`, `SESS<hash>` → Drupal. `frontend=`, `X-Magento-Vary` cookie partner → Magento. `ghost-members-ssr` and `ghost-members-ssr.sig` → Ghost. `Sqsp-*` → Squarespace. `__Secure-3PSID` and Google Cloud-typical headers → could be Firebase Hosting or Google Cloud Run, not a CMS but a hosting signal.

  5. 5

    Probe for the admin or API route

    Try the standard admin URLs: `/wp-admin/`, `/admin/`, `/sites/default/files/.htaccess`, `/typo3/`, `/customer-login`, `/users/login`. The redirect or 401 response often reveals the CMS even when the front of the site does not. Also try the standard API routes: `/wp-json/wp/v2/posts`, `/api/v1/sites`, `/api/_v3/json`, `/_v3/admin/`. A WordPress REST API response leaks `X-WP-*` headers and a `wp/v2/` URL structure that is unmistakeable.

    Tip: Hardened WordPress sites lock `/wp-admin/` behind two-factor or strip the route entirely. The `/wp-json/` endpoint is harder to disable because some plugins depend on it; if you get a JSON response there with `wp/v2/` in the URL, you have your CMS even without admin access.

  6. 6

    Run Sourcemap Explorer for CMS + plugin-level detail

    The extension identifies the CMS in the popup's Stack tab plus — for WordPress specifically — every plugin and theme loading assets on the page (Elementor, WooCommerce, Yoast, Rank Math, Astra and so on, by slug). For e-commerce CMSes it detects the payment, checkout and analytics stack. For headless setups it surfaces the CMS SDK from the bundle (`@sanity/client`, `contentful`, `@storyblok/react`, `@payload/<sdk>`) which is the only way to identify the CMS when the visible frontend is React/Vue/Svelte and the traditional fingerprints are absent.

  7. 7

    Cross-check with the page's structured data

    Many CMSes inject `<script type="application/ld+json">` blocks with `@type` references that telegraph the CMS or its e-commerce shape. WooCommerce sites emit `Product` schema with `Offer.url` pointing at `/?add-to-cart=`; Shopify emits `BreadcrumbList` and `Product` schema with `cdn.shopify.com` image URLs; Squarespace embeds its own template-name in `WebPage.publisher`. Search the page source for `application/ld+json` and read the JSON.

Real-world example

Alternative methods

Use a public CMS detector

Wappalyzer, BuiltWith, Whatcms.org all read the same fingerprints and return the CMS name. They generally do not surface plugin-level or theme-level detail and they cannot read sourcemaps for headless setups, but for the binary 'is this WordPress' question they are fine.

Probe with curl

From a terminal, `curl -I https://<site>/ 2>&1 | grep -iE 'powered|generator|x-(drupal|shopify|magento|wp)'` returns the relevant headers in one shot. Useful for scripting CMS detection across many domains, although the cookie and asset-URL signals require fetching the body too.

Look at the favicon hash

Many CMSes ship a default favicon. The hash of `/favicon.ico` (or the meta-rendered favicon) sometimes maps to a known CMS via tools like Shodan's favicon search or favicon-tracker databases. Niche, but useful for fingerprinting hardened sites that strip every other signal.

Troubleshooting

No generator tag, no obvious CMS asset paths.

Likely a custom-built site without a traditional CMS, or a heavily-customized headless setup. Check for API routes (`/api/`, `/wp-json/`, `/_api/`, `/graphql`) that reveal the backend, and run Sourcemap Explorer to surface any CMS SDK in the JavaScript bundle (`@sanity/client`, `contentful`, etc.).

Multiple CMS signals on the same page.

Possible multi-CMS stitch-up. Most likely explanation: the marketing site is on one CMS, a subdirectory or subdomain is on another, and they share assets through a CDN that pulls from both. Browse a few different routes to confirm which CMS owns which surface.

I see Next.js / React but no CMS at all.

Three possibilities. (1) The site is genuinely a custom React app with no CMS — the data lives in a hand-rolled API. (2) The CMS is headless and lives behind an API — open the Network tab, look for XHR/fetch requests to `cdn.contentful.com`, `cdn.sanity.io`, `<site>.storyblok.com`, `/wp-json/`, `/graphql`. (3) The CMS sits inside the build pipeline (markdown files for Astro, MDX for Next.js, contentlayer) and emits no runtime API calls. Sourcemap Explorer surfaces CMS SDKs from the bundle when they are present.

I see WordPress fingerprints but `/wp-admin/` returns a 404.

Hardened WordPress, often behind a security plugin like Wordfence or iThemes Security that renames or hides admin routes. The frontend signals (`/wp-content/`, `wp-json`, `wp-*` cookies) still confirm the CMS; you just cannot reach the admin without knowing the renamed URL.

Shopify signals on the homepage but a different CMS on /blog/.

Common pattern: Shopify for the storefront, WordPress on a subdomain or subpath for content marketing. Both are real; the home page belongs to Shopify and the blog to WordPress. Check the `<a>` href patterns and the asset URLs separately on each route.

I see a `cdn.contentful.com` request but no obvious framework.

Headless Contentful with a custom frontend. The framework might be vanilla JavaScript, a small static-site generator, or something internal. Sourcemap Explorer surfaces the Contentful SDK and the surrounding framework SDK from the bundle, which is usually enough to identify the rest of the stack.

Caveats

What to do next

For WordPress sites the next steps are the [find-wordpress-plugins-used-by-a-site](/how-to/find-wordpress-plugins-used-by-a-site) and [identify-a-wordpress-theme](/how-to/identify-a-wordpress-theme) guides — together with the CMS identification they give you a complete picture of the WordPress install. For Shopify, you are usually interested in the active theme, the apps in the page (Klaviyo, Privy, Recharge, Bold, Loox), and the checkout architecture (Shopify Payments + Stripe vs a third-party gateway). For headless setups, follow [check-if-a-site-is-built-with-nextjs](/how-to/check-if-a-site-is-built-with-nextjs) and [detect-framework-of-any-website](/how-to/detect-framework-of-any-website) to identify the frontend, then trace the CMS via API requests in the Network tab. For library-level work after CMS identification, [see-every-javascript-library-a-site-uses](/how-to/see-every-javascript-library-a-site-uses) is the natural follow-up — once you know it is a headless Sanity + Next.js stack, you usually want the rest of the dependency surface (Tailwind version, shadcn presence, TanStack Query, NextAuth, telemetry libraries). For competitive comparison of CMS-detection tools, the [Wappalyzer alternatives](/alternatives/wappalyzer) page contrasts Sourcemap Explorer's plugin-level depth with the categorical-only output of the established detectors.

FAQ

Can a site hide its CMS?

Partially — it can strip the generator meta and obfuscate some cookie names. Structural signals (URL paths, the specific CMS's admin routes, cookie namespaces) are much harder to hide without breaking the site, and the JavaScript bundle's SDK references survive even aggressive obfuscation because the framework needs to call them at runtime.

Is this the same as technology detection?

CMS detection is a subset. A fully featured detector identifies framework, libraries, CMS, hosting, analytics, payments and more. CMS is often the most informative single axis for content-heavy sites because it dictates so much of the rest of the architecture.

How do I detect a headless CMS?

Look at the JavaScript bundle's dependency surface — the CMS SDK (`@sanity/client`, `contentful`, `@storyblok/react`, `@payload/<sdk>`, `@hashicorp/react-cms`) reveals the backend even when the rendered HTML carries no traditional fingerprints. Sourcemap Explorer extracts these from the bundle automatically.

What's the difference between WordPress and headless WordPress?

Traditional WordPress renders pages on the WordPress server using PHP themes. Headless WordPress uses WordPress only as a content store, exposing it via the REST API or WPGraphQL, and the visible site is rendered by a separate framework (Next.js, Astro, Gatsby). The fingerprints on the visible site differ accordingly: traditional shows `/wp-content/` and `wordpress_*` cookies, headless shows the framework's signature with WordPress traces only in the API URLs.

Can I tell Shopify Plus apart from regular Shopify?

Sometimes. Shopify Plus enables Shopify Functions, Shopify Scripts (for the older checkout) and the `_shopify_plus` cookie on some configurations. The most reliable signal is looking for Shopify Functions runtime calls in the bundle, or checking whether the site uses any Plus-only features (multi-currency at the variant level, expansion stores, custom checkout extensions). For most workflows the regular vs Plus distinction is not load-bearing — you are mostly trying to confirm 'this is Shopify, what apps are on it, what theme is it'.

What about composable / decoupled commerce setups?

Same approach as headless CMS. The frontend is usually Next.js, Remix or a custom React/Vue setup; the backend is commercetools, BigCommerce headless, Shopify Hydrogen, or a custom commerce engine. The Network tab and the bundle's SDK references reveal the backend; the fingerprints on the visible site are the framework, not the commerce engine itself.

Why is `Server: cloudflare` not enough to identify the CMS?

Because Cloudflare is a CDN sitting in front of whatever the origin is. The Cloudflare header tells you the edge layer, not the application underneath. You usually have to inspect the body, cookies and any non-Cloudflare-stripped headers to reach the actual CMS.

Does Sourcemap Explorer detect Drupal modules the way it detects WordPress plugins?

Partially. Drupal's module loading is less URL-driven than WordPress's plugin loading, so the equivalent enumeration is harder. The extension surfaces Drupal core and the major modules that ship recognisable JavaScript or asset URLs (Bootstrap themes, Olivero, Layout Builder, Webform), but not at the same per-module-by-folder granularity as the WordPress plugin enumeration.

Related

Skip the manual steps.

Sourcemap Explorer automates every workflow in this guide — free, local, no sign-up.

Install free on Chrome