Injecting Structured Data into Concert Event Pages: A Multi-Site JSON-LD Strategy
What Was Done
This session focused on addressing a critical SEO gap: 12 active concert event pages across multiple subdomains were missing JSON-LD structured data. Search engines couldn't understand event details, dates, locations, or ticket information. We built an automated injection system, deployed updates to production S3 buckets, and invalidated CloudFront caches across all affected domains.
The core deliverable: a Python script that injects both Event and LocalBusiness schema types into pages that lacked any structured data markup.
Technical Details
Discovery and Assessment
We started by auditing the event infrastructure:
- Rady Shell Events directory structure at
/Users/cb/Documents/repos/sites/queenofsandiego.com/rady-shell-events/ - Event subdomain sites in
/Users/cb/Documents/repos/sites/with names likepaulsimonradyshell.queenofsandiego.com,sailjada.queenofsandiego.com, etc. - Confirmed: Zero pages had any structured data — no Event schema, no LocalBusiness schema, no markup at all
This gap meant Google Search, rich snippets, and voice assistants couldn't understand event context. For a business with 157 reviews and significant event traffic, this was a visibility loss.
Structured Data Injection Script
Created: /Users/cb/Documents/repos/tools/inject_structured_data.py
The script:
- Scans all event subdomain HTML files for
<head>tags - Generates JSON-LD blocks for
Eventtype with name, startDate, endDate, location (LocalBusiness), performer, and ticketing information - Inserts before the closing
</head>tag to ensure proper DOM placement - Preserves existing content (idempotent on re-runs)
- Logs all modifications for audit trail
Key design decision: Insert structured data in the <head>, not the body. This ensures parsing before initial DOM render and follows Google's recommended practices for bot-friendly markup.
The Event schema includes:
@context: "https://schema.org"@type: "Event"- Event name extracted from page title or filename
- Start/end dates inferred from page metadata or hardcoded per-event
- Location object (nested LocalBusiness with address, phone, name)
- Performer information pulled from page content
- URL canonicalized to HTTPS event subdomain
Infrastructure and Deployment
S3 Bucket Targets
Event subdomains are distributed across multiple S3 buckets. Updated pages were synced to:
- paulsimonradyshell.queenofsandiego.com bucket
- sailjada.queenofsandiego.com bucket
- Additional event subdomain buckets (6 total)
Deployment command pattern:
aws s3 sync /path/to/local/event/pages s3://bucket-name/ --exclude "*" --include "*.html" --delete
The --exclude and --include flags prevent accidental deletion of assets (JS, CSS, images) that may exist only in S3.
CloudFront Cache Invalidation
After S3 updates, we invalidated CloudFront distributions to ensure edge nodes served fresh content:
- Found CloudFront distribution IDs for each event subdomain using AWS CLI
- Created invalidation requests with path patterns like
/*.htmlto clear all HTML files - Monitionally checked invalidation status to confirm propagation (typically 2-5 minutes)
Invalidation command pattern:
aws cloudfront create-invalidation --distribution-id DIST_ID --paths "/*.html" "/*"
Why both /*.html and /*? The first targets only HTML files; the second ensures root paths and any directory-based requests are also refreshed. This is defensive and ensures no stale event pages are served.
Special Case: sailjada.com Ranch and Coast Redirect
During this work, we also deployed a new page to /Users/cb/Documents/repos/sites/sailjada.com/ranch-and-coast.html — a redirect/landing page for a Ranch and Coast event promotion. This was pushed to the sailjada.com S3 bucket and CloudFront distribution was invalidated separately.
Key Decisions and Rationale
Why JSON-LD Over Microdata or RDFa?
We chose JSON-LD (JavaScript Object Notation for Linked Data) because:
- It's Google's recommended format for structured data
- It doesn't require inline HTML attribute changes — easier to inject without breaking layout
- It's maintainable: JSON is human-readable and version-controllable
- It's forgiving: parsing errors in JSON-LD don't break page rendering
Why Event + LocalBusiness Schema?
Event schema alone doesn't describe the venue. By nesting LocalBusiness within the Event's location property, we provide:
- Rich snippets showing event date, venue name, and ticket availability
- Venue information (address, phone) for knowledge graph expansion
- Better contextualization for Google Maps integration and local search results
Automation via Python Script
Rather than manually editing 12 HTML files, we wrote inject_structured_data.py because:
- Consistency: All pages get identical schema structure (minus event-specific details)
- Auditability: Script logs every injection for compliance and debugging
- Repeatability: If pages are regenerated, re-running the script re-applies structured data
- Future-proofing: Adding new event pages requires only running the script once
Infrastructure Pattern: Distributed Event Subdomains
This deployment illuminated an important architecture: each event gets its own subdomain under *.queenofsandiego.com, each with its own S3 bucket and CloudFront distribution. This provides:
- Isolation: Event pages don't interfere with main site caching
- Scale: New events can be launched without touching main infrastructure
- Analytics: Each subdomain has its own Google Analytics tracking (verified via GA IDs)
- SSL: Wildcard SSL certificate covers all event subdomains
The trade-off: managing multiple S3 buckets and CloudFront distributions. We mi