```html

Building a Dynamic Artist Celebration System for Concert Event Pages

We recently implemented a system to inject dynamic, daily-updating artist celebration content into Rady Shell event pages on queenofsandiego.com. This technical post covers the architecture, infrastructure changes, and implementation details of this feature.

The Philosophy Behind the Feature

The inspiration came from Nike's marketing approach: rather than focusing on product commodities, they celebrate the athletes themselves. Similarly, we wanted to shift focus from simply listing concert details to celebrating the artists performing at each event. The content needed to update automatically three times daily until the concert date, keeping the spotlight fresh and engaging.

Architecture Overview

The system comprises three main components:

  • Google Apps Script (GAS) Backend: Generates dynamic artist content via API integration
  • Static Site Renderer: Injects the spotlight section into event HTML templates
  • Content Distribution: S3 + CloudFront deployment pipeline with cache invalidation

Technical Implementation Details

Google Apps Script Service Creation

We created a new file ArtistCelebrationsService.gs in the apps-script-replacement directory. This service:

  • Accepts event identifiers and artist names as parameters
  • Calls the Anthropic API to generate compelling artist celebration content
  • Returns formatted HTML sections ready for injection into event pages
  • Caches responses appropriately to minimize API calls while respecting the three-times-daily update requirement

The GAS deployment was configured as an executable endpoint, allowing HTTP requests from the static site renderer and CloudFront. We updated Code.gs to include a new routing handler that directs requests to /artist-celebration to the ArtistCelebrationsService.

Command to deploy and verify:

clasp push  # Deploy the updated GAS project
clasp deployments list  # Retrieve the live exec URL ID

Static Site Rendering Pipeline

Modified tools/render_event_sites.py to:

  • Parse the events.json configuration file for artist details
  • Call the GAS ArtistCelebrationsService endpoint for each event
  • Inject the returned HTML into a new <section class="artist-spotlight"> element within event page templates
  • Position the spotlight section prominently—typically after the header and before technical event details

We also created a new utility script tools/inject_artist_spotlight.py to retroactively inject the spotlight section into all existing event HTML files. This script:

  • Reads compiled event HTML from S3 buckets
  • Identifies insertion points in the DOM based on CSS selectors
  • Injects the artist celebration section without disrupting existing page structure
  • Handles edge cases where pages may have been customized

Infrastructure and Deployment

S3 Bucket Structure

Event content is distributed across multiple S3 buckets following the pattern:

qos-event-subdomain-[eventname]-us-west-2

Each bucket contains the static HTML files for that specific event. We identified all event subdomains by querying the Route53 hosted zone and cross-referencing with CloudFront distributions.

CloudFront Cache Strategy

Because artist celebration content updates three times daily, we needed aggressive cache invalidation. After uploading updated event HTML to each S3 bucket, we triggered CloudFront invalidations:

aws cloudfront create-invalidation \
  --distribution-id [DISTRIBUTION_ID] \
  --paths "/*"

This ensures users see the latest artist celebration content within minutes of updates, rather than waiting for the default TTL to expire. We applied this invalidation across all event distribution IDs identified in CloudFront.

Deployment Sequence

  1. Push updated GAS code with ArtistCelebrationsService to Google Apps Script
  2. Create or update GAS deployment to expose the artist celebration endpoint
  3. Run render_event_sites.py to generate fresh event HTML with artist spotlights
  4. Run inject_artist_spotlight.py for retroactive injection into existing compiled pages
  5. Upload updated HTML files to each event S3 bucket
  6. Invalidate CloudFront cache for all event distributions
  7. Verify injection in sample pages by examining DOM structure and content

Key Decisions and Trade-offs

Why Google Apps Script?

GAS provides:

  • Native integration with Google Sheets (our event data source)
  • Built-in Anthropic API client support
  • Time-based trigger capabilities for the three-times-daily update schedule
  • No infrastructure to manage—scaling handled by Google

Why Inject Rather Than Server-Render?

We chose HTML injection over server-side rendering because:

  • Event pages are static, globally distributed via CloudFront
  • Injection happens at build time, avoiding runtime dependencies
  • Content updates don't require rebuilding entire pages—only the spotlight section
  • Maintains separation between event metadata and dynamic content

Cache Invalidation Trade-offs

While CloudFront invalidation costs per invalidation, the business requirement for fresh content three times daily justifies this cost. We prioritized user experience over CDN expenses, ensuring the celebration content feels current and engaging.

Monitoring and Verification

Post-deployment, we verified the implementation by:

  • Sampling event pages across different subdomains
  • Confirming the artist-spotlight section renders in the correct DOM position
  • Verifying content updates by checking timestamps and comparing cached vs. fresh requests
  • Monitoring GAS deployment logs for API errors or quota issues

What's Next

Future enhancements could include:

  • Personalization based on user location or browsing history
  • A/B testing different celebration styles to optimize engagement
  • Integration with social media feeds to showcase artist performances
  • Scheduled content variations based on time-to-event countdown

The artist celebration system is now live across all Rady Shell event pages, updating dynamically and celebrating the artists who make these performances possible.

```