1
2const S = (n, c, h, hd) => ({ n, c, h, hd });
3export const SIGNATURES = [
4
5 S('WordPress', 'CMS', /\/wp-content\/|\/wp-includes\/|wp-json/i, /link:.*wp-json|x-powered-by:.*wordpress/i),
6 S('Drupal', 'CMS', /drupal-settings-json|\/sites\/default\/files\/|Drupal\.settings/i, /x-drupal|x-generator: drupal/i),
7 S('Joomla', 'CMS', /\/media\/jui\/|content="Joomla/i),
8 S('Webflow', 'CMS', /data-wf-site|webflow\.js|assets\.website-files\.com|cdn\.prod\.website-files\.com/i),
9 S('Wix', 'CMS', /static\.wixstatic\.com|_wixCIDX|wix-bolt/i, /x-wix-request-id/i),
10 S('Squarespace', 'CMS', /static1\.squarespace\.com|Squarespace\.Constants/i),
11 S('Ghost', 'CMS', /content="Ghost \d|ghost-(?:portal|sdk)/i),
12 S('HubSpot CMS', 'CMS', /\.hubspotusercontent(?:-na1)?\.net|hs-sites\.com/i, /x-hs-hub-id|x-powered-by: hubspot/i),
13 S('Framer', 'CMS', /framerusercontent\.com|data-framer-/i),
14 S('Contentful', 'CMS', /ctfassets\.net/i),
15 S('Sanity', 'CMS', /cdn\.sanity\.io/i),
16 S('Weebly', 'CMS', /editmysite\.com|weebly\.com\/weebly/i),
17 S('GoDaddy Website Builder', 'CMS', /img1\.wsimg\.com\/(?:isteam|blobby)/i),
18 S('TYPO3', 'CMS', /typo3(?:conf|temp)\//i),
19 S('Adobe Experience Manager', 'CMS', /\/etc\.clientlibs\/|\/content\/dam\//i),
20 S('Storyblok', 'CMS', /a\.storyblok\.com/i),
21
22 S('Shopify', 'Ecommerce', /cdn\.shopify\.com|Shopify\.theme/i, /x-shopify|x-shopid/i),
23 S('WooCommerce', 'Ecommerce', /wp-content\/plugins\/woocommerce|woocommerce-(?:no-js|page|js)|wc-ajax=|wc_add_to_cart_params/i),
24 S('Magento', 'Ecommerce', /Mage\.Cookies|mage\/cookies|\/static\/version\d+\/frontend\//i),
25 S('BigCommerce', 'Ecommerce', /cdn\d*\.bigcommerce\.com/i),
26 S('PrestaShop', 'Ecommerce', /var prestashop\s*=|prestashop\.(?:static_token|urls)|content="PrestaShop/i),
27 S('Salesforce Commerce Cloud', 'Ecommerce', /demandware\.static|\/on\/demandware\.store/i),
28 S('Ecwid', 'Ecommerce', /app\.ecwid\.com/i),
29
30 S('Google Analytics', 'Analytics', /google-analytics\.com\/(?:analytics|ga)\.js|gtag\/js\?id=(?:G|UA)-/i),
31 S('Google Tag Manager', 'Tag manager', /googletagmanager\.com\/gtm\.js|GTM-[A-Z0-9]{5,8}\b/),
32 S('Adobe Analytics', 'Analytics', /omtrdc\.net|AppMeasurement|s_code\.js/i),
33 S('Segment', 'Analytics', /cdn\.segment\.com|analytics\.load\(/i),
34 S('Mixpanel', 'Analytics', /cdn\.mxpnl\.com|mixpanel\.init/i),
35 S('Amplitude', 'Analytics', /cdn\.amplitude\.com|amplitude\.getInstance|@amplitude/i),
36 S('Heap', 'Analytics', /heapanalytics\.com|heap\.load\(/i),
37 S('Hotjar', 'Analytics', /static\.hotjar\.com|hotjar\.com\/c\/hotjar/i),
38 S('Microsoft Clarity', 'Analytics', /clarity\.ms\/tag/i),
39 S('Plausible', 'Analytics', /plausible\.io\/js/i),
40 S('Matomo', 'Analytics', /matomo\.js|piwik\.js|_paq\.push/i),
41 S('FullStory', 'Analytics', /fullstory\.com\/s\/fs\.js|edge\.fullstory\.com/i),
42 S('PostHog', 'Analytics', /posthog\.com\/static|posthog\.init|i\.posthog\.com/i),
43 S('Yandex Metrica', 'Analytics', /mc\.yandex\.ru\/metrika/i),
44 S('Fathom', 'Analytics', /cdn\.usefathom\.com/i),
45 S('Pendo', 'Analytics', /cdn\.pendo\.io|pendo\.initialize/i),
46
47 S('HubSpot', 'Marketing automation', /js\.hs-scripts\.com|js\.hsforms\.net|js\.hs-analytics\.net|_hsq\.push|js\.hs-banner\.com/i),
48 S('Marketo', 'Marketing automation', /munchkin\.marketo\.net|mktoForms2|marketo\.com\/js/i),
49 S('Pardot', 'Marketing automation', /pi\.pardot\.com|pardot\.com\/pd\.js|piAId/i),
50 S('Salesforce', 'CRM', /\.my\.salesforce\.com|service\.force\.com|servlet\.WebToLead|webto(?:lead|case)/i),
51 S('Mailchimp', 'Email marketing', /chimpstatic\.com|list-manage\.com/i),
52 S('Klaviyo', 'Email marketing', /static\.klaviyo\.com|klaviyo\.com\/onsite/i),
53 S('ActiveCampaign', 'Marketing automation', /trackcmp\.net|activehosted\.com/i),
54 S('Brevo', 'Email marketing', /sibforms\.com|sendinblue\.com|brevo\.com\/js/i),
55 S('6sense', 'Account-based marketing', /j\.6sc\.co|6sc\.co\/j\//i),
56 S('Clearbit', 'Account-based marketing', /tag\.clearbitscripts\.com|x\.clearbitjs\.com/i),
57 S('ZoomInfo', 'Account-based marketing', /ws\.zoominfo\.com|js\.zi-scripts\.com/i),
58 S('Demandbase', 'Account-based marketing', /tag\.demandbase\.com|scripts\.demandbase\.com/i),
59 S('Calendly', 'Scheduling', /assets\.calendly\.com|calendly\.com\/assets/i),
60 S('Chili Piper', 'Scheduling', /js\.chilipiper\.com/i),
61 S('Typeform', 'Forms', /embed\.typeform\.com/i),
62 S('Qualified', 'Live chat', /js\.qualified\.com/i),
63 S('Unbounce', 'Landing pages', /unbounce\.com|ubembed\.com/i),
64
65 S('Optimizely', 'A/B testing', /cdn\.optimizely\.com/i),
66 S('VWO', 'A/B testing', /dev\.visualwebsiteoptimizer\.com/i),
67 S('AB Tasty', 'A/B testing', /try\.abtasty\.com/i),
68
69 S('Meta Pixel', 'Advertising', /connect\.facebook\.net\/[^"']*fbevents\.js|fbq\(\s*['"]init/i),
70 S('LinkedIn Insight Tag', 'Advertising', /snap\.licdn\.com\/li\.lms-analytics|_linkedin_partner_id/i),
71 S('Google Ads', 'Advertising', /googleadservices\.com\/pagead\/conversion|gtag\/js\?id=AW-|googleads\.g\.doubleclick\.net/i),
72 S('X (Twitter) Pixel', 'Advertising', /static\.ads-twitter\.com|twq\(\s*['"]init/i),
73 S('TikTok Pixel', 'Advertising', /analytics\.tiktok\.com/i),
74 S('Pinterest Tag', 'Advertising', /s\.pinimg\.com\/ct\/core\.js|pintrk\(/i),
75 S('Microsoft Advertising', 'Advertising', /bat\.bing\.com/i),
76 S('Reddit Pixel', 'Advertising', /redditstatic\.com\/ads|rdt\(\s*['"]init/i),
77 S('Criteo', 'Advertising', /static\.criteo\.net/i),
78 S('Taboola', 'Advertising', /cdn\.taboola\.com/i),
79
80 S('Intercom', 'Live chat', /widget\.intercom\.io|js\.intercomcdn\.com|intercomSettings/i),
81 S('Drift', 'Live chat', /js\.driftt\.com|drift\.com\/include/i),
82 S('Zendesk', 'Customer support', /static\.zdassets\.com|zopim|\.zendesk\.com/i),
83 S('Freshworks', 'Customer support', /wchat\.freshchat\.com|freshdesk\.com|fw-cdn\.com/i),
84 S('LiveChat', 'Live chat', /cdn\.livechatinc\.com/i),
85 S('Crisp', 'Live chat', /client\.crisp\.chat/i),
86 S('Tawk.to', 'Live chat', /embed\.tawk\.to/i),
87 S('Tidio', 'Live chat', /code\.tidio\.co/i),
88 S('Gorgias', 'Customer support', /config\.gorgias\.chat/i),
89 S('Help Scout', 'Customer support', /beacon-v2\.helpscout\.net/i),
90
91 S('Next.js', 'JavaScript framework', /__NEXT_DATA__|\/_next\/static\//, /x-powered-by: next\.js/i),
92 S('Nuxt', 'JavaScript framework', /__NUXT__|\/_nuxt\//),
93 S('Gatsby', 'JavaScript framework', /___gatsby|\/page-data\/app-data\.json/),
94 S('Astro', 'JavaScript framework', /astro-island|data-astro-cid/),
95 S('Remix', 'JavaScript framework', /__remixContext/),
96 S('SvelteKit', 'JavaScript framework', /__sveltekit|data-sveltekit/),
97 S('Angular', 'JavaScript framework', /ng-version="/),
98 S('Vue.js', 'JavaScript framework', /data-v-[0-9a-f]{8}\b|vue(?:\.runtime)?(?:\.global)?(?:\.min)?\.js/),
99 S('React', 'JavaScript framework', /data-reactroot|react-dom(?:\.production)?(?:\.min)?\.js|__NEXT_DATA__|___gatsby/),
100 S('jQuery', 'JavaScript library', /jquery(?:[.-]\d[\d.]*)?(?:\.min)?\.js/i),
101 S('Bootstrap', 'UI framework', /bootstrap(?:\.bundle)?(?:\.min)?\.(?:css|js)/i),
102 S('Font Awesome', 'Font', /font-?awesome|kit\.fontawesome\.com/i),
103 S('Google Fonts', 'Font', /fonts\.googleapis\.com/i),
104 S('Adobe Fonts', 'Font', /use\.typekit\.net/i),
105
106 S('Cloudflare', 'CDN', null, /^server: cloudflare|^cf-ray:/im),
107 S('Fastly', 'CDN', null, /^x-served-by: cache-|^fastly-|^x-fastly/im),
108 S('Akamai', 'CDN', null, /^server: akamai|^x-akamai|akamaighost/im),
109 S('Amazon CloudFront', 'CDN', null, /^x-amz-cf-id|^via:.*cloudfront/im),
110 S('Vercel', 'Hosting', null, /^x-vercel-id|^server: vercel/im),
111 S('Netlify', 'Hosting', null, /^x-nf-request-id|^server: netlify/im),
112 S('Heroku', 'Hosting', null, /^via:.*vegur/im),
113 S('GitHub Pages', 'Hosting', null, /^server: github\.com/im),
114 S('WP Engine', 'Hosting', null, /^x-powered-by: wp engine|^wpe-backend/im),
115 S('Kinsta', 'Hosting', null, /^x-kinsta/im),
116 S('Amazon S3', 'Hosting', null, /^server: amazons3/im),
117 S('Nginx', 'Web server', null, /^server: nginx/im),
118 S('Apache', 'Web server', null, /^server: apache/im),
119 S('Microsoft IIS', 'Web server', null, /^server: microsoft-iis/im),
120 S('LiteSpeed', 'Web server', null, /^server: litespeed/im),
121 S('PHP', 'Programming language', null, /^x-powered-by: php|PHPSESSID/im),
122 S('ASP.NET', 'Web framework', /__VIEWSTATE/, /^x-aspnet-version|^x-powered-by: asp\.net|ASP\.NET_SessionId/im),
123 S('Laravel', 'Web framework', null, /laravel_session/i),
124
125 S('Stripe', 'Payments', /js\.stripe\.com/i),
126 S('PayPal', 'Payments', /paypal\.com\/sdk\/js|paypalobjects\.com/i),
127 S('Klarna', 'Payments', /klarnaservices\.com|js\.klarna\.com/i),
128 S('Afterpay', 'Payments', /afterpay\.com|static\.afterpay/i),
129 S('Braintree', 'Payments', /js\.braintreegateway\.com/i),
130
131 S('OneTrust', 'Cookie consent', /cdn\.cookielaw\.org|optanon/i),
132 S('Cookiebot', 'Cookie consent', /consent\.cookiebot\.com/i),
133 S('CookieYes', 'Cookie consent', /cdn-cookieyes\.com/i),
134 S('Osano', 'Cookie consent', /cmp\.osano\.com/i),
135 S('TrustArc', 'Cookie consent', /consent\.trustarc\.com/i),
136 S('Usercentrics', 'Cookie consent', /usercentrics\.eu/i),
137 S('Didomi', 'Cookie consent', /sdk\.privacy-center\.org/i),
138
139 S('Sentry', 'Error monitoring', /browser\.sentry-cdn\.com|Sentry\.init|ingest\.sentry\.io/i),
140 S('Datadog RUM', 'Monitoring', /datadoghq-browser-agent|DD_RUM/i),
141 S('New Relic', 'Monitoring', /js-agent\.newrelic\.com|NREUM/),
142 S('LogRocket', 'Monitoring', /cdn\.logrocket\.io|cdn\.lr-ingest\.io|LogRocket\.init/i),
143
144 S('reCAPTCHA', 'Security', /google\.com\/recaptcha|recaptcha\/api\.js/i),
145 S('hCaptcha', 'Security', /hcaptcha\.com\/1\/api\.js/i),
146 S('Cloudflare Turnstile', 'Security', /challenges\.cloudflare\.com\/turnstile/i),
147 S('Algolia', 'Search', /algolianet\.com|algoliasearch|\.algolia\.net/i),
148 S('Google Maps', 'Maps', /maps\.googleapis\.com|google\.com\/maps\/embed/i),
149 S('Wistia', 'Video', /fast\.wistia\.(?:com|net)/i),
150 S('Vimeo', 'Video', /player\.vimeo\.com/i),
151 S('YouTube', 'Video', /youtube(?:-nocookie)?\.com\/embed\//i),
152 S('Trustpilot', 'Reviews', /widget\.trustpilot\.com/i),
153 S('Yotpo', 'Reviews', /staticw2\.yotpo\.com|cdn-widgetsrepository\.yotpo\.com/i),
154];
155
156export function detectTech(html, headerText) {
157 const out = [];
158 for (const s of SIGNATURES) {
159 if ((s.h && s.h.test(html)) || (s.hd && s.hd.test(headerText))) out.push({ name: s.n, category: s.c });
160 }
161 return out;
162}