Building a Vendor Referral Tracking System: Lambda, DynamoDB, and CloudFront Deployment
Over the past development session, we implemented a complete vendor referral program for JADA, complete with click tracking infrastructure, email outreach templates, and a dashboard approval workflow. This post walks through the architectural decisions, deployment details, and the systems we built to support real-time referral attribution.
What We Built
The vendor referral system consists of three interconnected layers:
- Referral Tracking API: A GET endpoint on the ShipCaptainCrew Lambda that logs vendor clicks to DynamoDB and redirects guests to the main site with UTM parameters
- Click Attribution Storage: DynamoDB tables recording vendor name, timestamp, and running click counts for real-time analytics
- Email & Approval Workflow: HTML email templates with embedded previews, managed through a dashboard task system with S3 + CloudFront delivery
Seven vendors are currently active with live referral links. The system is production-ready and tracking clicks in real time.
The Referral Tracking Infrastructure
Lambda Endpoint Design
We deployed a new GET endpoint at /ref/{code} on the ShipCaptainCrew Lambda function. The endpoint is responsible for:
- Receiving a vendor code (e.g.,
solare,smallgoods) - Logging the click to DynamoDB with vendor name, ISO timestamp, and incremented count
- Redirecting the guest to
https://queenofsandiego.comwith UTM parameters for GA4 attribution
The function is exposed via API Gateway and routed through CloudFront. Here are the live referral links currently in use:
https://shipcaptaincrew.queenofsandiego.com/ref/solare
https://shipcaptaincrew.queenofsandiego.com/ref/smallgoods
https://shipcaptaincrew.queenofsandiego.com/ref/puesto
https://shipcaptaincrew.queenofsandiego.com/ref/boardbrew
https://shipcaptaincrew.queenofsandiego.com/ref/wholefoods
https://shipcaptaincrew.queenofsandiego.com/ref/totalwine
https://shipcaptaincrew.queenofsandiego.com/ref/gbvintners
Why this design: Using a path-based approach (/ref/{code}) keeps the URL clean and human-readable for vendors to share. The redirect pattern allows us to track the source while maintaining the original destination logic, and UTM parameters ensure GA4 attribution works without additional instrumentation on the landing page.
DynamoDB Click Tracking
Each click is persisted to DynamoDB with the following attributes:
vendor_name(partition key): The vendor identifier (e.g., "solare")timestamp(sort key): ISO 8601 formatted click timeclick_count(attribute): Running total of clicks for that vendor
We verified click counts are being recorded correctly by querying DynamoDB directly. The table schema is simple by design—it prioritizes write throughput and query speed over complex aggregations. Dashboard analytics aggregate the click data on read, not at write time.
Why this schema: A partition key on vendor name with a sort key on timestamp allows us to query all clicks for a vendor in chronological order, support time-range queries for reporting, and scale write throughput independently per vendor. Running counts are updated in-place to avoid separate read-modify-write cycles.
Email Outreach & Dashboard Approval Workflow
HTML Email Templates
We drafted three vendor email templates (in addition to two already sent). Each email is a self-contained HTML document stored in /tmp/vendor-referral-outreach.html during development and uploaded to S3 for preview and approval.
The emails follow this structure:
- Subject line with vendor name and program call-to-action
- Personalized greeting and context on JADA's referral value proposition
- Unique referral link specific to each vendor
- Click tracking details and expected follow-up
- Signature and contact information
Why HTML over plain text: HTML emails allow us to embed formatted link previews, track opens via pixel-based analytics (if needed), and provide a more professional presentation. However, we ensure all critical information is readable in plaintext fallback mode.
S3 + CloudFront Preview Delivery
The vendor email preview page was uploaded to S3 (bucket: queenofsandiego-assets, path: /vendor-referral-preview.html) and cached through CloudFront distribution (ID: E2ABCD1234XYZ).
After uploading, we invalidated the CloudFront cache with:
aws cloudfront create-invalidation \
--distribution-id E2ABCD1234XYZ \
--paths "/vendor-referral-preview.html"
Why S3 + CloudFront: S3 is a simple, durable storage layer for static HTML. CloudFront provides low-latency delivery globally and, more importantly, allows us to version and roll back content quickly. Cache invalidation ensures stakeholders see the latest version immediately after updates.
Dashboard Task Card
To enable approval workflow, we created a dashboard task card using the existing update_dashboard.py script. The card links directly to the preview page and includes metadata for tracking approval status.
The command executed:
python3 update_dashboard.py \
--action add-task \
--card-type vendor-referral-approval \
--title "Review & Approve Vendor Referral Emails" \
--link "https://queenofsandiego.com/vendor-referral-preview.html" \
--owner "Sergio" \
--priority high
This creates a new task in the progress dashboard visible to all team members. The deep link points to the preview page, which embeds all three vendor emails in a single approachable format. Once approved, emails are sent via SES (Simple Email Service) with proper authentication headers to ensure deliverability.
Why a dashboard task: The dashboard is the canonical source of truth for project status and approvals. By creating a task card with a direct link, we keep the approval process visible, trackable, and integrated with existing workflows. This avoids scattered email approvals or Slack decision trails.
Infrastructure & Deployment Details
Lambda Function Updates
The referral endpoint was added to the ShipCaptainCrew Lambda function deployed to AWS. The function code was updated locally, tested, and redeployed. We verified the new endpoint exists by:
- Comparing local vs. deployed Lambda code line counts
- Inspecting the
handle_referral_clickfunction logic - Checking API Gateway routing for the
/refpath
Lambda logs confirm that referral clicks are being processed and logged to DynamoDB