How the Tracking Service Integrates with Supabase for Download Analytics
The tracking service integrates with Supabase through a three-layer architecture where the CLI’s TrackingService sends anonymized JSON payloads to a Vercel API endpoint, which validates requests, enriches them with geolocation data, and writes to both component_downloads and download_stats tables.
The davila7/claude-code-templates repository implements a privacy-respecting download analytics pipeline that tracks component installations without blocking the CLI workflow. Understanding how the tracking service integrates with Supabase reveals a fire-and-forget system designed for minimal latency while maintaining detailed usage statistics and aggregated counters.
CLI Layer: Building and Sending Payloads
In cli-tool/src/tracking-service.js, the TrackingService class manages the client-side logic for capturing download events through three distinct phases.
Privacy Controls and Opt-Out Handling
The service respects user privacy through the shouldEnableTracking() method, which checks for CCT_NO_TRACKING, CCT_NO_ANALYTICS, or CI environment variables. When any are set, tracking disables entirely before any network requests occur.
Payload Creation and Session Management
The createTrackingPayload() method constructs a lightweight JSON object containing:
- Component
typeandname - Generated session ID and timestamp
- Runtime environment information
- Optional metadata object
Component types must belong to the allowed enum: agent, command, mcp, setting, hook, template, or skill.
Fire-and-Forget Transmission
The sendTrackingData() method posts to https://www.aitmpl.com/api/track-download-supabase with a 5-second abort timeout. The trackDownload() wrapper catches all errors silently unless CCT_DEBUG=true, ensuring analytics never bubble up to the user or delay installation flows.
// cli-tool/src/tracking-service.js
async trackDownload(componentType, componentName, metadata = {}) {
if (!this.trackingEnabled) return;
const trackingData = this.createTrackingPayload(componentType, componentName, metadata);
this.sendTrackingData(trackingData).catch(err => {
if (process.env.CCT_DEBUG === 'true') console.debug('📊 Tracking info (non‑critical):', err.message);
});
}
API Layer: Validation and Data Enrichment
The api/track-download-supabase.js endpoint processes incoming requests before database insertion.
Request Validation and CORS Guards
The endpoint accepts only POST requests (with OPTIONS pre-flight support). The validateComponentData() function verifies that type and name exist and that type matches the allowed component list.
Client Data Enrichment
Before Supabase insertion, the endpoint enriches payloads with:
- IP extraction:
getClientIP()parses Vercel forwarding headers (x-forwarded-for,x-real-ip) - Geolocation:
getCountry()extracts the two-letter country code fromx-vercel-ip-country - User-agent: Captured directly from request headers
Supabase Client Initialization
The getSupabaseClient() function creates a client using SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY environment variables, throwing immediately if either is missing from the Vercel environment.
Database Layer: Dual-Table Storage Strategy
The integration implements a write pattern that supports both granular event logging and fast aggregated queries.
Raw Event Logging
Every validated request inserts a row into component_downloads with columns for:
component_type,component_name,component_path,categorydownload_timestamp,cli_versionuser_agent,ip_address,country
Aggregated Statistics with Upsert Logic
Simultaneously, the endpoint upserts into download_stats to maintain counters without duplicate rows:
// api/track-download-supabase.js
const { error: upsertError } = await supabase
.from('download_stats')
.upsert({
component_type: type,
component_name: name,
total_downloads: 1,
last_download: new Date().toISOString(),
updated_at: new Date().toISOString()
}, {
onConflict: 'component_type,component_name',
ignoreDuplicates: false
});
The onConflict clause targets the composite unique key (component_type, component_name), incrementing total_downloads and refreshing timestamps for existing components.
Environment Configuration
The integration requires specific environment variables:
API Layer (Vercel):
SUPABASE_URL: Project URLSUPABASE_SERVICE_ROLE_KEY: Service role key for authenticated writes
CLI Layer (User Machine):
CCT_NO_TRACKINGorCCT_NO_ANALYTICS: Disables tracking when setCI: Automatically disables tracking in continuous integration environmentsCCT_DEBUG: Enables console logging for tracking debug information
Usage Examples
Tracking a Component Download from Node.js
const { trackingService } = require('../cli-tool/src/tracking-service');
// Track installation of the "security-audit" agent
trackingService.trackDownload('agent', 'security-audit', {
target_directory: '/path/to/project',
category: 'security'
});
Testing the Endpoint with cURL
curl -X POST https://www.aitmpl.com/api/track-download-supabase \
-H "Content-Type: application/json" \
-d '{
"type":"agent",
"name":"test-agent",
"path":"test/path",
"category":"testing",
"cliVersion":"1.20.0"
}'
Both methods result in a detailed row in component_downloads and an incremented counter in download_stats.
Summary
- Three-layer architecture: CLI service → Vercel API → Supabase database enables separation of concerns between data collection, validation, and storage
- Privacy-first design: Automatic opt-out via environment variables and fire-and-forget requests ensure no blocking or data leakage when users disable tracking
- Dual-table strategy:
component_downloadsstores granular event data for analysis whiledownload_statsprovides fast aggregated lookups via upsert operations - Zero-impact error handling: Network failures or Supabase outages are silently caught (or logged only in debug mode) without interrupting the CLI workflow
- Schema documentation: Full table definitions and architectural details are documented in
cli-tool/docs_to_claude/DOWNLOAD_TRACKING.md
Frequently Asked Questions
How does the tracking service handle user privacy and opt-outs?
The shouldEnableTracking() method in cli-tool/src/tracking-service.js checks for CCT_NO_TRACKING, CCT_NO_ANALYTICS, or CI environment variables. If any are present, the service sets trackingEnabled to false and returns immediately from trackDownload() without sending network requests, ensuring complete opt-out from analytics collection.
What component types does the tracking system accept?
According to the validateComponentData() function in api/track-download-supabase.js, the system validates that type belongs to a specific whitelist: agent, command, mcp, setting, hook, template, or skill. Requests with invalid types receive validation errors before any database writes occur.
How does the Supabase integration prevent duplicate download counts?
The download_stats table uses an atomic upsert operation with onConflict: 'component_type,component_name'. Rather than inserting duplicate rows for every download of the same component, this clause increments the total_downloads counter and updates the last_download timestamp on the existing row, maintaining accurate aggregated statistics without data duplication.
What happens if the Supabase write operation fails?
Because the CLI implements a fire-and-forget pattern with sendTrackingData().catch(), any network timeouts, validation errors, or Supabase connection issues are caught silently. Errors surface in the console only when the user sets CCT_DEBUG=true, ensuring that analytics failures never block or slow down component installations.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →