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.