Skip to content

feat: A/B/C test for homepage 2026 redesign#17294

Merged
pettinarip merged 13 commits into
home-redesignfrom
home-redesign-ab-test
Feb 18, 2026
Merged

feat: A/B/C test for homepage 2026 redesign#17294
pettinarip merged 13 commits into
home-redesignfrom
home-redesign-ab-test

Conversation

@pettinarip
Copy link
Copy Markdown
Member

@pettinarip pettinarip commented Feb 12, 2026

Summary

  • Adds A/B/C testing infrastructure for the homepage 2026 redesign
  • Variant A: Original homepage (control)
  • Variant B: Redesigned homepage with persona modal flow
  • Variant C: Redesigned homepage with direct action buttons (no modal)
  • Uses dynamic site URL detection for proper tracking in branch/preview deploys
  • Polishes hero CTA buttons to match Figma design specifications

Test plan

  • Verify A/B/C test panel appears in development/preview environments
  • Test variant switching works correctly via debug panel
  • Confirm Matomo tracking fires for each variant
  • Check dynamic URL detection works on Netlify preview deploys
  • Verify hero CTA button styling matches Figma design

@github-actions github-actions Bot added the tooling 🔧 Changes related to tooling of the project label Feb 12, 2026
@pettinarip pettinarip force-pushed the home-redesign-ab-test branch from 54b830c to 66f53c0 Compare February 12, 2026 20:24
@netlify
Copy link
Copy Markdown

netlify Bot commented Feb 12, 2026

Deploy Preview for ethereumorg ready!

Name Link
🔨 Latest commit a31cb08
🔍 Latest deploy log https://app.netlify.com/projects/ethereumorg/deploys/69933ccdaa5d532c47970453
😎 Deploy Preview https://deploy-preview-17294.ethereum.it
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
7 paths audited
Performance: 49 (🔴 down 6 from production)
Accessibility: 94 (no change from production)
Best Practices: 100 (no change from production)
SEO: 100 (no change from production)
PWA: 59 (no change from production)
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

@konopkja
Copy link
Copy Markdown
Contributor

SimulatorSection: eventCategory prop is accepted but never used

In src/components/Homepage/SimulatorSection/index.tsx, the eventCategory prop is defined in the type but never destructured or passed to child components:

type SimulatorSectionProps = {
  className?: string
  eventCategory?: string  // ← defined here
}

