```html

Building a Referral Tracking System for the JADA Vendor Program: Lambda, DynamoDB, and CloudFront Integration

What Was Done

We deployed a complete referral tracking infrastructure for the Queen of San Diego vendor partnership program, enabling real-time click attribution and automated vendor outreach workflows. The system tracks when guests click vendor-specific referral links, logs the events to DynamoDB, and redirects users with UTM parameters for GA4 integration.

The deployment included:

  • A new GET /ref/{code} endpoint in the SCC Lambda function
  • CloudFront distribution behavior configuration for the /ref/* path
  • DynamoDB referral click tracking with vendor attribution
  • HTML preview pages and dashboard approval cards for vendor email campaigns
  • Lambda code updates to handle public (unauthenticated) referral requests

Technical Architecture

Routing & CloudFront Configuration

The referral endpoint lives behind CloudFront distribution d2f5m3x4kp8qw1.cloudfront.net, which serves the domain shipcaptaincrew.queenofsandiego.com. Initially, referral requests were failing because the /ref/* path was being routed to the S3 origin instead of the Lambda origin.

We added a new CloudFront behavior with the following configuration:

  • Path Pattern: /ref/*
  • Origin: SCC API Gateway (not S3)
  • Allowed Methods: GET, HEAD, OPTIONS
  • Caching: 0 seconds (to prevent stale redirects)
  • Compress: Disabled (unnecessary for redirects)

The distribution was deployed via AWS CloudFront API with a cache invalidation on /ref/* to ensure the new behavior took effect immediately.

Lambda Handler Implementation

The SCC Lambda function (/tmp/scc-deployed/lambda_function.py) was modified to handle referral requests before the authorization gate. This is critical: the referral endpoint must be public, as it's shared with external vendors who have no AWS credentials.

The relevant handler section checks the request path early in the execution flow:

if event.get('rawPath', '').startswith('/ref/'):
    return handle_referral_click(event)

The handle_referral_click() function:

  • Extracts the vendor code from the path (e.g., boardbrew from /ref/boardbrew)
  • Logs the click to DynamoDB with a timestamp and running count
  • Constructs a redirect URL to queenofsandiego.com with UTM parameters
  • Returns a 302 HTTP redirect response

Example redirect: https://queenofsandiego.com/?utm_source=vendor_referral&utm_medium=referral&utm_campaign=boardbrew

DynamoDB Tracking Table

Referral clicks are persisted in a DynamoDB table with the following schema:

  • Partition Key: vendor_code (e.g., "boardbrew", "solare", "smallgoods")
  • Sort Key: timestamp (ISO 8601 format)
  • Attributes:
    • click_count — Running total of clicks from this vendor
    • user_agent — Browser/device information
    • ip_address — Anonymized request source

We queried the table via AWS CLI to validate that clicks were being recorded correctly:

aws dynamodb query \
  --table-name referral-clicks \
  --key-condition-expression "vendor_code = :code" \
  --expression-attribute-values '{":code":{"S":"boardbrew"}}' \
  --region us-west-2

Vendor Referral Links

Seven vendor partners are now active in the referral program:

  • Solare: https://shipcaptaincrew.queenofsandiego.com/ref/solare
  • Smallgoods: https://shipcaptaincrew.queenofsandiego.com/ref/smallgoods
  • Puesto: https://shipcaptaincrew.queenofsandiego.com/ref/puesto
  • Board & Brew: https://shipcaptaincrew.queenofsandiego.com/ref/boardbrew
  • Whole Foods: https://shipcaptaincrew.queenofsandiego.com/ref/wholefoods
  • Total Wine: https://shipcaptaincrew.queenofsandiego.com/ref/totalwine
  • Gianni Buonomo Vintners: https://shipcaptaincrew.queenofsandiego.com/ref/gbvintners

Key Decisions & Rationale

Why Public (Unauthenticated) Endpoint?

The referral endpoint had to bypass the Lambda's authorization gate because vendor partners (who are not system users) need to share working links. The authorization layer checks for valid API tokens, which external parties don't possess. By routing the /ref/* path before the auth check, we maintain security for authenticated endpoints while enabling public sharing.

CloudFront Behavior Ordering

CloudFront evaluates path patterns in order from most-specific to least-specific. We ensured the /ref/* behavior was defined before the default S3 behavior to guarantee correct routing. Existing API routes (e.g., /dashboard, /tasks) are defined with higher specificity and remain routed to the API Gateway origin.

Zero-Cache Redirect Strategy

Referral redirects have a TTL of 0 seconds in CloudFront. If we cached them, an updated redirect rule or vendor code change would require a cache invalidation. By disabling caching, every click hits the Lambda immediately, ensuring click counts are accurate and real-time.

Deployment Commands & Validation

The Lambda function was redeployed via AWS Lambda API:

aws lambda update-function-code \
  --function-name shipcaptaincrew \
  --zip-file fileb://lambda_function.zip \
  --region us-west-2

CloudFront distribution was updated via the AWS CLI:

aws cloudfront create-invalidation \
  --distribution-id d2f5m3x4kp8qw1 \
  --paths "/ref/*" \
  --region