Back to blog
InspectionJanuary 1, 2024ยท 7 min read

Framework and CMS Detection: What's This Site Built With?

A practical Fusebox guide to framework and cms detection.

Framework and CMS Detection: What's This Site Built With?

Published: January 2024
Reading time: 9 minutes

Every website is built on something - WordPress, React, Shopify, or countless other platforms. Knowing the framework or CMS reveals architecture decisions, capabilities, limitations, and opportunities. Here's how to detect them all.

Why Framework Detection Matters

Detecting frameworks tells you:

  • Technical debt - Old jQuery site vs modern React
  • Capabilities - What's possible with this stack
  • Performance implications - Some frameworks are heavy
  • Security concerns - Outdated versions, known vulnerabilities
  • Development cost - Custom vs off-the-shelf
  • Hiring needs - What skills to look for

Quick Detection Methods

1. The Universal Detector

// Comprehensive framework detection
(function detectFrameworks() {
  const detected = {
    cms: [],
    frontend: [],
    backend: [],
    ecommerce: [],
    analytics: []
  };
  
  // CMS Detection
  if (document.querySelector('meta[name="generator"]')) {
    const generator = document.querySelector('meta[name="generator"]').content;
    detected.cms.push(generator);
  }
  
  // WordPress specific
  if (window.wp || document.querySelector('link[href*="wp-content"]')) {
    detected.cms.push('WordPress');
  }
  
  // Frontend frameworks
  if (window.React) detected.frontend.push(`React ${React.version}`);
  if (window.Vue) detected.frontend.push(`Vue ${Vue.version}`);
  if (window.angular) detected.frontend.push('Angular 1.x');
  if (window.ng) detected.frontend.push('Angular 2+');
  if (window.Ember) detected.frontend.push('Ember.js');
  if (window.jQuery) detected.frontend.push(`jQuery ${jQuery.fn.jquery}`);
  
  // Next.js / Nuxt.js
  if (window.__NEXT_DATA__) detected.frontend.push('Next.js');
  if (window.__NUXT__) detected.frontend.push('Nuxt.js');
  
  // E-commerce
  if (window.Shopify) detected.ecommerce.push('Shopify');
  if (window.wc_add_to_cart_params) detected.ecommerce.push('WooCommerce');
  if (document.querySelector('meta[name="generator"][content*="PrestaShop"]')) {
    detected.ecommerce.push('PrestaShop');
  }
  
  console.log('๐Ÿ” Framework Detection Results:\n', detected);
})();

2. DOM Signature Detection

// Detect by DOM patterns
function detectByDOM() {
  const signatures = {
    // React
    react: () => {
      return document.querySelector('[data-reactroot]') || 
             document.querySelector('[data-reactid]') ||
             document.querySelector('._reactRootContainer');
    },
    
    // Vue
    vue: () => {
      // Vue 2
      if (document.querySelector('[data-server-rendered]')) return 'Vue.js (SSR)';
      // Vue 3
      const vueApps = Array.from(document.querySelectorAll('*')).filter(el => 
        el._vnode || el.__vueParentComponent
      );
      if (vueApps.length) return 'Vue.js 3';
      // Vue general
      if (document.querySelector('[data-v-]')) return 'Vue.js';
    },
    
    // Angular
    angular: () => {
      if (document.querySelector('[ng-version]')) {
        const version = document.querySelector('[ng-version]').getAttribute('ng-version');
        return `Angular ${version}`;
      }
      if (document.querySelector('[data-ng-version]')) return 'Angular 2+';
      if (document.querySelector('[ng-app]')) return 'AngularJS (1.x)';
    },
    
    // Svelte
    svelte: () => {
      if (document.querySelector('[data-svelte]')) return 'Svelte';
    }
  };
  
  console.log('๐ŸŽฏ DOM-based Detection:');
  Object.entries(signatures).forEach(([name, detect]) => {
    const result = detect();
    if (result) console.log(`โœ… ${result}`);
  });
}

CMS Detection Deep Dive

WordPress Detection

