Building Daily Artist Celebrations at Rady Shell Events: A Serverless Content Injection Pattern
What We Built
We implemented an automated artist celebration feature for Rady Shell event pages that delivers fresh, rotating content about featured performers three times daily until concert day. The system injects a curated "Artist Celebration" section into every event page without modifying the static HTML templates, leveraging Google Apps Script as a serverless backend and a Python-based content injection pipeline.
The inspiration came from a principle exemplified by Nike's marketing strategy: rather than selling the commodity (shoes/venue), celebrate the excellence of the people who matter (athletes/artists). By rotating artist spotlights throughout the day, we create an emotional connection between attendees and performers before they arrive.
Technical Architecture
The Three-Layer System
- Data Layer: Google Sheets storing artist information, celebration quotes, and scheduling metadata
- Service Layer: Google Apps Script (GAS) providing a REST API endpoint that generates celebration content
- Presentation Layer: Static HTML pages with injected spotlight sections, deployed across event subdomains
This approach avoids modifying the static site generator while enabling dynamic content updates without page rebuilds.
Implementation Details
Google Apps Script Service
We created ArtistCelebrationsService.gs with a core function that:
- Queries a Google Sheet for artist metadata (name, bio, achievements, images)
- Implements rotation logic: serves different content based on time of day and days until concert
- Returns structured JSON consumable by frontend injection code
- Includes caching headers to align with our three-daily-update cadence
The service is deployed via Google Apps Script's deployment system, creating a new versioned deployment with a unique execution ID. This ID becomes the basis for our API endpoint:
https://script.google.com/macros/s/{DEPLOYMENT_ID}/usercallable
We maintain this deployment URL in our project configuration so the Python renderer can reference it.
Static Site Generator Integration
The file /rady-shell-events/tools/render_event_sites.py handles the site generation for all event subdomains. We added artist spotlight injection logic that:
- Reads the base HTML template (which includes a placeholder section or hook point)
- Generates a script tag that calls the GAS API endpoint
- Injects this script into each event's HTML before deployment
- Ensures the spotlight section renders after page load with proper styling
Created inject_artist_spotlight.py as a dedicated utility that parses event metadata from events.json, maps each event to its artist data, and generates the appropriate injection markup for each page.
Content Delivery Pipeline
The deployment process follows this sequence:
- Generate:
render_event_sites.pyprocesses all events and injects spotlight markup - Upload: Each generated HTML file is uploaded to its corresponding S3 bucket (event subdomains are stored in separate buckets for isolation)
- Invalidate: CloudFront distributions serving each event subdomain are invalidated to bust cached versions
Infrastructure
AWS S3 Organization
Each Rady Shell event has its own S3 bucket following the naming pattern:
queenofsandiego-rady-shell-{event-name}
Example buckets discovered during deployment:
queenofsandiego-rady-shell-summer-concert-seriesqueenofsandiego-rady-shell-opening-night- Additional event-specific buckets per subdomain
The upload script iterates through all discovered buckets and syncs updated HTML files, preserving existing assets while replacing HTML pages.
CloudFront Distribution Management
Each event subdomain has a CloudFront distribution. Rather than hardcoding distribution IDs, we:
- Query CloudFront via AWS CLI to list all distributions
- Match distributions by domain name pattern (
*.rady-shell.queenofsandiego.com) - Generate invalidation requests for each matched distribution with the path pattern
/*
Example invalidation command pattern (with placeholders):
aws cloudfront create-invalidation \
--distribution-id {DIST_ID} \
--paths "/*" \
--query 'Invalidation.Id'
We cache the discovered distribution IDs to avoid repeated CloudFront API calls during the deployment cycle.
Google Apps Script Deployment
GAS projects have a project ID and multiple possible deployments. We:
- Push the updated
ArtistCelebrationsService.gsandCode.gsfiles to the GAS project - Create a new deployment labeled with timestamp and feature name
- Store the resulting deployment ID (execution URL) in our configuration
- Update the HTML injection template to reference this new deployment ID
Multiple deployments can coexist; we maintain only the latest in our renderer configuration.
Key Architectural Decisions
Why Google Apps Script for the Backend?
GAS provides native Google Sheets integration without additional infrastructure. Since artist data lives in Sheets, GAS eliminates middleware layers and reduces operational overhead. The authentication model (published as callable) works well for public content delivery.
Why Inject Rather Than Render?
The static site uses Jinja2 templates. Rather than modify the template system (which would require re-rendering all pages on every artist data update), we inject a client-side fetch to the GAS endpoint. This decouples artist celebration updates from site generation—we can change spotlight content in Sheets without redeploying HTML.
Why Three Times Daily?
The rotation interval aligns with cache invalidation strategy. CloudFront distributions are invalidated once per deployment cycle, and we deploy three times daily to ensure users see fresh artist spotlights without excessive API calls. This balances freshness with performance.
Why Separate S3 Buckets Per Event?
Event isolation provides security boundaries and granular access control. Each event can have separate stakeholders and deployment procedures. Scaling to new events requires no changes to the S3 bucket discovery logic—the script enumerates all matching buckets dynamically.
What's Next
- Analytics: Instrument GAS service to track spotlight view counts and engagement per artist
- A/B Testing: Extend celebration content to include multiple variants, rotating through different messaging styles
- Social Integration: Embed artist social media feeds or recent posts alongside spotlights
- Personalization: Use attendee purchase data (if available) to customize spotlight content per user segment
The current system creates a foundation for deeper artist-attendee relationships. By celebrating excellence daily, we echo Nike's insight: the product is secondary to the human