From 620293451ce003fec76a41acf21fcb5f76c39356 Mon Sep 17 00:00:00 2001 From: mohanadft Date: Mon, 13 Jul 2026 16:53:30 +0300 Subject: [PATCH 1/4] feat(seo): add sitewide Organization schema and noindex support to HomeLayout Adds NonprofitOrganization JSON-LD (EIN, address, sameAs social links) so every -new draft page and 404 gets machine-readable entity data, and a noindex prop so draft pages can opt out of indexing via robots meta. --- src/layouts/HomeLayout.astro | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/layouts/HomeLayout.astro b/src/layouts/HomeLayout.astro index 7de8cf0..0782c5e 100644 --- a/src/layouts/HomeLayout.astro +++ b/src/layouts/HomeLayout.astro @@ -11,12 +11,14 @@ interface Props { title: string; description?: string; image?: string; + noindex?: boolean; } const { title, description = "T4P is an incubator for Palestine advocacy projects.", image = "https://techforpalestine.org/t4p-social-logo.png", + noindex = false, } = Astro.props; const membershipLive = getEnv("MEMBERSHIP_LIVE", Astro.locals) === "true"; @@ -25,6 +27,30 @@ const canonicalUrl = new URL( Astro.url.pathname, Astro.site || "https://techforpalestine.org" ).toString(); + +const organizationSchema = { + "@context": "https://schema.org", + "@type": "NonprofitOrganization", + name: "Tech for Palestine", + url: "https://techforpalestine.org", + logo: "https://techforpalestine.org/t4p-social-logo.png", + taxID: "99-3441367", + address: { + "@type": "PostalAddress", + streetAddress: "548 Market St #266950", + addressLocality: "San Francisco", + addressRegion: "CA", + postalCode: "94104-5401", + addressCountry: "US", + }, + sameAs: [ + "https://www.instagram.com/techforpalestine", + "https://twitter.com/tech4palestine", + "https://github.com/TechForPalestine/", + "https://www.linkedin.com/company/techforpalestine/", + "https://infosec.exchange/@tech4palestine", + ], +}; --- @@ -39,6 +65,7 @@ const canonicalUrl = new URL( + {noindex && } -`** @@ -90,15 +90,14 @@ import "../styles/base.css"; Locate the closing `` tag in `src/pages/index.astro` and insert the tracking script immediately before it: ```astro - - + ``` The guard `v === "control"` ensures the event only fires for users who were properly assigned through the A/B test (not someone who cleared their storage mid-session). @@ -106,6 +105,7 @@ The guard `v === "control"` ensures the event only fires for users who were prop - [ ] **Step 3: Verify locally** Start the dev server: + ```bash pnpm dev ``` @@ -113,6 +113,7 @@ pnpm dev Open `http://localhost:4321` in a browser with devtools open. **Test A — variant assignment:** + 1. Open Application → Local Storage → `http://localhost:4321` 2. Confirm `ab-homepage-variant` is absent 3. Hard-reload the page several times @@ -121,12 +122,14 @@ Open `http://localhost:4321` in a browser with devtools open. 6. If `"control"`: confirm the homepage renders normally **Test B — stickiness:** + 1. Set `ab-homepage-variant` to `"variant"` manually in devtools 2. Navigate to `/` — should immediately redirect to `/home-new` 3. Set `ab-homepage-variant` to `"control"` manually 4. Navigate to `/` — should stay on `/` **Test C — Plausible event (control):** + 1. Set `ab-homepage-variant` to `"control"` 2. Navigate to `/` 3. Open Console and run: `window.plausible.q` — confirm an entry for `"ab-homepage"` with `{ variant: "control" }` is queued @@ -143,9 +146,11 @@ git commit -m "feat(ab-test): add homepage A/B anti-flicker script and variant t ### Task 2: Plausible tracking on the variant page (`home-new.astro`) **Files:** + - Modify: `src/pages/home-new.astro` **Context:** + - `HomeLayout.astro` initialises the Plausible queue in the `` (line 169–181), before ``. Any ` - + ``` - [ ] **Step 2: Verify locally** @@ -170,18 +174,21 @@ Open `src/pages/home-new.astro`. Locate the closing `` tag and insert imm With the dev server running: **Test A — Plausible event fires for assigned variant users:** + 1. Set `ab-homepage-variant` to `"variant"` in devtools 2. Navigate to `/home-new` 3. Open Console, run: `window.plausible.q` 4. Confirm an entry for `"ab-homepage"` with `{ variant: "new" }` is queued **Test B — event does NOT fire for direct visitors:** + 1. Clear `ab-homepage-variant` from localStorage (or delete the key) 2. Navigate directly to `/home-new` 3. Open Console, run: `window.plausible.q` 4. Confirm NO `"ab-homepage"` entry is present **Test C — full flow end-to-end:** + 1. Clear all localStorage 2. Navigate to `/` 3. If redirected to `/home-new`: confirm `ab-homepage-variant === "variant"` and Plausible event queued with `variant: "new"` @@ -216,6 +223,7 @@ Then in your dashboard reports, filter by the `variant` property to compare beha When you have a winner: **If `variant` wins (new design):** + ```bash # 1. Replace index.astro content with home-new.astro content # 2. Delete home-new.astro @@ -226,6 +234,7 @@ echo "/home-new / 301" >> public/_redirects ``` **If `control` wins (old design):** + ```bash # 1. Remove the anti-flicker script and tracking script from index.astro # 2. Delete home-new.astro diff --git a/docs/superpowers/specs/2026-06-30-homepage-ab-test-design.md b/docs/superpowers/specs/2026-06-30-homepage-ab-test-design.md index b6d2ffb..f071522 100644 --- a/docs/superpowers/specs/2026-06-30-homepage-ab-test-design.md +++ b/docs/superpowers/specs/2026-06-30-homepage-ab-test-design.md @@ -17,6 +17,7 @@ Run a controlled A/B test comparing the current homepage design (control) agains **Option chosen:** Client-side anti-flicker inline script with localStorage for sticky assignment. **Why:** + - PECR compliance — localStorage is not a cookie; no consent banner required under UK law - Consistent with existing A/B test patterns in the codebase (`donate-new.astro`, `MembershipPage.tsx`) - No infrastructure changes — no middleware, no Cloudflare Workers, no new dependencies @@ -45,24 +46,24 @@ Both / and /home-new ## Assignment Properties -| Property | Value | -|---|---| -| localStorage key | `ab-homepage-variant` | -| Possible values | `control`, `variant` | -| Split | 50/50 (`Math.random() < 0.5`) | -| Persistence | Until localStorage is cleared | +| Property | Value | +| ----------------- | --------------------------------------- | +| localStorage key | `ab-homepage-variant` | +| Possible values | `control`, `variant` | +| Split | 50/50 (`Math.random() < 0.5`) | +| Persistence | Until localStorage is cleared | | Private/incognito | Re-randomised each session (acceptable) | --- ## Edge Cases -| Scenario | Behaviour | -|---|---| -| User lands on `/about` first, then `/` | Assigned on first visit to `/` — correct | -| User lands directly on `/home-new` | Sees new design unassigned; assigned on next `/` visit | +| Scenario | Behaviour | +| ------------------------------------------------ | --------------------------------------------------------------------- | +| User lands on `/about` first, then `/` | Assigned on first visit to `/` — correct | +| User lands directly on `/home-new` | Sees new design unassigned; assigned on next `/` visit | | `control` user navigates manually to `/home-new` | Sees new design — acceptable edge case, negligible statistical impact | -| JS disabled | Always sees control (no redirect fires) | +| JS disabled | Always sees control (no redirect fires) | --- @@ -71,9 +72,9 @@ Both / and /home-new Plausible Analytics is already set up. Variant exposure is recorded via a custom event on both pages: ```js -window.plausible('ab-homepage', { props: { variant: 'control' } }) +window.plausible("ab-homepage", { props: { variant: "control" } }); // or -window.plausible('ab-homepage', { props: { variant: 'new' } }) +window.plausible("ab-homepage", { props: { variant: "new" } }); ``` In the Plausible dashboard: create a custom event goal named `ab-homepage`, then filter by the `variant` property to compare engagement between groups. @@ -82,10 +83,10 @@ In the Plausible dashboard: create a custom event goal named `ab-homepage`, then ## Files Changed -| File | Change | -|---|---| -| `src/pages/index.astro` | Add anti-flicker ` diff --git a/src/components/home/FooterSection.astro b/src/components/home/FooterSection.astro index 840b967..da1fe49 100644 --- a/src/components/home/FooterSection.astro +++ b/src/components/home/FooterSection.astro @@ -44,16 +44,32 @@ const socials: { name: string; url: string; icon: string }[] = [ { name: "Twitter", url: "https://twitter.com/tech4palestine", icon: "mdi:twitter" }, { name: "YouTube", url: "https://www.youtube.com/@tech4palestine", icon: "mdi:youtube" }, { name: "GitHub", url: "https://github.com/TechForPalestine/", icon: "mdi:github" }, - { name: "LinkedIn", url: "https://www.linkedin.com/company/techforpalestine/", icon: "mdi:linkedin" }, - { name: "Discord", url: "https://techforpalestine.org/discord-invite", icon: "ic:baseline-discord" }, + { + name: "LinkedIn", + url: "https://www.linkedin.com/company/techforpalestine/", + icon: "mdi:linkedin", + }, + { + name: "Discord", + url: "https://techforpalestine.org/discord-invite", + icon: "ic:baseline-discord", + }, { name: "Mastodon", url: "https://infosec.exchange/@tech4palestine", icon: "mdi:mastodon" }, { name: "TikTok", url: "https://www.tiktok.com/@techforpalestine", icon: "ic:baseline-tiktok" }, - { name: "Bluesky", url: "https://bsky.app/profile/techforpalestine.org", icon: "simple-icons:bluesky" }, - { name: "UpScrolled", url: "https://share.upscrolled.com/en/user/39494e76-22a4-47ee-a67d-cd7049835a53/", icon: "/upscrolled-icon.svg" }, + { + name: "Bluesky", + url: "https://bsky.app/profile/techforpalestine.org", + icon: "simple-icons:bluesky", + }, + { + name: "UpScrolled", + url: "https://share.upscrolled.com/en/user/39494e76-22a4-47ee-a67d-cd7049835a53/", + icon: "/upscrolled-icon.svg", + }, ]; --- -