Skip to content

Commit 739e88a

Browse files
Stanzin7Stanfordyclaude
authored
SEO: free extension scanner positioning + live "extensions scanned" count (ExtensionShield#232)
* Reposition ExtensionShield SEO content * SEO: free extension scanner positioning + live "extensions scanned" count Homepage & landing SEO (Phase 1): - Retitle the homepage to target "free Chrome extension scanner" while keeping the security/governance positioning (title, meta, keywords, eyebrow, H1, subhead, trust H2). - Mobile hero now renders the real H1 + a working scan input instead of a "check on desktop" stub (mobile-first indexing). - Add /free-extension-scanner landing page via the SeoLongFormPage template, with FAQPage + BreadcrumbList + SoftwareApplication (price 0) JSON-LD and internal links only (no competitor backlinks). - Wire the page into nav (Product), footer, homepage CTA, routes, and sitemap. - Add "is it free" / "no install" entries to the homepage FAQ schema. - Remove 10 stray macOS " 2" duplicate files. Live "extensions scanned" count: - Homepage stat now reads the real total from /statistics (databaseService.getStatistics) instead of a hardcoded 100. - Supabase get_statistics uses an exact count for total_scans so the number is accurate regardless of the default PostgREST row cap. Also carries the in-progress SEO repositioning of the compare/landing pages and blog content on this branch. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Stanzin <snorzang65@gmail.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 46f2355 commit 739e88a

16 files changed

Lines changed: 2867 additions & 2290 deletions

File tree

frontend/public/sitemap.xml

Lines changed: 64 additions & 58 deletions
Large diffs are not rendered by default.

frontend/src/App.scss

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -570,9 +570,9 @@ body {
570570
}
571571

572572
.nav-dropdown-menu {
573-
position: absolute;
574-
top: calc(100% + 0.25rem);
575-
left: 0;
573+
position: fixed;
574+
top: var(--extensionshield-header-offset);
575+
left: auto;
576576
min-width: 280px;
577577
max-width: calc(100vw - 2rem);
578578
background: var(--extensionshield-bg-card);
@@ -587,13 +587,13 @@ body {
587587
display: flex;
588588
flex-direction: column;
589589
gap: 0.5rem;
590-
margin-top: 0.25rem;
590+
margin-top: 0;
591591

592592
/* Categorized dropdown (e.g. Research = Research + Resources) – centered on viewport */
593593
&--sections {
594594
position: fixed;
595595
left: 50%;
596-
top: calc(var(--extensionshield-header-height) + 0.5rem);
596+
top: var(--extensionshield-header-offset);
597597
transform: translateX(-50%);
598598
animation: megamenuEnterCentered 0.2s ease;
599599
min-width: 320px;

frontend/src/components/Footer.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@
158158
.app-footer__groups {
159159
display: grid;
160160
grid-template-columns: repeat(2, minmax(0, 150px));
161-
gap: 0.75rem 1.25rem;
161+
gap: 0.75rem 3rem;
162162

163163
@media (max-width: 600px) {
164164
grid-template-columns: 1fr;

frontend/src/components/home/HowWeProtectYouSection.jsx

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -274,15 +274,6 @@ export default function HowWeProtectYouSection() {
274274
</div>
275275
</div>
276276

277-
<motion.p
278-
className="how-protect-footnote"
279-
initial={reduced ? false : { opacity: 0 }}
280-
whileInView={reduced ? {} : { opacity: 1 }}
281-
viewport={{ once: true, amount: 0.5 }}
282-
transition={{ duration: 0.35, delay: stagger * 7 }}
283-
>
284-
Just because it's in the Chrome store doesn't mean it's safe.
285-
</motion.p>
286277
</div>
287278
</div>
288279
</div>

frontend/src/components/home/HowWeProtectYouSection.scss

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@
44

55
.how-protect-section {
66
position: relative;
7-
padding: var(--landing-section-padding-y-top) var(--landing-section-padding-x) var(--landing-section-padding-y-bottom);
7+
padding: var(--hp-section-py) var(--hp-px);
88
background: transparent;
99
}
1010

1111
.how-protect-container {
12-
max-width: var(--landing-section-inner-max);
12+
max-width: var(--hp-max);
1313
margin: 0 auto;
14-
padding: 0 4rem;
14+
padding: 0;
1515
box-sizing: border-box;
1616
}
1717

frontend/src/data/blogPosts.js

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,5 +446,78 @@ export const blogPosts = [
446446
}
447447
];
448448

449+
export const blogStrategyTopics = [
450+
{
451+
title: "How to Check if a Chrome Extension Is Safe Before Installing",
452+
longTailKeyword: "how to check if chrome extension is safe",
453+
intent: "Practical pre-install safety checklist for users who are one search away from installing an extension.",
454+
featuredSnippetAngle: "Answer with a numbered checklist: permissions, publisher, reviews, privacy policy, update history, and risk score.",
455+
internalLinks: ["/scan", "/extension-security", "/extension-risk-score", "/blog"]
456+
},
457+
{
458+
title: "What Permissions Are Dangerous in Chrome Extensions?",
459+
longTailKeyword: "dangerous chrome extension permissions",
460+
intent: "Explain high-risk permissions and help users understand whether requested access is justified.",
461+
featuredSnippetAngle: "List dangerous permissions with one-sentence risk explanations.",
462+
internalLinks: ["/extension-permissions", "/scan", "/extension-risk-score", "/blog"]
463+
},
464+
{
465+
title: "Can Chrome Extensions Steal Data?",
466+
longTailKeyword: "can chrome extensions steal data",
467+
intent: "Answer a security fear directly and show how permissions, page access, and network calls create exposure.",
468+
featuredSnippetAngle: "Lead with a direct yes/no answer, then list the main data paths.",
469+
internalLinks: ["/extension-security", "/extension-permissions", "/scan", "/blog"]
470+
},
471+
{
472+
title: "How Hackers Use Browser Extensions to Steal Data",
473+
longTailKeyword: "how hackers use browser extensions to steal data",
474+
intent: "Educate users and security teams on attack chains without hype.",
475+
featuredSnippetAngle: "Break the attack into install, permission, collection, exfiltration, and update abuse steps.",
476+
internalLinks: ["/extension-security", "/scan", "/extension-risk-score", "/blog"]
477+
},
478+
{
479+
title: "Chrome Extension Scanner vs Extension Governance Platform",
480+
longTailKeyword: "chrome extension scanner vs governance platform",
481+
intent: "Capture scanner traffic while moving readers toward the larger governance category.",
482+
featuredSnippetAngle: "Use a two-column scanner vs governance comparison.",
483+
internalLinks: ["/extension-governance", "/extension-security", "/scan", "/blog"]
484+
},
485+
{
486+
title: "Top Risky Chrome Extension Patterns to Watch in 2026",
487+
longTailKeyword: "risky chrome extensions 2026",
488+
intent: "Rank for annual risk queries without publishing an unsupported blacklist.",
489+
featuredSnippetAngle: "List risky patterns such as all-site access, data collection, obfuscation, ownership changes, and suspicious updates.",
490+
internalLinks: ["/scan", "/extension-permissions", "/extension-risk-score", "/blog"]
491+
},
492+
{
493+
title: "Spin.ai vs ExtensionShield",
494+
longTailKeyword: "Spin.ai alternative",
495+
intent: "Capture high-intent comparison traffic from buyers evaluating browser extension security tools.",
496+
featuredSnippetAngle: "Neutral best-fit comparison table by workflow.",
497+
internalLinks: ["/compare/spin-ai", "/extension-governance", "/scan", "/blog"]
498+
},
499+
{
500+
title: "CRXcavator vs ExtensionShield",
501+
longTailKeyword: "CRXcavator alternative",
502+
intent: "Capture users looking for a current extension risk scoring and governance workflow.",
503+
featuredSnippetAngle: "Compare historical risk scoring criteria with current governance requirements.",
504+
internalLinks: ["/compare/crxcavator", "/extension-risk-score", "/scan", "/blog"]
505+
},
506+
{
507+
title: "How to Build a Chrome Extension Allowlist Policy",
508+
longTailKeyword: "chrome extension allowlist policy",
509+
intent: "Help enterprise security teams create a repeatable governance process.",
510+
featuredSnippetAngle: "Give policy tiers: allow, monitor, request fix, block.",
511+
internalLinks: ["/extension-governance", "/extension-risk-score", "/scan", "/blog"]
512+
},
513+
{
514+
title: "How to Audit a CRX or ZIP Chrome Extension Before Release",
515+
longTailKeyword: "audit CRX ZIP chrome extension before release",
516+
intent: "Convert developers who need pre-release extension security checks.",
517+
featuredSnippetAngle: "Checklist for manifest, permissions, content scripts, service worker, network access, and privacy disclosures.",
518+
internalLinks: ["/scan/upload", "/extension-security", "/extension-permissions", "/blog"]
519+
}
520+
];
521+
449522
export const getBlogPostBySlug = (slug) =>
450523
blogPosts.find((p) => p.slug === slug) || null;

frontend/src/nav/navigation.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,14 @@ export const topNavItems = [
1515
category: NAV_CATEGORIES.PRODUCT,
1616
label: "Scan",
1717
path: "/scan",
18-
matchPaths: ["/scan", "/extension-security", "/extension-risk-score", "/extension-permissions"],
18+
matchPaths: ["/scan", "/free-extension-scanner", "/extension-security", "/extension-risk-score", "/extension-permissions"],
1919
dropdownItems: [
20+
{
21+
icon: "🔎",
22+
label: "Free Extension Scanner",
23+
description: "Check any Chrome extension by URL",
24+
path: "/free-extension-scanner"
25+
},
2026
{
2127
icon: "🛡️",
2228
label: "Security Platform",
@@ -56,7 +62,7 @@ export const topNavItems = [
5662
{ icon: "📋", label: "Case Studies", description: "Real-world analysis", path: "/research/case-studies" },
5763
{ icon: "⚙️", label: "How We Score", description: "How we score risk", path: "/research/methodology" },
5864
{ icon: "benchmarks", label: "Benchmarks", description: "Industry trends & scoring", path: "/research/benchmarks" },
59-
{ icon: "compare", label: "Compare Scanners", description: "ExtensionShield vs alternatives", path: "/compare" }
65+
{ icon: "compare", label: "Compare Tools", description: "Security tool comparison", path: "/compare" }
6066
]
6167
},
6268
{
@@ -157,6 +163,7 @@ export const footerConfig = {
157163
{
158164
heading: "Product",
159165
links: [
166+
{ label: "Free Extension Scanner", path: "/free-extension-scanner" },
160167
{ label: "Risk Check (Free)", path: "/scan" },
161168
{ label: "Private Build Audit (Pro)", path: "/scan/upload" },
162169
{ label: "Extension Security", path: "/extension-security" },

0 commit comments

Comments
 (0)