Skip to main content
Route targeting allows you to show popups only on specific pages or routes in your application. The SDK uses the segments.path field to match the current URL against your targeting rules.

How Route Targeting Works

When a popup definition includes segments.path, the SDK evaluates the current route before showing the popup:
  1. User navigates to a page
  2. SDK checks if the current URL matches any path in segments.path
  3. Popup shows only if there’s a match and conditions are met
segments.path is the only segment currently evaluated by the SDK runtime. Other segment fields may be used for organization but won’t affect popup display.

Basic Path Matching

Homepage

Target the root path:
segments: {
  path: ['/']
}
Matches:
  • https://example.com/
  • https://example.com (trailing slash optional)
  • https://example.com/about

Specific Pages

Target named routes:
segments: {
  path: ['/pricing', '/features', '/contact']
}
Matches:
  • https://example.com/pricing
  • https://example.com/features
  • https://example.com/contact
  • https://example.com/about

Hash Routes

Support single-page applications with hash routing:
segments: {
  path: ['/#/home', '/#/dashboard', '/#/settings']
}
Matches:
  • https://example.com/#/home
  • https://example.com/#/dashboard
  • https://example.com/#/profile

Path Matching Rules

The SDK normalizes and compares URLs using these rules:

Full URL Matching

If the path starts with http:// or https://, it’s matched as a complete URL:
segments: {
  path: ['https://example.com/pricing']
}
  • ✅ Exact match required
  • ❌ Won’t match http://example.com/pricing (protocol must match)
  • ❌ Won’t match https://other.com/pricing (domain must match)

Path Fragment Matching

If the path starts with /, it’s matched as a path fragment:
segments: {
  path: ['/pricing']
}
  • ✅ Matches if the current URL contains the path
  • ✅ Works with any domain
  • ✅ Example: https://example.com/pricing

Relative Path Matching

If the path doesn’t start with http://, https://, or /, it’s matched against the pathname:
segments: {
  path: ['pricing']
}
  • ✅ Matches the pathname exactly
  • ✅ Example: If pathname is pricing, it matches
  • ❌ Won’t match /pricing or /pages/pricing

URL Normalization

The SDK normalizes URLs before comparison:

Trailing Slashes

Removed from the end of URLs:
// These are equivalent:
'https://example.com/pricing/'
'https://example.com/pricing'

index.html

Removed from URLs:
// These are equivalent:
'https://example.com/index.html'
'https://example.com/'

'https://example.com/pricing/index.html'
'https://example.com/pricing'
You don’t need to worry about trailing slashes or index.html in your path definitions. The SDK handles normalization automatically.

Advanced Examples

Multiple Pages

Target several related pages:
const popupDefinition = {
  id: 'popup-product-pages',
  title: 'Product feedback',
  message: '<p>Help us improve our product pages.</p>',
  triggers: {
    type: 'time_on_page',
    value: 10,
  },
  surveyId: 'survey-product',
  productId: 'product-main',
  segments: {
    path: [
      '/products',
      '/features',
      '/pricing',
      '/demo',
    ]
  },
};

Hash Route Application

Target specific views in a single-page app:
const popupDefinition = {
  id: 'popup-dashboard',
  title: 'Dashboard feedback',
  message: '<p>How can we improve your dashboard?</p>',
  triggers: {
    type: 'scroll',
    value: 50,
  },
  surveyId: 'survey-dashboard',
  productId: 'product-main',
  segments: {
    path: [
      '/#/dashboard',
      '/#/analytics',
      '/#/reports',
    ]
  },
};

Combining Full URLs and Paths

Mix different path types:
segments: {
  path: [
    'https://example.com/special',  // Exact URL
    '/general',                      // Path fragment
    '/#/app',                        // Hash route
  ]
}

No Path = All Routes

If you don’t specify segments.path, the popup can appear on any route:
const popupDefinition = {
  id: 'popup-global',
  title: 'General feedback',
  message: '<p>How is your experience?</p>',
  triggers: {
    type: 'time_on_page',
    value: 30,
  },
  surveyId: 'survey-general',
  productId: 'product-main',
  // No segments.path → shows on all routes
};
Use global popups sparingly. Targeting specific routes leads to better, more contextual feedback.

Exit Popups and Route Targeting

For exit triggers, segments.path specifies the source routes to watch:
const exitPopup = {
  id: 'popup-pricing-exit',
  title: 'Pricing feedback',
  message: '<p>What made you leave?</p>',
  triggers: {
    type: 'exit',
    value: 3,
  },
  surveyId: 'survey-exit',
  productId: 'product-main',
  segments: {
    path: ['/pricing'] // Show when user LEAVES /pricing
  },
};
Learn more in the Exit Popups guide.

Source Code Reference

Path matching logic is in src/core/deepdots-popups.ts:247-283:
private matchesSegmentsPath(def: PopupDefinition, pathUrl?: string): boolean {
  const paths = def.segments?.path;
  if (!paths || paths.length === 0) return true;
  
  const normalizedHref = this.normalizeUrl(pathUrl || window.location.href || '');
  const currentUrl = this.safeParseUrl(normalizedHref);
  const normalizedPath = this.normalizeUrl(currentUrl?.pathname || window.location.pathname || '');

  const matches = paths.some(rawCandidate => {
    const candidate = this.normalizeUrl(rawCandidate);
    let match = false;
    if (candidate.startsWith('http://') || candidate.startsWith('https://')) {
      match = normalizedHref === candidate;
    } else if (candidate.startsWith('/')) {
      match = normalizedHref.includes(candidate);
    } else {
      match = normalizedPath === candidate;
    }
    return match;
  });

  return matches;
}

Debugging Path Matching

Enable debug mode to see path matching logs:
popups.init({
  mode: 'client',
  debug: true,
  popups: definitions,
});
Logs include:
  • Current pathname and href
  • Candidate paths being evaluated
  • Whether each path matched
  • Why popups were blocked

Common Patterns

Target welcome and setup pages:
segments: {
  path: ['/welcome', '/setup', '/onboarding']
}
Target conversion funnel pages:
segments: {
  path: ['/cart', '/checkout', '/payment']
}
Target blog or documentation:
segments: {
  path: ['/blog', '/docs', '/help']
}
Target specific app features:
segments: {
  path: ['/#/dashboard', '/#/analytics', '/#/settings']
}

Limitations

No wildcard support: The SDK doesn’t support glob patterns like /products/* or regex matching. You must list specific paths.
To target multiple related pages, list them explicitly:
// Instead of: '/products/*'
segments: {
  path: [
    '/products/widget-a',
    '/products/widget-b',
    '/products/widget-c',
  ]
}

Best Practices

Target pages where feedback is most valuable:
// Good: Specific high-value pages
segments: { path: ['/pricing', '/demo'] }

// Avoid: Too broad
segments: { path: ['/'] } // Every page
Ensure hash routes include the #:
// Correct
segments: { path: ['/#/dashboard'] }

// Won't work
segments: { path: ['/dashboard'] } // Missing #
Verify path matching during development:
popups.init({
  mode: 'client',
  debug: true, // See matching logs
  popups: definitions,
});

Next Steps

Exit Popups

Use route targeting with exit triggers

Event Triggers

Combine routes with business events

Server Mode

Manage route targeting remotely

Client Mode

Define route targeting inline

Build docs developers (and LLMs) love