// Comprehensive WordPress detection
function detectWordPress() {
  const wpSignatures = {
    // URL patterns
    urls: [
      '/wp-content/',
      '/wp-includes/',
      '/wp-admin/',
      '/wp-json/'
    ],
    
    // Meta tags
    meta: [
      'meta[name="generator"][content*="WordPress"]',
      'link[rel="https://api.w.org/"]'
    ],
    
    // Scripts/Styles
    assets: [
      'script[src*="wp-includes"]',
      'link[href*="wp-content"]'
    ],
    
    // Classes
    classes: [
      '.wp-block',
      '.wp-embedded-content',
      '.wordpress'
    ]
  };
  
  let detected = false;
  let version = null;
  
  // Check meta generator
  const generator = document.querySelector('meta[name="generator"]');
  if (generator?.content.includes('WordPress')) {
    detected = true;
    version = generator.content.match(/WordPress\s*([\d.]+)/)?.[1];
  }
  
  // Check for WP REST API
  const apiLink = document.querySelector('link[rel="https://api.w.org/"]');
  if (apiLink) {
    detected = true;
    console.log('WordPress REST API detected');
  }
  
  // Check resources
  const resources = performance.getEntriesByType('resource');
  const wpResources = resources.filter(r => 
    r.name.includes('wp-content') || r.name.includes('wp-includes')
  );
  
  if (wpResources.length > 0) {
    detected = true;
    console.log(`WordPress resources found: ${wpResources.length}`);
  }
  
  if (detected) {
    console.log(`โœ… WordPress ${version || 'detected'}`);
    
    // Detect plugins
    detectWordPressPlugins();
  }
}

function detectWordPressPlugins() {
  const plugins = {
    'Yoast SEO': 'yoast',
    'WooCommerce': 'woocommerce',
    'Contact Form 7': 'contact-form-7',
    'Elementor': 'elementor',
    'WP Rocket': 'wp-rocket'
  };
  
  console.log('\nWordPress Plugins:');
  Object.entries(plugins).forEach(([name, signature]) => {
    if (document.querySelector(`[class*="${signature}"], [id*="${signature}"]`) ||
        Array.from(document.scripts).some(s => s.src?.includes(signature))) {
      console.log(`  โœ… ${name}`);
    }
  });
}

Shopify Detection

// Detect Shopify and its features
function detectShopify() {
  const shopifySignatures = {
    // Global objects
    globals: ['Shopify', 'ShopifyAnalytics', 'ShopifyPay'],
    
    // Meta tags
    meta: {
      'shopify-checkout-api-token': 'Checkout API',
      'shopify-digital-wallet': 'Digital Wallet Support'
    },
    
    // CDN usage
    cdn: 'cdn.shopify.com'
  };
  
  // Check for Shopify object
  if (window.Shopify) {
    console.log('โœ… Shopify detected');
    
    // Get Shopify details
    const shopifyData = {
      shop: window.Shopify.shop,
      theme: window.Shopify.theme,
      currency: window.Shopify.currency,
      country: window.Shopify.country
    };
    
    console.log('Shopify Details:', shopifyData);
    
    // Check for Shopify Plus
    if (window.Shopify.checkout || document.querySelector('[data-shopify-checkout]')) {
      console.log('๐Ÿ“ฆ Shopify Plus detected');
    }
    
    // Detect apps
    detectShopifyApps();
  }
}

function detectShopifyApps() {
  const commonApps = {
    'Klaviyo': 'klaviyo',
    'Privy': 'privy',
    'Bold': 'bold-commerce',
    'ReCharge': 'recharge',
    'Smile.io': 'smile-io'
  };
  
  console.log('\nShopify Apps:');
  Object.entries(commonApps).forEach(([app, signature]) => {
    if (window[signature] || document.querySelector(`[class*="${signature}"]`)) {
      console.log(`  โœ… ${app}`);
    }
  });
}

Modern CMS Detection

// Detect headless CMS and modern platforms
function detectModernCMS() {
  const modernCMS = {
    // Jamstack
    'Netlify CMS': () => window.netlifyIdentity,
    'Contentful': () => document.querySelector('[data-contentful]'),
    'Sanity': () => window._sanityClient || document.querySelector('[data-sanity]'),
    'Strapi': () => {
      const resources = performance.getEntriesByType('resource');
      return resources.some(r => r.name.includes('strapi'));
    },
    
    // Site builders
    'Webflow': () => document.querySelector('[data-wf-page]'),
    'Wix': () => window.wixBiSession,
    'Squarespace': () => window.Static?.SQUARESPACE_CONTEXT,
    'Bubble': () => window._bubble_page_load_data,
    
    // Static generators
    'Gatsby': () => window.___gatsby,
    'Hugo': () => document.querySelector('meta[name="generator"][content*="Hugo"]'),
    'Jekyll': () => document.querySelector('meta[name="generator"][content*="Jekyll"]'),
    
    // Page builders
    'Elementor': () => document.querySelector('.elementor'),
    'Divi': () => document.querySelector('.et_pb_section'),
    'Gutenberg': () => document.querySelector('.wp-block')
  };
  
  console.log('๐Ÿš€ Modern CMS Detection:');
  Object.entries(modernCMS).forEach(([name, detect]) => {
    if (detect()) {
      console.log(`โœ… ${name}`);
    }
  });
}

Frontend Framework Analysis

React Ecosystem Detection

// Detailed React analysis
function analyzeReact() {
  if (!window.React && !document.querySelector('[data-reactroot]')) return;
  
  console.log('โš›๏ธ React Analysis:');
  
  // Version
  if (window.React) {
    console.log(`Version: ${React.version}`);
  }
  
  // Detect React Router
  if (window.ReactRouter || document.querySelector('[data-react-router]')) {
    console.log('โœ… React Router detected');
  }
  
  // Detect Redux
  if (window.Redux || window.__REDUX_DEVTOOLS_EXTENSION__) {
    console.log('โœ… Redux detected');
    
    // Try to access store
    if (window.__REDUX_DEVTOOLS_EXTENSION__) {
      console.log('Redux DevTools available');
    }
  }
  
  // Detect Next.js
  if (window.__NEXT_DATA__) {
    const nextData = window.__NEXT_DATA__;
    console.log('โœ… Next.js detected');
    console.log(`  Build ID: ${nextData.buildId}`);
    console.log(`  Pages: ${Object.keys(nextData.props?.pageProps || {}).length}`);
  }
  
  // Material-UI / MUI
  if (document.querySelector('[class*="MuiButton"]') || window.MaterialUI) {
    console.log('โœ… Material-UI detected');
  }
  
  // Styled Components
  if (document.querySelector('style[data-styled]')) {
    console.log('โœ… Styled Components detected');
  }
}

Vue.js Ecosystem

// Vue.js deep analysis
function analyzeVue() {
  console.log('๐Ÿ’š Vue.js Analysis:');
  
  // Detect Vue version
  if (window.Vue) {
    console.log(`Vue ${Vue.version} (global)`);
  } else if (document.querySelector('[data-v-]')) {
    console.log('Vue.js detected (compiled)');
  }
  
  // Nuxt.js
  if (window.__NUXT__ || window.$nuxt) {
    console.log('โœ… Nuxt.js detected');
    if (window.__NUXT__) {
      console.log(`  Mode: ${window.__NUXT__.mode || 'universal'}`);
    }
  }
  
  // Vuex
  if (window.Vuex || window.$store) {
    console.log('โœ… Vuex detected');
  }
  
  // Vue Router
  if (window.VueRouter || window.$route) {
    console.log('โœ… Vue Router detected');
  }
  
  // Vuetify
  if (document.querySelector('.v-application') || window.Vuetify) {
    console.log('โœ… Vuetify detected');
  }
  
  // Quasar
  if (window.Quasar) {
    console.log('โœ… Quasar Framework detected');
  }
}

Backend Technology Detection

Server Detection

// Detect backend technologies from responses
async function detectBackend() {
  const response = await fetch(location.href);
  const headers = {};
  response.headers.forEach((value, key) => {
    headers[key.toLowerCase()] = value;
  });
  
  console.log('๐Ÿ–ฅ๏ธ Backend Detection:');
  
  // Server type
  if (headers.server) {
    console.log(`Server: ${headers.server}`);
    
    // Parse server details
    if (headers.server.includes('nginx')) console.log('  โœ… Nginx');
    if (headers.server.includes('Apache')) console.log('  โœ… Apache');
    if (headers.server.includes('Microsoft-IIS')) console.log('  โœ… IIS');
  }
  
  // Programming language
  if (headers['x-powered-by']) {
    const powered = headers['x-powered-by'];
    console.log(`Powered by: ${powered}`);
    
    if (powered.includes('PHP')) console.log('  โœ… PHP');
    if (powered.includes('ASP.NET')) console.log('  โœ… ASP.NET');
    if (powered.includes('Express')) console.log('  โœ… Node.js/Express');
  }
  
  // Framework hints
  if (headers['x-aspnet-version']) console.log(`ASP.NET: ${headers['x-aspnet-version']}`);
  if (headers['x-rails-version']) console.log(`Ruby on Rails: ${headers['x-rails-version']}`);
  if (headers['x-django-version']) console.log(`Django: ${headers['x-django-version']}`);
  
  // Check cookies for framework hints
  if (document.cookie.includes('laravel_session')) console.log('โœ… Laravel detected');
  if (document.cookie.includes('PHPSESSID')) console.log('โœ… PHP detected');
  if (document.cookie.includes('ASP.NET_SessionId')) console.log('โœ… ASP.NET detected');
}

Performance Impact by Framework

Framework Weight Analysis

