```html

Injecting Structured Data into Event Pages: A Schema.org Implementation Across Multi-Domain Infrastructure

During this development session, we identified and resolved a critical SEO gap: 12 concert event pages across multiple subdomains were missing JSON-LD structured data. This post walks through the technical approach to injecting Event and LocalBusiness schema across a distributed multi-site architecture, the infrastructure considerations, and how we deployed the changes with cache invalidation.

The Problem: Missing Structured Data at Scale

A structured data audit revealed that our event pages—hosted across multiple CloudFront distributions and S3 buckets—had no JSON-LD markup. Search engines rely on this data to understand event dates, locations, ticket information, and venue details. Without it, rich snippets in search results were unavailable, and voice assistants couldn't parse event information reliably.

The challenge: these pages were generated dynamically through different build pipelines, served from different S3 buckets, and cached behind separate CloudFront distributions. A manual fix wouldn't scale.

Technical Solution: The Injection Script

We created /Users/cb/Documents/repos/tools/inject_structured_data.py, a Python script that:

  • Scans all event HTML files for existing schema markers
  • Generates valid Event and LocalBusiness JSON-LD based on page metadata
  • Injects the schema into the <head> section before the closing tag
  • Preserves existing markup and avoids duplicate injection
  • Reports which pages were modified and which already had data

The script reads HTML files from the local filesystem (built pages before S3 upload), identifies page context through filename patterns and existing meta tags, and generates appropriate Schema.org markup. For event pages, we inject both:

  • Event schema: name, startDate, endDate, location, image, url, offers (ticket availability)
  • LocalBusiness schema: venue name, address, phone, coordinates, business type

Example injection pattern:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Event",
  "name": "Concert Name",
  "startDate": "2024-03-15T19:00:00-07:00",
  "endDate": "2024-03-15T22:00:00-07:00",
  "location": {
    "@type": "Place",
    "name": "Venue Name",
    "address": {
      "@type": "PostalAddress",
      "streetAddress": "123 Main St",
      "addressLocality": "San Diego",
      "addressRegion": "CA",
      "postalCode": "92101",
      "addressCountry": "US"
    }
  },
  "image": "https://example.com/image.jpg",
  "description": "Event description",
  "url": "https://event.example.com/page",
  "offers": {
    "@type": "Offer",
    "url": "https://tickets.example.com",
    "price": "25",
    "priceCurrency": "USD",
    "availability": "https://schema.org/InStock"
  }
}
</script>

Multi-Domain Infrastructure Coordination

The event pages span multiple subdomains, each with its own S3 bucket and CloudFront distribution:

  • Event subdomain buckets: Located in /Users/cb/Documents/repos/sites/queenofsandiego.com/rady-shell-events/
  • S3 bucket naming: Pattern follows subdomain convention (e.g., paulsimonradyshell.com bucket)
  • CloudFront distributions: Each event subdomain has a dedicated distribution with unique distribution ID

We identified 12 pages requiring injection across these domains:

  • Multiple concert detail pages
  • Event index pages
  • Venue information pages
  • Special event pages (e.g., ranch-and-coast.html redirect page)

Deployment Pipeline: S3 → CloudFront Cache Invalidation

After running the injection script and verifying all 12 pages contained valid JSON-LD, we deployed using this process:

  1. Local validation: Ran the script against the built HTML files in the repository
  2. S3 sync: Used AWS CLI to sync updated pages to the correct S3 buckets for each event subdomain
  3. CloudFront invalidation: Created cache invalidations for each distribution to force edge locations to fetch fresh copies

Example invalidation command pattern (no specific dist IDs shown):

aws cloudfront create-invalidation \
  --distribution-id DISTRIBUTION_ID \
  --paths "/*" \
  --region us-east-1

We invalidated entire distributions using /* to ensure all cached variants were cleared. This is aggressive but necessary when modifying page headers; targeted path invalidation could miss edge-case caching scenarios.

Why This Approach?

  • Schema.org compliance: We chose JSON-LD over microdata because it's unobtrusive, easier to maintain, and doesn't require HTML structure modifications
  • Automation over manual work: A reusable script prevents human error and scales if new event pages are added
  • Full distribution invalidation: Rather than guessing which CloudFront cache objects needed refreshing, we invalidated everything, trading a brief edge spike for certainty
  • Metadata extraction from HTML: The script parses existing page content (title, meta description, og:image) to populate schema fields, reducing duplicated data entry

Integration with Existing Build Pipelines

During the session, we also reviewed two key generation scripts that create event pages:

  • /Users/cb/Documents/repos/sites/queenofsandiego.com/rady-shell-events/tools/render_event_sites.py: Renders concert detail pages from templates
  • /Users/cb/Documents/repos/sites/quickdumpnow.com/tools/generate_service_area_pages.py: Generates location-specific service pages

For long-term maintainability, structured data injection should move upstream into these generators rather than remaining a post-processing step. This ensures new pages automatically include schema without manual intervention.

What's Next

  • Integrate schema generation into render pipelines: Modify render_event_sites.py to generate JSON-LD directly during page creation
  • Validate schema.org compliance: Run Google's Rich Results Test against all 12 pages to confirm search engines can parse the markup
  • Monitor search appearance: Track rich snippet impressions in Google Search Console to measure impact
  • Extend to other domains: Apply the same pattern to quickdumpnow.com and dangerouscentaur.com pages if they have events