const SimulatorSection = ({ className }: SimulatorSectionProps) => {
//                          ^ eventCategory not destructured

This means the simulator's internal interactions (step navigation buttons, finalCtaLink at the end of the walkthrough) have no event tracking from the homepage context. The TrackedSection wrapper catches the section_view, but individual clicks inside the simulator are invisible to analytics.

Not a blocker for launch, but worth fixing so we can measure simulator engagement across the A/B/C variations.

@konopkja
Copy link
Copy Markdown
Contributor

SEO Blocker: Bots must always receive the Original variant

@pettinarip — heads up, this needs to be addressed before we activate the experiment.

Problem

The current assignment logic in src/lib/ab-testing/server.ts hashes Googlebot like any regular visitor. Since Googlebot has a consistent IP + User-Agent, it will deterministically land on one specific variant for the entire test.

The redesigned homepage has substantially different content — different headings, different sections (KPI, Savings Carousel, Feature Cards vs the current What is Ethereum, Activity, Builders, etc.). If Googlebot is assigned to a redesign variant:

  • Google re-indexes the homepage with completely different content
  • Search snippets change
  • Temporary ranking fluctuation during test
  • Content changes again when the test ends → double disruption

Fix

Add bot detection at the top of getABTestAssignment() in src/lib/ab-testing/server.ts. This is not cloakingGoogle's A/B testing guidelines explicitly allow serving the original to bots during experiments.

const BOT_PATTERN = /googlebot|bingbot|yandex|baiduspider|duckduckbot|slurp/i

export const getABTestAssignment = async (
  testKey: string
): Promise<ABTestAssignment | null> => {
  const configs = await getABTestConfigs()
  const testConfig = configs[testKey]

  if (!testConfig || !testConfig.enabled) return null

  const headers = await import("next/headers").then((m) => m.headers())
  const userAgent = headers.get("user-agent") || ""

  // Always serve Original to search engine bots to prevent
  // indexing fluctuation during A/B tests. Not cloaking per Google guidelines.
  if (BOT_PATTERN.test(userAgent)) return null

  // ... rest of fingerprint + assignment logic unchanged ...
}

Returning null triggers the existing fallback in ABTestWrapper which renders variants[0] (Original). No other changes needed.

What's already fine

  • ✅ Canonical URL is the same for all variants (https://ethereum.org/en/)
  • ✅ No separate URLs per variant
  • ✅ hreflang tags unchanged
  • ✅ JSON-LD rendered outside ABTestWrapper (same for all)

This is the only remaining SEO concern — everything else looks good.

Add bot detection to prevent search engine indexing fluctuation
and ensure consistent social media link previews during A/B tests.
Bots receive the original variant per Google's A/B testing guidelines.

Ref: https://developers.google.com/search/docs/advanced/guidelines/cloaking
@pettinarip
Copy link
Copy Markdown
Member Author

@konopkja good catch, pushed the patch. Also extend it to catch social engines to deliver a consistent OG preview when sharing the link.

@konopkja
Copy link
Copy Markdown
Contributor

⚠️ getAccountHolders() failure can crash the homepage for all variants

The new getAccountHolders() call was added to the main Promise.all in page.tsx, and if it fails (Dune API timeout, rate limit, outage), the page throws:

if (!accountHolders || "error" in accountHolders) {
  throw new Error("Failed to fetch account holders data")
}

This is on the critical path for every homepage visitor, including Variant A (Original) which doesn't use this data at all. A Dune API outage during the test would take down the entire homepage — not just the redesign variants.

Suggestion: Degrade gracefully instead of throwing. The KPI counters in the redesign can show a fallback (e.g. 0 or a static cached value) while the Original variant continues working unaffected:

// Instead of throwing:
const accountHoldersValue =
  accountHolders && !("error" in accountHolders) ? accountHolders.value : 0
const transactionsToday =
  growThePieData && "value" in growThePieData.txCount
    ? growThePieData.txCount.value
    : 0

This way, if Dune is down, the redesign variants show 0 for the KPI counters (or you could hide them) but the page still renders for all three variants.

@wackerow
Copy link
Copy Markdown
Member

Security Review

PR: feat: A/B/C test for homepage 2026 redesign (#17294)
Reviewed: 2026-02-17
Risk: LOW

Findings

[LOW] Matomo analytics enabled on preview deploys

File: src/components/Matomo.tsx:10-18, app/api/ab-config/route.ts:36
Issue: The IS_PREVIEW_DEPLOY guard was removed from Matomo initialization and the AB config route. Preview and branch deploys will now send analytics events to the production Matomo instance, potentially polluting production data with test traffic.
Recommendation: Confirm this is intentional for A/B testing on preview deploys. If preview analytics should be isolated, consider a separate Matomo site ID for preview environments.


Areas Reviewed

  • API Route Security
  • SSRF & External Fetching
  • XSS & Content Injection
  • Security Headers & Transport
  • Secrets & Configuration

Not applicable: GitHub Workflow Security, Dependencies & Supply Chain

Limitations

  • Cannot verify runtime values of Netlify environment variables (DEPLOY_PRIME_URL, DEPLOY_URL, URL) used in the new SITE_URL fallback chain.
  • The home-redesign base branch was not fully reviewed — only changes introduced by this PR were evaluated.

🤖 Review performed by Claude Opus 4.6 (claude-opus-4-6)

@pettinarip
Copy link
Copy Markdown
Member Author

Security Review

PR: feat: A/B/C test for homepage 2026 redesign (#17294) Reviewed: 2026-02-17 Risk: LOW

Findings

[LOW] Matomo analytics enabled on preview deploys

File: src/components/Matomo.tsx:10-18, app/api/ab-config/route.ts:36 Issue: The IS_PREVIEW_DEPLOY guard was removed from Matomo initialization and the AB config route. Preview and branch deploys will now send analytics events to the production Matomo instance, potentially polluting production data with test traffic. Recommendation: Confirm this is intentional for A/B testing on preview deploys. If preview analytics should be isolated, consider a separate Matomo site ID for preview environments.

Areas Reviewed

  • API Route Security
  • SSRF & External Fetching
  • XSS & Content Injection
  • Security Headers & Transport
  • Secrets & Configuration

Not applicable: GitHub Workflow Security, Dependencies & Supply Chain

Limitations

  • Cannot verify runtime values of Netlify environment variables (DEPLOY_PRIME_URL, DEPLOY_URL, URL) used in the new SITE_URL fallback chain.
  • The home-redesign base branch was not fully reviewed — only changes introduced by this PR were evaluated.

🤖 Review performed by Claude Opus 4.6 (claude-opus-4-6)

we are using a different Matomo site id for non-prod envs.

@pettinarip pettinarip merged commit 86571f4 into home-redesign Feb 18, 2026
6 checks passed
@pettinarip pettinarip deleted the home-redesign-ab-test branch February 18, 2026 11:00
@pettinarip pettinarip mentioned this pull request Feb 19, 2026
@pettinarip pettinarip mentioned this pull request Feb 27, 2026
pettinarip added a commit that referenced this pull request Mar 9, 2026
The A/B test has concluded. This reverts the test infrastructure from
#17261 and #17294 while preserving the Homepage2026 component code.

Changes reverted:
- Remove ABTestWrapper, ScrollDepthTracker, TrackedSection wrappers
- Remove force-dynamic rendering and .catch() graceful degradation
- Restore original error handling (throw on missing data)
- Restore original event names and action labels
- Remove getAccountHolders fetch (only used by redesign variants)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

tooling 🔧 Changes related to tooling of the project

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants