Skip to main content

๐Ÿ”— URL Shortener Module

๐Ÿ“– Overviewโ€‹

The URL Shortener module provides branded short link creation with click tracking and analytics. It enables agencies to create memorable, trackable short URLs for marketing campaigns, social media, and client communications.

File Path: internal/api/v1/url-shortener/

Key Featuresโ€‹

  • Short Code Generation: Create unique short codes for URLs
  • Click Tracking: Count visits to each shortened URL
  • Custom Codes: Support for vanity/custom short codes
  • Redirect Management: 301/302 redirects with protocol normalization
  • Analytics: Track clicks, referrers, and user agents
  • Bulk Creation: Generate multiple short URLs at once

๏ฟฝ Directory Structureโ€‹

url-shortener/
โ”œโ”€โ”€ ๐Ÿ“„ index.js - Module router
โ”œโ”€โ”€ ๐Ÿ“„ redirector.js - Redirect handler (20 lines)
โ”œโ”€โ”€ ๐Ÿ“„ README.md - Module documentation
โ”œโ”€โ”€ ๐Ÿ“‚ controllers/
โ”‚ โ””โ”€โ”€ (URL management)
โ”œโ”€โ”€ ๐Ÿ“‚ services/
โ”‚ โ””โ”€โ”€ (business logic)
โ””โ”€โ”€ ๐Ÿ“‚ routes/
โ””โ”€โ”€ (route definitions)

Note: Core redirect logic is in standalone redirector.js for simplicity.

๏ฟฝ๐Ÿ—„๏ธ Collections Usedโ€‹

short-urlsโ€‹

  • Purpose: Store shortened URL mappings
  • Model: shared/models/short-url.js
  • Key Fields:
    • code (String, unique) - Short code identifier
    • url (String) - Full destination URL
    • account_id (ObjectId) - Owner account
    • created_by (ObjectId) - Creator user
    • visits (Number) - Click count
    • custom (Boolean) - Is custom vanity code
    • active (Boolean) - Enable/disable redirect
    • created_at (Date)

๐Ÿ”„ Data Flowโ€‹

URL Shortening Flowโ€‹

sequenceDiagram
participant User
participant API as URL Shortener API
participant DB as MongoDB
participant Redirect as Redirect Handler
participant Analytics as Analytics Service

User->>API: POST /v1/url (url, custom_code?)
API->>API: Generate/validate short code
API->>DB: Check code uniqueness

alt Code Available
API->>DB: Create short-url document
DB-->>API: { code, url }
API-->>User: Short URL: dash.cl/{code}
else Code Taken
API->>API: Generate new code
API->>DB: Retry insert
end

Note over User,Analytics: Later: User clicks short link

User->>Redirect: GET /{code}
Redirect->>DB: Find URL by code
DB-->>Redirect: { url, visits }
Redirect->>DB: Increment visits counter
Redirect->>Analytics: Log click event
Redirect-->>User: 302 Redirect to full URL

Click Tracking Flowโ€‹

flowchart TD
A[User Clicks Short URL] --> B[Extract Short Code]
B --> C[Query Database]
C --> D{URL Found?}

D -->|No| E[Return 404 Error]
D -->|Yes| F[Increment Visit Count]

F --> G[Log Click Event]
G --> H{Protocol Present?}

H -->|No| I[Prepend https://]
H -->|Yes| J[Use URL as-is]

I --> K[302 Redirect]
J --> K

K --> L[User Reaches Destination]

๐Ÿ”ง Core Functionalityโ€‹

Redirect Handlerโ€‹

File: redirector.js

Function: redirector(req, res, next)

Handles incoming short URL requests and redirects to full URLs.

Process:

// 1. Extract code from URL parameter
const code = req.params.code;

// 2. Find URL mapping
const url = await ShortURL.findOne({ code });

if (!url) {
throw new Error('RESOURCE_NOT_FOUND');
}

// 3. Increment visit counter
url.visits = (url.visits || 0) + 1;
await url.save();

// 4. Normalize URL protocol
let redirectUrl = url.url;
if (!redirectUrl.startsWith('http://') && !redirectUrl.startsWith('https://')) {
redirectUrl = `https://${redirectUrl}`;
}

// 5. Redirect user
res.redirect(redirectUrl);

Business Logic:

  • Visit Tracking: Increments counter on every access
  • Protocol Normalization: Ensures valid HTTP/HTTPS URL
  • Case Sensitivity: Codes are case-sensitive
  • 404 Handling: Returns standard 404 for invalid codes

URL Creationโ€‹

Endpoint: POST /v1/url

Request Body:

{
url: String, // Full URL to shorten
custom_code?: String, // Optional vanity code
active?: Boolean // Enable/disable (default: true)
}

Response:

{
success: true,
data: {
code: 'abc123',
url: 'https://example.com/very-long-url',
short_url: 'https://dash.cl/abc123',
visits: 0,
created_at: Date
}
}

Code Generation Logic:

// Default: 6-character alphanumeric code
function generateCode() {
const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
let code = '';
for (let i = 0; i < 6; i++) {
code += chars.charAt(Math.floor(Math.random() * chars.length));
}
return code;
}

// Custom code validation
function validateCustomCode(code) {
// 3-20 characters, alphanumeric and hyphens only
const pattern = /^[a-zA-Z0-9-]{3,20}$/;
return pattern.test(code);
}

Analytics Retrievalโ€‹

Endpoint: GET /v1/url/:code/analytics

Response:

{
success: true,
data: {
code: 'abc123',
url: 'https://example.com',
total_visits: 1250,
created_at: Date,
last_accessed: Date,
click_history: [
{ date: '2025-10-01', clicks: 45 },
{ date: '2025-10-02', clicks: 62 }
]
}
}

Bulk Creationโ€‹

Endpoint: POST /v1/url/bulk

Request Body:

{
urls: [
{ url: 'https://example.com/page1', custom_code: 'promo1' },
{ url: 'https://example.com/page2' },
{ url: 'https://example.com/page3', custom_code: 'sale25' },
];
}

Response:

{
success: true,
data: {
created: [
{ code: 'promo1', url: 'https://example.com/page1' },
{ code: 'xYz789', url: 'https://example.com/page2' },
{ code: 'sale25', url: 'https://example.com/page3' }
],
errors: [] // Codes that failed (duplicates, invalid)
}
}

๐Ÿ”€ Integration Pointsโ€‹

Main Applicationโ€‹

Route: GET /:code in internal/app.js

// Global route handler for short URLs
app.get('/:code', redirector);

This enables short URLs at the root level: https://dash.cl/abc123

Marketing Campaignsโ€‹

  • Email Marketing: Trackable links in email campaigns
  • Social Media: Shortened URLs for Twitter, LinkedIn, etc.
  • SMS: Space-saving short links in text messages
  • Print Materials: QR codes linking to short URLs

Analytics Dashboardโ€‹

  • Click-through rate (CTR) tracking
  • Geographic distribution of clicks
  • Referrer analysis (where clicks came from)
  • Device/browser breakdown

โš™๏ธ Configurationโ€‹

Short URL Domainโ€‹

Environment Variable:

SHORT_URL_DOMAIN=dash.cl

Code Generation Settingsโ€‹

const CONFIG = {
codeLength: 6, // Default code length
customCodeMinLength: 3, // Minimum custom code length
customCodeMaxLength: 20, // Maximum custom code length
allowedChars: 'a-zA-Z0-9-', // Valid characters
maxRetries: 5, // Collision retry limit
};

โš ๏ธ Important Notesโ€‹

  • ๐Ÿ”’ Case-Sensitive Codes: 'ABC' and 'abc' are different codes
  • ๐Ÿ”„ Collision Handling: Auto-generates new code if collision occurs
  • ๐Ÿ“Š Visit Tracking: Simple counter (no detailed analytics stored in base model)
  • ๐ŸŒ Protocol Handling: Automatically adds https:// if missing
  • โšก No TTL: Short URLs never expire (unless manually deactivated)
  • ๐Ÿšซ No Preview: Direct redirect without preview page
  • ๐Ÿ”— Permanent: Codes cannot be changed after creation (URL can be updated)

๐Ÿงช Edge Cases & Special Handlingโ€‹

Case: URL Without Protocolโ€‹

Condition: User submits example.com instead of https://example.com

Handling:

// Redirect handler adds https:// prefix
if (!url.startsWith('http://') && !url.startsWith('https://')) {
url = `https://${url}`;
}

Case: Custom Code Collisionโ€‹

Condition: Requested custom code already exists

Handling:

  • Return error: "Custom code already in use"
  • User must choose different code
  • No automatic fallback to generated code

Case: Invalid Destination URLโ€‹

Condition: URL is malformed or inaccessible

Handling:

  • URL validation on creation (basic format check)
  • No reachability test performed
  • Dead links still redirect (400+ errors shown to end user)

Case: High-Traffic Short URLโ€‹

Condition: Popular short URL receiving thousands of clicks

Handling:

  • Consider caching URL mapping in Redis
  • Use database read replicas for lookups
  • Batch visit count updates (every N clicks instead of every click)

๐Ÿ“ˆ Performance Considerationsโ€‹

Indexing Requirementsโ€‹

// short-urls collection
{
code: 1;
} // Unique index for fast lookups
{
account_id: 1;
} // List account's short URLs
{
created_by: 1;
} // User's short URLs
{
created_at: -1;
} // Recent short URLs

Optimization Patternsโ€‹

  • Code Lookup Cache: Cache popular codes in Redis (TTL: 1 hour)
  • Asynchronous Visit Increment: Queue visit increments to avoid blocking redirect
  • Bulk Insert: Use insertMany() for bulk creation
  • Projection: Only fetch url field for redirects

Scaling Considerationsโ€‹

  • CDN Integration: Use CDN edge locations for global redirect speed
  • Sharding: Shard by code prefix for horizontal scaling
  • Read Replicas: Use MongoDB read replicas for lookup queries

๐Ÿ” Security Considerationsโ€‹

Abuse Preventionโ€‹

  • Rate Limiting: Limit URL creation per account (e.g., 100/day)
  • Code Validation: Prevent reserved words and profanity
  • Malicious URL Detection: Integrate with URL reputation services
  • CAPTCHA: Require CAPTCHA for bulk creation

Reserved Codesโ€‹

const RESERVED_CODES = [
'admin',
'api',
'app',
'dashboard',
'help',
'login',
'register',
'settings',
'support',
'www',
];

// Reject reserved codes
if (RESERVED_CODES.includes(customCode.toLowerCase())) {
throw new Error('Code is reserved');
}

Last Updated: 2025-10-08
Module Path: internal/api/v1/url-shortener/
Primary File: redirector.js (20 lines - simple but critical)

๐Ÿ’ฌ

Documentation Assistant

Ask me anything about the docs

Hi! I'm your documentation assistant. Ask me anything about the docs!

I can help you with:
- Code examples
- Configuration details
- Troubleshooting
- Best practices

Try asking: How do I configure the API?
09:31 AM