// Analyze framework performance impact
function analyzeFrameworkPerformance() {
  const bundles = performance.getEntriesByType('resource')
    .filter(r => r.name.includes('.js'));
  
  const frameworkSizes = {
    react: 0,
    vue: 0,
    angular: 0,
    jquery: 0,
    other: 0
  };
  
  bundles.forEach(bundle => {
    const size = bundle.transferSize || 0;
    const name = bundle.name.toLowerCase();
    
    if (name.includes('react')) frameworkSizes.react += size;
    else if (name.includes('vue')) frameworkSizes.vue += size;
    else if (name.includes('angular')) frameworkSizes.angular += size;
    else if (name.includes('jquery')) frameworkSizes.jquery += size;
    else frameworkSizes.other += size;
  });
  
  console.log('๐Ÿ“Š Framework Size Analysis:');
  Object.entries(frameworkSizes).forEach(([framework, size]) => {
    if (size > 0) {
      console.log(`${framework}: ${(size / 1024).toFixed(1)}KB`);
    }
  });
  
  // Check for framework bloat
  const totalJS = Object.values(frameworkSizes).reduce((a, b) => a + b, 0);
  if (totalJS > 500 * 1024) {
    console.warn('โš ๏ธ Heavy JavaScript detected (>500KB)');
  }
}

Security Implications

Version Security Check

// Check for outdated/vulnerable versions
function checkFrameworkSecurity() {
  const vulnerabilities = {
    'jQuery': {
      '< 3.5.0': 'XSS vulnerability (CVE-2020-11022)',
      '< 3.4.0': 'Prototype pollution (CVE-2019-11358)'
    },
    'Angular': {
      '< 1.6.0': 'Various security vulnerabilities',
      '1.x': 'End of life - no security updates'
    },
    'Bootstrap': {
      '< 4.3.1': 'XSS vulnerability in tooltips',
      '< 3.4.0': 'XSS vulnerability in data-attributes'
    }
  };
  
  console.log('๐Ÿ”’ Security Check:');
  
  // Check jQuery
  if (window.jQuery) {
    const version = jQuery.fn.jquery;
    console.log(`jQuery ${version}`);
    
    Object.entries(vulnerabilities.jQuery).forEach(([condition, issue]) => {
      if (versionCompare(version, condition)) {
        console.warn(`  โš ๏ธ ${issue}`);
      }
    });
  }
}

function versionCompare(version, condition) {
  // Simple version comparison (would need full implementation)
  const conditionMatch = condition.match(/([<>=]+)\s*([\d.]+)/);
  if (!conditionMatch) return false;
  
  const [, operator, targetVersion] = conditionMatch;
  // Implement actual comparison logic here
  return true; // Simplified
}

Complete Framework Audit

// Run complete framework analysis
(async function completeFrameworkAudit() {
  console.log('๐Ÿ” Complete Framework & CMS Audit\n');
  
  // 1. CMS Detection
  console.log('=== CMS Detection ===');
  detectWordPress();
  detectShopify();
  detectModernCMS();
  
  // 2. Frontend Frameworks
  console.log('\n=== Frontend Frameworks ===');
  analyzeReact();
  analyzeVue();
  detectByDOM();
  
  // 3. Backend Detection
  console.log('\n=== Backend Technology ===');
  await detectBackend();
  
  // 4. Performance Impact
  console.log('\n=== Performance Analysis ===');
  analyzeFrameworkPerformance();
  
  // 5. Security Check
  console.log('\n=== Security Analysis ===');
  checkFrameworkSecurity();
  
  // 6. Summary
  console.log('\n=== Summary ===');
  const summary = {
    cms: document.querySelector('meta[name="generator"]')?.content || 'Not detected',
    frontend: window.React ? 'React' : window.Vue ? 'Vue' : 'Other/None',
    jquery: window.jQuery ? jQuery.fn.jquery : 'Not found',
    responsive: document.querySelector('meta[name="viewport"]') ? 'Yes' : 'No',
    pwa: 'serviceWorker' in navigator ? 'Capable' : 'No'
  };
  
  console.table(summary);
})();

The Bottom Line

Framework and CMS detection reveals:

  • Technical architecture - Modern vs legacy
  • Development approach - Custom vs template
  • Maintenance burden - Update requirements
  • Performance implications - Heavy vs lightweight
  • Security posture - Updated vs vulnerable
  • Business model - Enterprise vs budget

Understanding the stack helps you make better technical decisions, estimate costs, and identify opportunities.


Detect frameworks instantly: Fusebox identifies all frameworks, CMS platforms, and their versions while you browse. Know what any site is built with. $29 one-time purchase.