A Moose application for receiving and processing UTM redirect webhook data from utm.fiveonefour.dev.
This project implements a webhook receiver that:
- Accepts redirect event data from the UTM redirect service
- Processes and enriches the data with extracted UTM parameters
- Stores events in ClickHouse for analytics and reporting
app/
├── ingest/
│ ├── models.ts # Data models for UTM webhook events
│ └── transforms.ts # Data transformation logic
└── index.ts # Main application entry point
- Webhook Ingestion: Receives POST requests at
/ingest/UTMWebhook - Data Processing: Transforms raw webhook data and extracts UTM parameters
- Storage: Stores processed events in ClickHouse's
ProcessedUTMtable
- Moose CLI
- Node.js 18+
- ngrok (for local webhook testing)
- Clone the repository:
git clone https://github.com/514-labs/redirect-data.git
cd redirect-data- Install dependencies:
npm install-
Configure authentication (see Authentication section below)
-
Start the development server:
moose devThe server will start on http://localhost:4000
To receive webhooks from the UTM service locally:
- Start ngrok to expose your local server:
ngrok http 4000- Configure the UTM service at utm.fiveonefour.dev/admin to use your ngrok URL as the analytics endpoint.
This service requires bearer token authentication for security. The UTM tracker prototype must include an Authorization: Bearer <token> header when sending webhook data.
- Copy the
.env.examplefile to.env:
cp .env.example .env- Generate a hashed API key using the Moose CLI:
moose generate hash-token- Set the generated hash in your
.envfile:
MOOSE_INGEST_API_KEY=your_generated_hash_here- Configure the UTM tracker prototype to send the same token (before hashing) in the
Authorizationheader:
# In the utm-tracker-prototype .env file:
ANALYTICS_BEARER_TOKEN=your-plain-token-here- The UTM tracker sends:
Authorization: Bearer your-plain-token-here - Moose verifies this against the hashed version in
MOOSE_INGEST_API_KEY - Requests without valid authentication are rejected with a 401 error
For more advanced use cases, you can use JWT tokens with RSA signatures. See the Moose authentication docs for setup instructions.
The webhook endpoint expects POST requests with the following JSON structure:
{
"originalUrl": "https://your-domain.com/page?utm_source=twitter",
"redirectUrl": "https://target-site.com/landing",
"timestamp": "2025-01-15T10:30:00.000Z",
"userAgent": "Mozilla/5.0...",
"utmParams": {
"utm_source": "twitter",
"utm_medium": "social",
"utm_campaign": "launch2025"
},
"path": "/page"
}Processed events are stored in ClickHouse in the ProcessedUTM table with:
Original webhook fields:
originalUrl,redirectUrl,timestamp,userAgent,pathutmParams: JSON object with all UTM parametersreferer: Optional field (if provided by webhook)
Additional generated fields:
id: Auto-generated unique identifier (format:utm-{timestamp}-{random})utm_source,utm_medium,utm_campaign,utm_term,utm_content: Extracted as separate columns for efficient querying
Table configuration:
- Ordered by
timestampfor optimal query performance
The easiest way to deploy your Moose application is to use Boreal.
Check out the Moose deployment documentation for more details.
Join the Moose community on Slack.
