Skip to content

Smart Routing

Route visitors to different destinations based on conditions like device, location, and time.

Overview

Smart Routing enables conditional redirects based on visitor attributes. Create rules to direct traffic dynamically without creating multiple short URLs.

Decision Flow

Creating Routing Rules

Basic Rule Creation

json
POST /api/urls/{urlId}/routing-rules

{
  "name": "iOS Users to App Store",
  "targetUrl": "https://apps.apple.com/app/myapp",
  "priority": 100,
  "isActive": true,
  "conditions": {
    "operator": "AND",
    "conditions": [
      {
        "type": "os",
        "operator": "equals",
        "value": "iOS"
      }
    ]
  }
}

Parameters:

ParameterDescriptionRequiredDefault
nameRule name (1-100 chars)-
targetUrlDestination URL-
priorityEvaluation order (0-10000)0
isActiveEnable ruletrue
conditionsRouting conditions-

Priority System

Rules are evaluated from highest to lowest priority:

  • Higher numbers = evaluated first
  • First matching rule wins
  • No match = use default URL
Priority 100: iOS → App Store
Priority 90:  Android → Play Store
Priority 0:   (Default) → Website

Condition Types

Device Conditions

TypeOperatorValues
deviceequalsMOBILE, DESKTOP, TABLET
json
{
  "type": "device",
  "operator": "equals",
  "value": "MOBILE"
}

Operating System

TypeOperatorValues
osequals, containsiOS, Android, Windows, macOS, Linux
json
{
  "type": "os",
  "operator": "equals",
  "value": "iOS"
}

Browser

TypeOperatorValues
browserequals, containsChrome, Safari, Firefox, Edge, etc.
json
{
  "type": "browser",
  "operator": "contains",
  "value": "Chrome"
}

Geographic Location

TypeOperatorValues
countryequals, not_equals, inISO country codes (TW, US, CN)
regionequals, containsState/province names
cityequals, containsCity names
json
{
  "type": "country",
  "operator": "in",
  "value": ["TW", "HK", "SG"]
}

Language

TypeOperatorValues
languageequals, containsLanguage codes (zh-TW, en-US)
json
{
  "type": "language",
  "operator": "contains",
  "value": "zh"
}

Time-Based

TypeOperatorValues
timebetween, before, afterTime range (HH:MM format)
day_of_weekinArray of days (1=Monday to 7=Sunday)
json
{
  "type": "time",
  "operator": "between",
  "value": { "start": "09:00", "end": "18:00" }
}
json
{
  "type": "day_of_week",
  "operator": "in",
  "value": [1, 2, 3, 4, 5]
}

Referrer

TypeOperatorValues
referercontains, starts_with, ends_withURL patterns
json
{
  "type": "referer",
  "operator": "contains",
  "value": "facebook.com"
}

UTM Parameters

TypeOperatorValues
utm_sourceequals, containsSource value
utm_mediumequals, containsMedium value
utm_campaignequals, containsCampaign value
utm_termequalsTerm value
utm_contentequalsContent value
json
{
  "type": "utm_source",
  "operator": "equals",
  "value": "newsletter"
}

Operators Reference

OperatorDescriptionExample
equalsExact match"iOS"
not_equalsNot equal"Windows"
containsContains substring"Chrome"
not_containsDoesn't contain"bot"
inIn array["TW", "US"]
not_inNot in array["CN", "RU"]
starts_withStarts with"https://"
ends_withEnds with".com"
betweenIn range (time){"start": "09:00", "end": "18:00"}
beforeBefore (time)"12:00"
afterAfter (time)"18:00"

Combining Conditions

AND Logic

All conditions must match:

json
{
  "operator": "AND",
  "conditions": [
    { "type": "device", "operator": "equals", "value": "MOBILE" },
    { "type": "country", "operator": "equals", "value": "US" }
  ]
}

OR Logic

Any condition can match:

json
{
  "operator": "OR",
  "conditions": [
    { "type": "os", "operator": "equals", "value": "iOS" },
    { "type": "os", "operator": "equals", "value": "macOS" }
  ]
}

Nested Conditions

Combine AND and OR:

json
{
  "operator": "AND",
  "conditions": [
    {
      "operator": "OR",
      "conditions": [
        { "type": "os", "operator": "equals", "value": "iOS" },
        { "type": "os", "operator": "equals", "value": "Android" }
      ]
    },
    { "type": "time", "operator": "between", "value": { "start": "09:00", "end": "18:00" } }
  ]
}

Routing Templates

Use pre-built templates for common scenarios.

Available Templates

Template KeyDescription
APP_DOWNLOAD_IOSRoute iOS users to App Store
APP_DOWNLOAD_ANDROIDRoute Android users to Play Store
MULTILANG_TWRoute Traditional Chinese users
MULTILANG_CNRoute Simplified Chinese users
BUSINESS_HOURSRoute during business hours (9-18, Mon-Fri)
MOBILE_ONLYRoute mobile users
DESKTOP_ONLYRoute desktop users

Create Rule from Template

json
POST /api/urls/{urlId}/routing-rules/from-template

{
  "templateKey": "APP_DOWNLOAD_IOS",
  "targetUrl": "https://apps.apple.com/app/myapp"
}

Managing Rules

List Rules

GET /api/urls/{urlId}/routing-rules

Get Single Rule

GET /api/urls/{urlId}/routing-rules/{ruleId}

Update Rule

json
PUT /api/urls/{urlId}/routing-rules/{ruleId}

{
  "name": "Updated Name",
  "priority": 150,
  "isActive": true
}

Delete Rule

DELETE /api/urls/{urlId}/routing-rules/{ruleId}

Smart Routing Settings

Enable/Disable Smart Routing

json
PATCH /api/urls/{urlId}/routing-rules/settings

{
  "isSmartRouting": true,
  "defaultUrl": "https://example.com/default"
}

Settings:

SettingDescription
isSmartRoutingEnable smart routing
defaultUrlFallback URL when no rules match

Routing Analytics

View rule performance:

GET /api/analytics/urls/{id}/routing

Response includes:

  • Match count per rule
  • Traffic distribution
  • Time series trends

Use Cases

App Store Routing

Route users to the appropriate app store:

json
// Rule 1: iOS → App Store (Priority 100)
{
  "name": "iOS App Store",
  "targetUrl": "https://apps.apple.com/app/myapp",
  "priority": 100,
  "conditions": {
    "operator": "AND",
    "conditions": [{ "type": "os", "operator": "equals", "value": "iOS" }]
  }
}

// Rule 2: Android → Play Store (Priority 90)
{
  "name": "Android Play Store",
  "targetUrl": "https://play.google.com/store/apps/myapp",
  "priority": 90,
  "conditions": {
    "operator": "AND",
    "conditions": [{ "type": "os", "operator": "equals", "value": "Android" }]
  }
}

// Default: Web app

Multilingual Routing

Direct users to localized pages:

json
// Traditional Chinese (Taiwan, Hong Kong)
{
  "name": "Traditional Chinese",
  "targetUrl": "https://example.com/zh-tw",
  "priority": 100,
  "conditions": {
    "operator": "OR",
    "conditions": [
      { "type": "country", "operator": "in", "value": ["TW", "HK"] },
      { "type": "language", "operator": "contains", "value": "zh-TW" }
    ]
  }
}

// Simplified Chinese (China)
{
  "name": "Simplified Chinese",
  "targetUrl": "https://example.com/zh-cn",
  "priority": 90,
  "conditions": {
    "operator": "OR",
    "conditions": [
      { "type": "country", "operator": "equals", "value": "CN" },
      { "type": "language", "operator": "contains", "value": "zh-CN" }
    ]
  }
}

Business Hours Routing

Route differently during office hours:

json
{
  "name": "Business Hours - Live Chat",
  "targetUrl": "https://example.com/live-chat",
  "priority": 100,
  "conditions": {
    "operator": "AND",
    "conditions": [
      { "type": "time", "operator": "between", "value": { "start": "09:00", "end": "18:00" } },
      { "type": "day_of_week", "operator": "in", "value": [1, 2, 3, 4, 5] }
    ]
  }
}

// After hours → FAQ page (default)

Campaign-Specific Routing

Route based on traffic source:

json
{
  "name": "Newsletter Subscribers",
  "targetUrl": "https://example.com/special-offer",
  "priority": 100,
  "conditions": {
    "operator": "AND",
    "conditions": [
      { "type": "utm_source", "operator": "equals", "value": "newsletter" }
    ]
  }
}

Combining with A/B Testing

Smart Routing and A/B Testing work together:

  1. Routing rules evaluated first
  2. If no rule matches, A/B testing applies (if enabled)
  3. Finally, use default URL

This enables segment-specific A/B tests.

Best Practices

  1. Use clear priority ordering - Leave gaps (100, 90, 80) for future rules
  2. Test rules thoroughly - Verify conditions work as expected
  3. Start broad, then narrow - General rules first, specific later
  4. Monitor analytics - Track which rules are matching
  5. Document complex rules - Use descriptive names

Rate Limits

OperationLimit
Rule management30 requests/minute

Next Steps

Released under the MIT License.