UX Strategy — Conversion, Mobile, Accessibility

Events Discovery Page — UX Strategy & Conversion Optimization

Date: 2026-03-16 Status: Draft Scope: almaghrib.org events discovery page — static HTML+JS consuming public API Audience for this document: Engineering, product, and design stakeholders


Table of Contents

  1. Conversion Funnel Analysis
  2. Page Architecture & Information Hierarchy
  3. Social Proof & Urgency Patterns
  4. Mobile-First UX Strategy
  5. WhatsApp & Social Sharing Strategy
  6. SEO & Discoverability
  7. Accessibility Requirements
  8. Analytics & Measurement Plan
  9. Performance Budget
  10. Three Design Direction Concepts

1. Conversion Funnel Analysis

1.1 Entry Points & Optimization

Users arrive at this page from four primary channels, each with distinct intent and optimization needs:

Entry Point Est. Share Intent Optimization Strategy
WhatsApp share 40-50% "My friend sent me this event" — high intent for a specific event Deep link directly to the event card pre-expanded. Pre-filter to the shared event's city. Minimize steps between landing and "Register."
Email newsletter 25-30% "What's new this month?" — browsing intent, moderate commitment Landing with continent auto-detected via GeoIP. Show nearest events first. Subject line should match page headline for scent continuity.
Social media (Instagram, Facebook, X) 15-20% "This looks interesting" — low commitment, easily distracted Strong hero with clear value proposition. Single compelling event showcased. Fast load time critical (social media users bounce in <3 seconds).
Direct / organic search 5-10% "AlMaghrib events near me" — high intent, self-directed SEO-optimized title and meta. City name in URL if filtered. Structured data for Google Events rich results.

Cross-channel optimization principles:

1.2 Conversion Funnel Map

AWARENESS                    INTEREST                     DESIRE                       ACTION
─────────────────────────────────────────────────────────────────────────────────────────────────
Land on page ──► Scan events ──► Expand a card ──► Review details ──► Click "Register" ──► (off-site)
     │                │               │                  │                  │
     │                │               │                  │                  └─ Macro conversion
     │                │               │                  └─ Micro: scroll pricing, view instructor
     │                │               └─ Micro: expand card
     │                └─ Micro: use filter, scroll past fold
     └─ Entry (tracked by source)

1.3 Key Conversion Metrics

Metric Definition Target Why It Matters
Registration click-through rate (CTR) Clicks on "Register" / unique page visitors 8-12% Primary macro conversion. Users leave our page for almaghrib.org checkout.
Card expansion rate Cards expanded / unique visitors 35-50% Indicates the summary view is compelling enough to drive curiosity.
Filter engagement rate Visitors who use any filter / total visitors 25-40% Shows the navigation is discoverable and useful. Low rate means either auto-detection is perfect or filters are hidden.
Events-per-session Average unique cards expanded per session 1.5-2.5 Multiple expansions signal browsing behavior — the page is serving discovery well.
Share rate Share button clicks / unique visitors 3-5% Viral coefficient. Each share can bring 2-5 new visitors via WhatsApp group dynamics.
Bounce rate Single-page sessions with no interaction / total sessions < 40% High bounce = wrong audience, slow load, or unclear value proposition.
Time to first interaction Median time from page load to first click/tap < 5 seconds If users aren't interacting quickly, the page isn't immediately useful.

1.4 Drop-Off Risks & Mitigations

Funnel Stage Risk Severity Mitigation
Page load Slow load on mobile data (3G/4G) HIGH Performance budget: <2s first contentful paint. Skeleton screens. Defer non-critical images.
Page load User sees events in wrong continent HIGH GeoIP auto-detection with instant filter. Fallback: "All" view sorted by proximity.
Scanning Information overload (21+ events) MEDIUM Strong visual hierarchy. Continent grouping. Only 1-2 lines of text per card in summary.
Scanning No events in user's city MEDIUM Show nearest city events with distance indicator. "No events in [city] yet — here's what's nearby."
Card expand Card expansion feels heavy or slow MEDIUM CSS-only animation. No additional API calls. Content already loaded.
Detail review Pricing is confusing (multi-tier) HIGH Clear pricing table. Bold the current/best price. Strikethrough for higher tiers. "You save $X" callout.
Detail review No clear next step after reading HIGH Sticky "Register" CTA within expanded card. Repeat at top and bottom of detail view.
Register click User leaves page (external link) LOW Expected behavior — but open in new tab so user can return. Track as conversion.
Register click Fear of commitment / "I'll do it later" MEDIUM Add "Save" or "Share with friend" as soft CTAs. Calendar reminder link.

1.5 Micro vs. Macro Conversions

Micro-conversions (engagement signals):

Macro-conversions (business value):

The key insight: On a discovery page with external registration, our macro conversion is the "Register" click. We cannot track actual registration completion — that happens on almaghrib.org. This means our analytics must be exceptionally precise about click-through, because it is our last measurable touchpoint.


2. Page Architecture & Information Hierarchy

2.1 Hero Section Strategy

The hero section must accomplish three things in under 3 seconds:

  1. Confirm identity — "Yes, this is AlMaghrib events"
  2. Communicate value — "Find an event near you"
  3. Enable action — "Start browsing now"

Recommended hero design:

┌──────────────────────────────────────────────────────────────────┐
│  [AlMaghrib Logo]                                    [City: DC ▾]│
│                                                                  │
│         Find Your Next AlMaghrib Experience                      │
│         Weekend seminars, Ilm Nights, and more                   │
│         in 45+ cities worldwide                                  │
│                                                                  │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐           │
│  │   All    │ │ N.America│ │  Europe  │ │  Online  │           │
│  └──────────┘ └──────────┘ └──────────┘ └──────────┘           │
│                                                                  │
│  Ottawa  Boston  Calgary  Charlotte  Dallas  Houston  >>>        │
└──────────────────────────────────────────────────────────────────┘

Hero messaging principles:

What NOT to do in the hero:

2.2 Filter Bar Design Principles

The filter bar is the primary navigation for this page. It must be:

Immediate — Filters apply instantly, no "Apply" button. Client-side filtering with ~21 events is instantaneous.

Visible — Sticky on scroll (desktop and mobile). The user should always be able to change their view without scrolling back up.

Progressive — Two levels that reveal progressively:

  1. Continent tabs — Always visible. 3-4 tabs maximum (All, North America, Europe, plus Online if included). Use a segmented control pattern, not traditional tabs.
  2. City pills — Appear below continent tabs. Horizontal scrollable row. Highlight the auto-detected city. Show event count per city as a badge.

Forgiving — "All" is always available and always the widest view. There is no dead-end state.

Filter bar specifics:

Element Desktop Mobile
Continent tabs Full-width segmented control, all visible Full-width, same as desktop (3-4 tabs fit)
City pills Horizontal row, wrapping to 2 rows if needed Horizontal scroll with fade hint on right edge
Active state Bold text + underline + background color change Same, with slight haptic feedback feel
Event count Badge on each city pill ("Dallas (3)") Same
Sticky behavior Sticks below site header on scroll Sticks at top of viewport on scroll
Background White with subtle bottom shadow when stuck Same
Z-index Above cards, below modals Same

City pill sorting: Sort by event count descending, then alphabetically. Most active cities appear first. This creates a natural "popularity" signal.

GeoIP auto-selection: On page load, auto-select the user's continent and highlight (but don't auto-filter to) their nearest city. The city pill should be visually highlighted ("Your area") but the view should show all cities in the continent. Reason: auto-filtering to a single city can show as few as 1 event, which feels empty. Showing the continent with the nearest city highlighted gives context while keeping the page full.

2.3 Card Design Principles for Scannability

Each card must be scannable in under 2 seconds. The user should be able to decide "Is this for me?" from the summary alone.

Card information hierarchy (summary view):

┌─────────────────────────────────────────────────┐
│  ┌──────────┐                                   │
│  │          │  Fiqh of Salah                     │
│  │  Poster  │  with Sh. Yasir Qadhi             │
│  │  Image   │                                   │
│  │ 250x375  │  📍 Houston, TX                    │
│  │ (cropped │  📅 Apr 12-13 (Sat-Sun)            │
│  │  to fit) │                                   │
│  └──────────┘  🎓 2 credits                      │
│                                                  │
│  ┌────────────┐  ┌──────────────────────┐       │
│  │  $99 Early │  │  47 students enrolled │       │
│  │  Bird ✨   │  └──────────────────────┘       │
│  └────────────┘                                  │
│                                      [View ▾]    │
└─────────────────────────────────────────────────┘

Summary card must include:

  1. Event image (poster 250x375, cropped/scaled) — visual anchor, aids recognition for returning visitors
  2. Title (heading) — largest text, bold, 1 line max with ellipsis
  3. Instructor — name only, small text, with tiny avatar if available (skip default placeholder avatars)
  4. Location — city + country (or state for US/Canada)
  5. Date — formatted as "Apr 12-13 (Sat-Sun)" — day-of-week is critical for weekend seminars
  6. Credits — small badge, only if > 0
  7. Price — show the lowest available price prominently ("From $99")
  8. Social proof — registration count if > 20 (hide if low to avoid negative social proof)
  9. Expand trigger — subtle "View Details" or chevron

What to EXCLUDE from summary (save for expanded view):

Card design rules:

2.4 Expanded Detail View Strategy

When a card is expanded, it should feel like the same card opened up — not a new page or modal.

Recommended pattern: Inline expansion (accordion)

Reasons to prefer inline over modal:

Expanded view layout:

┌──────────────────────────────────────────────────────────────────┐
│  ┌──────────────────────────────────────────────────────────┐   │
│  │                    Background Image (960x600)             │   │
│  │                    with dark gradient overlay              │   │
│  │                                                           │   │
│  │    Fiqh of Salah                                         │   │
│  │    Purification of the Soul Through Prayer                │   │
│  │    with Sheikh Yasir Qadhi                               │   │
│  └──────────────────────────────────────────────────────────┘   │
│                                                                  │
│  ┌──────────────────┐  ┌──────────────────────────────────┐    │
│  │ 📅 Dates         │  │ Description                      │    │
│  │ Apr 12-13, 2026  │  │ Lorem ipsum dolor sit amet,     │    │
│  │ Sat 10am-6pm     │  │ consectetur adipiscing elit.     │    │
│  │ Sun 10am-5pm     │  │ Sed do eiusmod tempor...         │    │
│  │                  │  │                                   │    │
│  │ 📍 Venue         │  │ [Read more]                      │    │
│  │ Marriott Houston │  │                                   │    │
│  │ 123 Main St      │  └──────────────────────────────────┘    │
│  │                  │                                           │
│  │ 🎓 2 Credits     │  ┌──────────────────────────────────┐    │
│  │                  │  │ Instructor                        │    │
│  │ 👥 47 enrolled   │  │ [Avatar] Sheikh Yasir Qadhi      │    │
│  └──────────────────┘  │ Brief bio line...                │    │
│                         └──────────────────────────────────┘    │
│                                                                  │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │  Pricing                                                  │   │
│  │  ┌────────────┐ ┌────────────┐ ┌────────────┐           │   │
│  │  │ Early Bird │ │  Standard  │ │  Special   │           │   │
│  │  │   $99 ✨   │ │    $129    │ │  Contact   │           │   │
│  │  │ Until Apr 1│ │            │ │            │           │   │
│  │  └────────────┘ └────────────┘ └────────────┘           │   │
│  └──────────────────────────────────────────────────────────┘   │
│                                                                  │
│  ┌──────────────────────┐  ┌──────────────┐  ┌────────────┐   │
│  │  Register Now  →     │  │  Share 🔗    │  │ Collapse ▲ │   │
│  └──────────────────────┘  └──────────────┘  └────────────┘   │
└──────────────────────────────────────────────────────────────────┘

Expanded view must include:

  1. Background image (960x600) as a visual header within the expanded card
  2. Full title + subtitle (heading + sub_heading)
  3. Full description (truncated to ~3 lines with "Read more" for very long descriptions)
  4. Instructor section — avatar (if not placeholder), name, brief bio if available
  5. Date and schedule details — full date range with day-of-week and times with timezone
  6. Venue — name and address from event_schedule_venue
  7. Credits — with brief explanation of what credits mean
  8. Pricing breakdown — all tiers in a clear comparison layout
  9. Registration count — "47 students registered" with context
  10. Primary CTA — "Register Now" button, full-width on mobile, linking to site_url
  11. Secondary CTAs — Share button, "Add to Calendar" link
  12. Collapse trigger — clear way to close the expanded view

Scroll behavior on expand: When a card expands, smooth-scroll so the top of the expanded card is at the top of the viewport (accounting for sticky filter bar). This prevents the user from losing their place.

Only one card expanded at a time. Expanding a new card collapses the previously expanded one. Reason: performance on mobile, and it maintains a clear mental model.

2.5 Footer & Secondary Content

The footer should be minimal — this is a task-oriented page, not a content page.

Footer contents:

No newsletter signup in footer — the page's goal is event registration. Adding a secondary conversion dilutes focus.

"Don't see your city?" link is strategically important: it converts a dead-end (no events in my area) into a positive engagement signal and gives the org demand data for expansion planning.


3. Social Proof & Urgency Patterns

3.1 Registration Count Display

The total_attendees field is a powerful social proof signal, but it must be used carefully:

Attendee Count Display Strategy Rationale
0-9 Hide entirely Low numbers create negative social proof. "3 students registered" says "nobody wants this."
10-29 Show as "Students are registering" (no number) Signals activity without exposing the low count.
30-99 Show exact number: "47 students registered" Credible social proof. Large enough to be meaningful, specific enough to be believable.
100-499 Show rounded: "100+ students registered" At this scale, precision doesn't matter. Round number feels bigger.
500+ Show with emphasis: "500+ students registered" with a visual highlight This is a blockbuster event. Make it a badge or callout.

Placement: In both summary card (small text near bottom) and expanded view (prominent position near pricing).

Formatting: Use the word "students" not "attendees" or "registrations" — "students" reinforces the educational identity and creates in-group belonging.

3.2 Pricing Urgency

Multi-tier pricing (early bird, standard, special) is a natural urgency driver. Use it explicitly:

On summary card:

In expanded view:

Pricing display rules:

3.3 Instructor Reputation

Instructors are the primary draw for many AlMaghrib students. The instructor signal should be:

On summary card:

In expanded view:

Instructor as a filter (Phase 2 consideration):

3.4 Credits as Value Signal

Credits (credits field) are meaningful to returning AlMaghrib students but opaque to newcomers.

Display strategy:

Positioning: Credits are a differentiator from competing Islamic education events. For returning students, it reinforces the unique value. For new students, it signals academic rigor without being intimidating.

3.5 Scarcity Indicators

Use scarcity sparingly and honestly. Manufactured scarcity destroys trust, especially in a faith-based community.

Appropriate scarcity signals:

Never use:

Tone calibration: AlMaghrib's audience trusts the brand. Social proof and urgency should feel like helpful information ("here's what others are doing, here's how to save money") not like pressure ("act now or lose out!"). An Islamic education institute should feel trustworthy, not like a flash-sale site.


4. Mobile-First UX Strategy

4.1 Mobile Filter Design

Given 60-70% mobile traffic from WhatsApp and email, the filter experience must be thumb-native.

Recommended pattern: Persistent horizontal scroll (NOT bottom sheet or dropdown)

Rationale:

Mobile filter implementation:

┌─────────────────────────────────────────┐
│  [All] [N.America ✓] [Europe] [Online]  │  ← Continent: full-width, all visible
├─────────────────────────────────────────┤
│  Ottawa  Boston  Calgary  Dallas  Hou >>>│  ← City: horizontal scroll, fade right
└─────────────────────────────────────────┘

Specific mobile filter rules:

Auto-scroll to nearest city: On first load, after GeoIP detection, auto-scroll the city pill row so the nearest city is visible (centered if possible). Add a subtle "Near you" label or location pin icon on the detected city.

4.2 Mobile Card Layout

Single-column, full-width cards:

┌─────────────────────────────────────┐
│  ┌─────────────────────────────┐    │
│  │     Poster Image             │    │
│  │     (full-width, 16:9 crop)  │    │
│  └─────────────────────────────┘    │
│                                      │
│  Fiqh of Salah                       │
│  with Sh. Yasir Qadhi                │
│                                      │
│  📍 Houston, TX  ·  📅 Apr 12-13    │
│  🎓 2 credits   ·  From $99         │
│                                      │
│  47 students registered              │
│                                      │
│  [View Details ▾]                    │
└─────────────────────────────────────┘

Mobile card specifics:

Mobile expanded view:

4.3 Touch Targets & Gestures

Element Minimum Size Gesture Notes
Continent tab 44x44px Tap Full-width segments, ample spacing
City pill 44x36px min Tap + horizontal swipe for scroll Pill padding: 12px horizontal, 8px vertical
Event card (summary) Full-width Tap anywhere to expand Entire card is a tap target
"Register Now" button Full-width x 48px Tap Primary green/purple CTA color
Share button 44x44px Tap Opens native share sheet on mobile
Collapse chevron 44x44px Tap Large target, positioned in easy thumb zone
Card image Full-width None (no pinch-zoom needed) Images are decorative, not informational

Gestures to support:

4.4 Sticky Elements Strategy

Mobile viewport is precious. Be extremely selective about what sticks.

Sticky elements on mobile (max 2):

  1. Filter bar (continent tabs + city pills) — sticks at top. ~88px.
  2. "Register Now" button — sticks at bottom ONLY when an expanded card is in view. ~60px with padding.

NOT sticky:

Total sticky real estate: 88px (top) + 60px (bottom, conditional) = 148px max, leaving ~500px+ for content on a standard phone (667px viewport). This is within acceptable limits.

4.5 Performance Considerations for Mobile

Concern Strategy
Image loading Lazy load all images below the fold. First 3 cards load eagerly. Use loading="lazy" attribute.
Image sizing Serve poster (250x375) for card thumbnails, background (960x600) only when card is expanded. On mobile: use background image for summary too (cropped), but at reduced quality via CDN transform if available.
Initial payload Single API call returns all ~21 events. Response is ~50-100KB JSON. This is acceptable even on 3G.
JavaScript Minimal JS: fetch, filter, expand/collapse. No framework needed (vanilla JS or Preact at ~3KB). Target: <30KB JS total, gzipped.
CSS Inline critical CSS in <head> for above-fold content. Remainder in a small external file. Target: <10KB CSS total.
Skeleton screens Show 3 placeholder card outlines (gray rectangles) while API data loads. Shows structure immediately.
Font loading Use system font stack (-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif) for body text. Only load a custom font (if needed) for headings, and use font-display: swap.
Touch responsiveness No touch delay (use touch-action: manipulation on interactive elements). Instant visual feedback on tap (opacity change or background color shift).
Offline consideration Not required for v1, but the page should show a graceful error if the API call fails: "Unable to load events. Please check your connection and try again." with a retry button.

5. WhatsApp & Social Sharing Strategy

5.1 Open Graph Meta Tags Specification

Every shared link from this page must generate an attractive, informative preview card.

Default page meta (no specific event selected):

<meta property="og:type" content="website" />
<meta property="og:site_name" content="AlMaghrib Institute" />
<meta property="og:title" content="Upcoming Events — AlMaghrib Institute" />
<meta property="og:description" content="Browse weekend seminars, Ilm Nights, and more in 45+ cities. Find an event near you." />
<meta property="og:image" content="https://public.assets.almaghrib.org/events-page/og-default.jpg" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:url" content="https://almaghrib.org/events" />

<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="Upcoming Events — AlMaghrib Institute" />
<meta name="twitter:description" content="Browse weekend seminars, Ilm Nights, and more in 45+ cities." />
<meta name="twitter:image" content="https://public.assets.almaghrib.org/events-page/og-default.jpg" />

Per-event shared link meta (dynamically set via JS):

When a user shares a specific event (via the share button), the URL should include the event ID as a parameter. Since this is a static page, Open Graph tags cannot be truly dynamic server-side. Two approaches:

Option A (Recommended for v1): Server-side redirect page Create a lightweight server-side endpoint (e.g., PHP, Node, or Cloudflare Worker) at /events/share/{event_id} that:

  1. Reads the event ID from the URL
  2. Fetches event data from the API
  3. Returns an HTML page with correct OG tags for that event
  4. Includes a JavaScript redirect to the main events page with the event pre-selected

This is the only way to get correct WhatsApp/social previews per event, because crawlers do not execute JavaScript.

Option B (Simpler but limited): Generic OG tags with smart URL Use the default OG tags (above) for all shares. The share URL includes event parameters (?event=123&city=houston) so the page can pre-filter. The preview will always show the generic events page image, not the specific event.

Recommendation: Start with Option B, move to Option A if share-driven traffic becomes significant (>20% of total).

5.2 Share Button Placement & Design

Placement (two locations):

  1. Inside expanded card — Primary share location. Next to "Register Now" button. Users share after reading details.
  2. On summary card — Small share icon (top-right corner or bottom row). For quick sharing without expanding.

Design:

The share button should NOT:

5.3 Deep Linking Strategy

URL parameter scheme:

https://almaghrib.org/events                        → Default view (all events, GeoIP auto-select)
https://almaghrib.org/events?continent=north-america → Pre-filtered to North America
https://almaghrib.org/events?city=houston            → Pre-filtered to Houston
https://almaghrib.org/events?event=1234              → Scrolls to and auto-expands event 1234
https://almaghrib.org/events?city=houston&event=1234 → Filters to Houston, expands event 1234
https://almaghrib.org/events?type=weekend-seminars   → Pre-filtered to weekend seminars (Phase 2)

Implementation rules:

WhatsApp deep link construction: When a user shares via WhatsApp, the share should include:

5.4 WhatsApp Share Message Format

WhatsApp is the primary sharing channel. The share message should be formatted for maximum click-through in a chat context.

Template for sharing a specific event:

📚 *{Event Title}*
🎓 with {Instructor Name}

📍 {City} — {Date Range}
💰 From {Lowest Price}

{X} students already registered!

🔗 {URL with event parameter}

Example:

📚 *Fiqh of Salah*
🎓 with Sh. Yasir Qadhi

📍 Houston, TX — Apr 12-13 (Sat-Sun)
💰 From $99 (Early Bird)

47 students already registered!

🔗 https://almaghrib.org/events?event=1234&city=houston

Implementation:

const shareText = `📚 *${event.heading}*\n🎓 with ${event.instructors[0]?.name}\n\n📍 ${event.city} — ${formatDateRange(event)}\n💰 From ${getLowestPrice(event)}\n\n${event.total_attendees > 20 ? event.total_attendees + ' students already registered!\n\n' : ''}🔗 ${shareUrl}`;

if (navigator.share) {
  navigator.share({ text: shareText, url: shareUrl });
} else {
  // Fallback: copy to clipboard
  navigator.clipboard.writeText(shareText + '\n' + shareUrl);
}

WhatsApp-specific formatting notes:

5.5 Social Preview Image

For the best WhatsApp/social preview, create a default OG image:

Specifications:


6. SEO & Discoverability

6.1 Schema.org Event Structured Data

Add JSON-LD structured data for each event on the page. This enables Google Events rich results — a significant traffic driver for "islamic events near me" and similar queries.

Schema specification per event:

{
  "@context": "https://schema.org",
  "@type": "EducationEvent",
  "name": "{heading}",
  "description": "{description (first 200 chars)}",
  "startDate": "{datetime_start in ISO 8601}",
  "endDate": "{datetime_end in ISO 8601}",
  "eventStatus": "https://schema.org/EventScheduled",
  "eventAttendanceMode": "https://schema.org/OfflineEventAttendanceMode",
  "location": {
    "@type": "Place",
    "name": "{event_schedule_venue name}",
    "address": {
      "@type": "PostalAddress",
      "addressLocality": "{city}",
      "addressCountry": "{country}"
    }
  },
  "organizer": {
    "@type": "Organization",
    "name": "AlMaghrib Institute",
    "url": "https://almaghrib.org"
  },
  "performer": [
    {
      "@type": "Person",
      "name": "{instructors[0].name}",
      "image": "{instructors[0].avatar}"
    }
  ],
  "image": "{image_bg}",
  "offers": {
    "@type": "AggregateOffer",
    "lowPrice": "{lowest price}",
    "highPrice": "{highest price}",
    "priceCurrency": "{currency}",
    "availability": "https://schema.org/InStock",
    "url": "{site_url}"
  },
  "maximumAttendeeCapacity": null,
  "remainingAttendeeCapacity": null
}

Implementation consideration: Since this is client-side rendered, Google may or may not execute the JavaScript to see the structured data. Two mitigations:

  1. Inject JSON-LD via JavaScript after data loads. Googlebot does render JavaScript for major sites. Since almaghrib.org is an established domain, this should work.
  2. Server-side render the JSON-LD (if available via WordPress template or Cloudflare Worker). This guarantees Googlebot sees the structured data regardless of JS execution.

Wrap all events in an ItemList schema:

{
  "@context": "https://schema.org",
  "@type": "ItemList",
  "name": "Upcoming AlMaghrib Events",
  "numberOfItems": 21,
  "itemListElement": [
    {
      "@type": "ListItem",
      "position": 1,
      "item": { /* EducationEvent schema above */ }
    }
  ]
}

6.2 Meta Tag Strategy

<title>Upcoming Islamic Events & Seminars — AlMaghrib Institute</title>
<meta name="description" content="Browse upcoming AlMaghrib weekend seminars, Ilm Nights, and community events in 45+ cities across North America and Europe. Find events near you and register today." />
<meta name="keywords" content="AlMaghrib, Islamic events, weekend seminars, Islamic education, Ilm Night, Muslim events" />
<link rel="canonical" href="https://almaghrib.org/events" />

<!-- Geo targeting -->
<meta name="geo.placename" content="Global" />

<!-- Pagination / filtering (for crawlers) -->
<link rel="alternate" href="https://almaghrib.org/events?continent=north-america" hreflang="en" />
<link rel="alternate" href="https://almaghrib.org/events?continent=europe" hreflang="en" />

6.3 URL Structure Recommendations

URL Purpose
/events Main events page (canonical)
/events?continent=north-america Filtered view (parameter, not separate URL)
/events?city=houston City-filtered view
/events?event=1234 Direct link to specific event
/events/share/{event_id} Server-side share redirect (for OG tags, Phase 2)

Why parameters, not path segments:

Phase 2 consideration: If SEO becomes a priority, consider server-side rendering individual city pages (/events/houston) for better indexing and city-specific meta descriptions.

6.4 Internal Linking Strategy


7. Accessibility Requirements

7.1 WCAG 2.1 AA Checklist for This Page

Criterion Requirement Implementation
1.1.1 Non-text Content All images have alt text Event images: alt="{event title} poster". Instructor avatars: alt="{instructor name}". Decorative images: alt="".
1.3.1 Info and Relationships Structure conveyed through markup Filter tabs use role="tablist" and role="tab". Cards use <article>. Headings follow hierarchy (h1 for page title, h2 for event titles, h3 for sections within expanded cards).
1.3.2 Meaningful Sequence DOM order matches visual order Cards render in the same order they appear visually. Filter bar before cards in DOM.
1.4.1 Use of Color Color not sole visual means Active filter tab has bold text + underline + background change (not just color). Pricing urgency uses text labels, not just red/green.
1.4.3 Contrast (Minimum) 4.5:1 for normal text, 3:1 for large text Body text on white: use #24292f (GitHub's color, 14.5:1 ratio). Muted text: #57606a minimum (5.7:1). Price text: #1a7f37 on white for green (4.8:1).
1.4.4 Resize Text Page usable at 200% zoom Test at 200% — filter bar should not overflow, cards should reflow to single column.
1.4.10 Reflow No horizontal scroll at 320px width Single-column layout at 320px. City pills are the only horizontal scroll element (by design, with proper scroll affordance).
1.4.11 Non-text Contrast UI components 3:1 against background Card borders, button borders, filter tab outlines all meet 3:1 against background.
2.1.1 Keyboard All functionality available via keyboard Tab through filters, Enter/Space to activate. Tab through cards, Enter to expand. Tab through expanded content.
2.1.2 No Keyboard Trap Keyboard focus never trapped Expanding a card does not trap focus. Tab moves through expanded content and continues to next card. Escape collapses expanded card.
2.4.3 Focus Order Focus order matches logical sequence Tab order: filters → cards (top to bottom) → footer. Within expanded card: image → details → pricing → Register → Share → Collapse.
2.4.7 Focus Visible Visible focus indicator on all interactive elements Use a 2px solid outline in brand color (#7c3aed or similar purple) with 2px offset. Never use outline: none without a replacement.
3.2.1 On Focus No context change on focus alone Focusing a filter tab does not activate it. Only Enter/Space activates.
4.1.2 Name, Role, Value Custom components have proper ARIA Expandable cards use aria-expanded="true/false". Filter tabs use aria-selected. Registration counts use aria-label for screen reader context.

7.2 Screen Reader Considerations

Filter tabs:

<div role="tablist" aria-label="Filter events by continent">
  <button role="tab" aria-selected="true" aria-controls="events-panel" id="tab-all">
    All Events
  </button>
  <button role="tab" aria-selected="false" aria-controls="events-panel" id="tab-na">
    North America
  </button>
  <!-- ... -->
</div>

City pills (within the tab panel):

<div role="group" aria-label="Filter by city">
  <button role="button" aria-pressed="false" aria-label="Houston, 3 events">
    Houston (3)
  </button>
  <!-- ... -->
</div>

Expandable cards:

<article aria-label="Fiqh of Salah, April 12-13, Houston">
  <div class="card-summary">
    <h2>Fiqh of Salah</h2>
    <!-- summary content -->
    <button aria-expanded="false" aria-controls="event-1234-details">
      View Details
    </button>
  </div>
  <div id="event-1234-details" role="region" aria-labelledby="event-1234-title" hidden>
    <!-- expanded content -->
  </div>
</article>

Screen reader announcements:

Hidden live region for dynamic updates:

<div aria-live="polite" aria-atomic="true" class="sr-only" id="filter-status">
  <!-- JS updates this: "Showing 8 events in North America" -->
</div>

7.3 Keyboard Navigation Flow

Tab order (sequential):

1. Skip to content link (hidden, appears on first Tab press)
2. Continent tabs (Left/Right arrow to navigate between tabs, Enter/Space to select)
3. City pills (Left/Right arrow to scroll, Enter/Space to select)
4. First event card summary
   → Enter/Space: expand card
   → Within expanded card: Tab through all interactive elements
   → Escape: collapse card, return focus to card trigger
5. Second event card summary
   → (repeat)
6. Footer links

Keyboard shortcuts (optional, Phase 2):

7.4 Color Contrast Requirements

Element Foreground Background Ratio Passes AA
Body text #24292f #ffffff 14.5:1 Yes
Muted/secondary text #57606a #ffffff 5.7:1 Yes
Card title #24292f #ffffff 14.5:1 Yes
Price text (green) #1a7f37 #ffffff 4.8:1 Yes
Active tab text #ffffff #7c3aed (purple) 7.2:1 Yes
Inactive tab text #57606a #f6f8fa (light gray) 4.8:1 Yes
Link text #0969da #ffffff 4.7:1 Yes
"Register" button text #ffffff #2da44e (green) or #7c3aed (purple) 4.5:1+ Yes
Card border #d0d7de #ffffff 1.8:1 (decorative, 3:1 not required for borders used as visual grouping) N/A
Focus outline #7c3aed any background 3:1+ Yes

7.5 Focus Management

On page load:

On filter change:

On card expand:

On card collapse:

On "Register Now" click:


8. Analytics & Measurement Plan

8.1 Event Tracking Specification

All events should be tracked via a lightweight analytics library (Google Analytics 4, Plausible, or a custom endpoint). Use a consistent naming convention.

Page-level events:

Event Name Trigger Properties
page_view Page load complete source (utm_source or referrer), continent_auto (GeoIP-detected), city_auto (GeoIP-detected), total_events (count of events loaded), load_time_ms
page_error API call fails error_type (network, timeout, parse), error_message

Filter events:

Event Name Trigger Properties
filter_continent User clicks a continent tab continent (slug), events_shown (count after filter), was_auto_selected (boolean)
filter_city User clicks a city pill city (slug), continent (slug), events_shown (count after filter), was_auto_selected (boolean)
filter_reset User clicks "All" previous_continent, previous_city

Card events:

Event Name Trigger Properties
card_expand User expands a card event_id, event_title, city, instructor, position (nth card on page), time_on_page_seconds
card_collapse User collapses a card event_id, time_expanded_seconds
card_scroll User scrolls within expanded card event_id, scroll_depth_percent (25, 50, 75, 100)

Conversion events:

Event Name Trigger Properties
register_click User clicks "Register Now" event_id, event_title, city, continent, instructor, price_shown (lowest tier), pricing_tier (early_bird / standard / special), attendees_shown (registration count), position, time_on_page_seconds, cards_expanded_count, source (utm_source)
share_click User clicks share button event_id, event_title, city, share_method (native_share / copy_link), share_location (summary_card / expanded_card)
share_complete Native share completes (if detectable) event_id, share_target (whatsapp / messages / etc., if available from share API)

Engagement events:

Event Name Trigger Properties
instructor_click User clicks instructor name/link instructor_name, event_id
scroll_depth User scrolls to 25%, 50%, 75%, 100% of page depth_percent, events_visible (how many cards were in view)
time_on_page User has been on page for 15s, 30s, 60s, 120s duration_seconds, cards_expanded, filters_used

8.2 Heatmap & Scroll Depth Recommendations

Heatmap tracking (Hotjar, Microsoft Clarity, or similar):

Scroll depth tracking:

Session recording priorities:

8.3 A/B Test Ideas for Future Optimization

Test Hypothesis Metric Priority
Card image: poster vs. background The wider background image (960x600) on mobile card summaries will increase card expansion rate by 10%+ vs. the narrow poster (250x375) Card expansion rate HIGH
Social proof threshold Showing "Students are registering" (no number) for events with 10-29 attendees increases Register CTR vs. hiding the count entirely Register CTR for those events HIGH
Pricing display: "From $99" vs. "$99 / $129" Showing only the lowest price increases Register CTR, but showing both creates urgency via price anchoring Register CTR MEDIUM
Expand animation: inline vs. modal Inline expansion has higher card expansion rate (lower friction) but modal may have higher Register CTR (more focused attention) Card expansion rate + Register CTR MEDIUM
Filter default: continent vs. city Auto-selecting just the continent (showing all cities) vs. auto-selecting the nearest city. Broader view = more browsing, narrow view = faster conversion Register CTR, events-per-session MEDIUM
CTA copy: "Register Now" vs. "Learn More & Register" "Register Now" is clearer but may feel like a commitment. "Learn More" implies the registration page has more information. Register CTR LOW
Hero: with stats vs. without Adding "300K+ students worldwide" to the hero increases trust for new visitors Bounce rate, Register CTR for first-time visitors LOW
City pill sort: by count vs. alphabetical Sorting by event count (Houston (3) before Boston (1)) vs. alphabetical. Count-based creates popularity signals but may feel unfamiliar. Filter engagement rate LOW

8.4 Success Metrics & KPIs

Primary KPIs (review weekly):

KPI Target Measurement
Register CTR 8-12% register_click / unique_visitors
Share rate 3-5% share_click / unique_visitors
Bounce rate < 40% Single-interaction sessions / total sessions
Mobile Register CTR 6-10% register_click on mobile / mobile unique_visitors

Secondary KPIs (review monthly):

KPI Target Measurement
Card expansion rate 35-50% card_expand (unique) / unique_visitors
Filter engagement 25-40% filter_continent or filter_city / unique_visitors
Events per session 1.5-2.5 card_expand (total) / sessions with at least 1 expand
Average time on page 45-90 seconds Median time_on_page for engaged sessions
WhatsApp share rate 2-3% of total shares share_complete where target=whatsapp / total share_click

North star metric: Register CTR from mobile WhatsApp traffic. This is the highest-volume, highest-intent segment. If the page converts these users well, it is succeeding at its primary job.

Reporting cadence:


9. Performance Budget

9.1 Target Load Times

Metric Target Measurement
First Contentful Paint (FCP) < 1.5s on 4G, < 3s on 3G Lighthouse, Web Vitals
Largest Contentful Paint (LCP) < 2.5s on 4G, < 4s on 3G Lighthouse, Web Vitals
Cumulative Layout Shift (CLS) < 0.1 Lighthouse, Web Vitals
First Input Delay (FID) < 100ms Web Vitals
Interaction to Next Paint (INP) < 200ms Web Vitals
Time to Interactive (TTI) < 3.5s on 4G Lighthouse
Total page weight < 500KB initial, < 1.5MB total (with lazy images) DevTools Network

9.2 Image Optimization Strategy

Image types and sizes:

Image Source Size Optimized Target Format Loading
Event poster (card thumbnail) 250x375 JPEG 200x300 @ 80% quality WebP with JPEG fallback Eager (first 3), lazy (rest)
Event background (expanded) 960x600 JPEG 720x450 @ 75% quality WebP with JPEG fallback Lazy (only on expand)
Instructor avatar Varies 48x48 @ 80% quality WebP with JPEG fallback Lazy
OG share image 1200x630 JPEG 1200x630 @ 85% quality JPEG (social crawlers need JPEG) N/A (meta tag only)

Implementation:

<!-- Card thumbnail with srcset -->
<picture>
  <source
    type="image/webp"
    srcset="poster_200x300.webp 1x, poster_250x375.webp 2x"
  />
  <img
    src="poster_250x375.jpg"
    alt="Fiqh of Salah poster"
    width="200"
    height="300"
    loading="lazy"
    decoding="async"
  />
</picture>

If the CDN does not support WebP or resizing on the fly:

Placeholder strategy:

9.3 Critical CSS Strategy

Inline in <head> (critical CSS — ~5KB):

Loaded asynchronously (non-critical CSS — ~5KB):

Implementation:

<head>
  <style>/* Critical CSS inlined here - ~5KB */</style>
  <link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
  <noscript><link rel="stylesheet" href="styles.css"></noscript>
</head>

9.4 JavaScript Bundle Size Target

Component Target Size (gzipped) Notes
API fetch + data parsing 2KB Vanilla fetch, simple JSON parsing
Filter logic 2KB Client-side array filtering, URL parameter sync
Card expand/collapse 2KB DOM manipulation, ARIA updates, scroll behavior
Share functionality 1KB navigator.share + clipboard fallback + message formatting
GeoIP detection 1KB Single API call + distance calculation
Analytics wrapper 2KB Event dispatch to GA4 or custom endpoint
Schema.org injection 1KB JSON-LD generation from event data
Total ~11KB gzipped No framework needed

Framework decision: At ~21 events with client-side filtering, vanilla JavaScript is more than sufficient. A framework (React, Vue, Preact) adds 3-30KB of overhead for negligible benefit at this scale. If the page later needs complex state management (e.g., real-time updates, user preferences, saved events), Preact (~3KB) would be the right minimal choice.

Third-party script budget:

Loading order:

  1. HTML + critical CSS (inline) → First Contentful Paint
  2. API fetch begins (in parallel with CSS parse)
  3. Non-critical CSS loads asynchronously
  4. App JS loads (11KB) → parses API data, renders cards
  5. Images lazy-load as user scrolls
  6. Analytics + heatmap load deferred (after page interactive)

10. Three Design Direction Concepts

Direction A: "Community Hub"

Visual approach and mood: Warm, inviting, people-centric. The design emphasizes that events are about joining a community, not just attending a class. Colors are warm purples and golds with generous white space. Photography (where used) shows people — students, instructors, gatherings — not abstract Islamic geometric art. The vibe is "your friends are already going."

Hero section concept:

Card design concept:

How filters are presented:

Mobile adaptation:

Strengths:

Trade-offs:


Direction B: "Clean Directory"

Visual approach and mood: Information-dense, scannable, efficient. Inspired by the clarity of Google search results, Stripe's documentation, or GitHub's issue lists. Every pixel serves a purpose. The design trusts users to know what they want and optimizes for fast scanning and filtering. No decorative elements. Neutral whites, grays, and blues with purple as the sole accent color.

Hero section concept:

Card design concept:

Layout:

┌──────────────────────────────────────────────────────────────────────┐
│ [Img]  Fiqh of Salah · Sh. Yasir Qadhi · Houston · Apr 12-13  $99 →│
├──────────────────────────────────────────────────────────────────────┤
│ [Img]  Heart Therapy · Sh. Omar Suleiman · Dallas · Apr 19-20 $109 →│
├──────────────────────────────────────────────────────────────────────┤
│ [Img]  Light of Guidance · Dr. Reda Bedeir · NYC · Apr 26-27  $119 →│
└──────────────────────────────────────────────────────────────────────┘

How filters are presented:

Mobile adaptation:

Strengths:

Trade-offs:


Direction C: "Immersive Showcase"

Visual approach and mood: Visual-first, cinematic, storytelling. Inspired by Apple's product pages, Airbnb's experience pages, or conference websites like WWDC. Large imagery, generous whitespace, and a sense of occasion. Each event feels like a significant experience worth investing in, not just a class listing. The design conveys prestige and quality.

Hero section concept:

Card design concept:

Layout:

┌────────────────────────────────┐ ┌────────────────────────────────┐
│                                │ │                                │
│     [960x600 Background]       │ │     [960x600 Background]       │
│                                │ │                                │
│                                │ │                                │
│  ┌──────────────────────────┐  │ │  ┌──────────────────────────┐  │
│  │ Fiqh of Salah            │  │ │  │ Heart Therapy             │  │
│  │ Sh. Yasir Qadhi          │  │ │  │ Sh. Omar Suleiman        │  │
│  │ Houston · Apr 12-13 · $99│  │ │  │ Dallas · Apr 19-20 · $109│  │
│  └──────────────────────────┘  │ │  └──────────────────────────┘  │
└────────────────────────────────┘ └────────────────────────────────┘

How filters are presented:

Mobile adaptation:

Strengths:

Trade-offs:


Design Direction Recommendation

For v1: Direction B ("Clean Directory") with selected elements from Direction A ("Community Hub").

Rationale:

  1. Performance first. With 60-70% mobile WhatsApp traffic, load speed and scannability are non-negotiable. Direction B is the lightest and fastest.
  2. Community trust already exists. Users arriving from WhatsApp shares already have social proof (their friend sent it). The page doesn't need to sell the AlMaghrib brand — it needs to get users to the right event and registered.
  3. 21 events is a small catalog. With this few events, the page's job is to help users filter to their city and review details quickly. A directory pattern serves this better than a showcase.
  4. Selective community warmth. Borrow from Direction A: show "X students registered" on cards (when count > 30), use the warm purple palette, and add the instructor avatar on expanded view. These add community feel without sacrificing density.
  5. Direction C for later. As the event catalog grows and the page becomes a primary landing page (rather than a WhatsApp referral destination), a more visual approach makes sense. The immersive showcase would be powerful for social media marketing campaigns.

v1 implementation priority:


Appendix A: Implementation Checklist

A phased checklist for building the page against this strategy:

Phase 1 — Core Page (Week 1-2)

Phase 2 — Polish (Week 2-3)

Phase 3 — Enhancement (Week 3-4)


Appendix B: Reference Comparisons

Pages to study for pattern inspiration (not copy):

Site What to Study Relevant Pattern
Eventbrite search results Card density, filter UX, mobile layout Directory pattern, tag-based filtering
Airbnb Experiences Card design, image treatment, social proof Visual cards with price, rating, host info
Google Events Structured data display, search intent matching Schema.org integration, location-based results
ClassPass Studio/class discovery, booking CTA placement Mobile-first class cards, sticky CTA
Meetup.com Community event discovery, city-based filtering Group-based events, location auto-detect
Coursera course catalog Educational course cards, instructor prominence Credits/certification badge pattern

This document should be revisited after the first 2 weeks of page analytics data to validate assumptions and adjust the strategy based on actual user behavior.