URL patterns tell the Netskope DEM browser extension which web applications to monitor. Getting them right is the single most important setup step, and the most common source of why am I not seeing data? questions. This guide covers how patterns work, exact syntax, real‑world SPA and MPA examples, and every corner case.
Read this first — the one concept that prevents most mistakes: A URL pattern matches the page (the top‑level navigation). After a page is monitored, the extension automatically captures everything that page loads: all API calls, all resources (JS, CSS, images, fonts), and all cross‑origin requests, including assets served from CDNs or cloud storage such as Amazon S3. You do not list CDN, API, or storage hosts in your patterns; you list the pages of your app, and their traffic follows automatically.
How Capture Actually Works
There are two stages, and confusing them is the root of most configuration errors.
Stage 1: Patterns select the Page
When a tab navigates to a new document, the extension checks the page URL against your app’s urlPatterns (and urlExclusions). If a pattern matches, monitoring starts for that page.
Stage 2: All of the page’s traffic is captured automatically
After a page is monitored, the extension records every request it makes (via the browser’s W3C Resource Timing API):
- The page navigation itself
- Every resource: JavaScript, CSS, images, fonts, media
- Every API call:
fetch,XMLHttpRequest,beacon - Regardless of host: your origin, a CDN, an API subdomain, a third party, or Amazon S3 / Azure Blob storage
The only things that remove traffic are your urlExclusions and a built‑in filter that ignores non‑http(s) requests.
Takeaway: Configure patterns for the pages users visit, not the assets those pages load. If your UI lives at https://app.contoso.com/*, but pulls data from api.contoso.com, and files from S3, the single pattern https://app.contoso.com/* captures all three.
When do you need a pattern for another host? Only when that host is opened as its own top‑level page, like a file that opens in its own tab, an auth page on another domain you want monitored, or a separate sub‑app on another domain.
Pattern Format
<scheme>://<host>[:port][/path]
Scheme
One of: http, https, ws, wss, or *.
*matches any of the four.- The scheme determines the default port.
- Practical guidance: Use
https, or*to be scheme‑agnostic.ws/wssare accepted, but WebSocket traffic is not recorded (RUM is HTTP‑based).
Host
Case‑insensitive. ASCII letters, digits, hyphen, dot, and the wildcard *. IPv6 supported in brackets, like [fe80::7d15:f81e:c9c7:d2d9].
*matches any run of characters, including dots:*.contoso.commatchesmail.contoso.comanda.b.contoso.com.- ⚠️
*.contoso.comdoes not match the apexcontoso.com. Addcontoso.comtoo. - A non‑wildcard host matches exactly —
contoso.comis not its subdomains.
Port
- Omitted: the URL must use the scheme’s standard port (80 for
http/ws, 443 forhttps/wss). A pattern with no port will not match a non‑standard port. :*→ any port.:<number>→ that exact port.
Path
- Omitted/empty → matches all paths (same as
/*). - Starts with
/; may contain*; no?or#. - Matching is exact — a full match of the whole path, not a prefix.
/pathmatches only/path, not/path/or/path/x. Use*to extend. - Consecutive slashes collapse to one (
/a///b→/a/b). - Matched against the URL path only — query (
?…) and fragment (#…) are stripped first.
Not allowed in a pattern
- Query strings. A pattern with
?is rejected. (Matching still ignores a URL’s query, so a presigned S3 URL like…/file?X-Amz-Signature=…matches on its path.) - A literal
*.*is always a wildcard. - Non‑ASCII. Use punycode for IDNs:
www.café.fr→www.xn--caf-dma.fr(regular hyphen-). - No percent‑decoding.
https://contoso.com/test/*does not matchhttps://contoso.com/t%65st.
Golden Rules Top Mistakes
| Number | Rule | Wrong | Right |
|---|---|---|---|
| 1 | To capture a whole app, don’t pin a path (path matching is exact). | https://app.contoso.com/home | https://app.contoso.com/* |
| 2 | Match a path prefix with *. | https://app.contoso.com/portal | https://app.contoso.com/portal/* (under /portal/) or …/portal* (also /portalX) |
| 3 | Cover apex and subdomains. | https://*.contoso.com/* alone | https://contoso.com/* and https://*.contoso.com/* |
| 4 | Allow any port if the app uses one. | https://app.contoso.com/* (misses :8443) | https://app.contoso.com:*/* |
| 5 | List pages, not assets. | adding *.cloudfront.net, *.s3.amazonaws.com to capture assets | just https://app.contoso.com/* — assets captured automatically |
| 6 | Don’t over‑match. | https://*/dashboard (every host on the internet) | https://app.contoso.com/dashboard* |
Real‑world Examples
Here are four types of real-world examples: Single Page Applications, Multi-Page Applications, Apps that use AWS S3 (or other cloud storage), and a typical internal app.
Single Page Applications (SPA)
SPAs load once, then change view via client‑side routing (the path or #fragment changes without a full navigation). The extension matches the initial navigation, so you match the host, not in‑app routes, and you can’t target a #fragment route anyway. The app’s API calls and CDN/storage assets are captured automatically.
| Application | Recommended Pattern(s) | Notes |
|---|---|---|
| Microsoft SharePoint Online | https://contoso.sharepoint.com/* | Add OneDrive https://contoso-my.sharepoint.com/*. Assets from *.sharepointonline.com, *.office.net, Akamai, Azure Blob — captured automatically. |
| Salesforce (Lightning) | https://*.lightning.force.com/*https://*.my.salesforce.com/* | UI and API span both hosts; include both. |
| Google Workspace (Gmail/Docs) | https://mail.google.com/*https://docs.google.com/* | Hash routing (#inbox) is invisible to patterns and needs no config. |
| Atlassian Jira/Confluence Cloud | https://contoso.atlassian.net/* | Single tenant host; APIs same host + *.atlassian.com assets. |
| ServiceNow | https://contoso.service-now.com/* | SPA‑style now/nav/… routing; host pattern covers it. |
Multi‑Page Applications (MPA)
MPAs perform a real navigation for most actions, loading many distinct page URLs. Each navigation is rechecked, so a single host‑level /* covers them; add subdomain/port wildcards if the app spans several.
| Scenario | Recommended pattern(s) | Notes |
|---|---|---|
| Classic app, many paths, one host | https://portal.contoso.com/* | Captures every page (/login, /reports/2024, /admin/users…). |
| App across subdomains | https://*.contoso.com/* + https://contoso.com/* | Covers app., auth., reports. and the apex. |
| Workday | https://*.myworkday.com/* | Pod hosts vary (wd2, wd5…); subdomain wildcard is safest. |
| Non‑standard port | https://app.contoso.com:*/* | Required for e.g. :8443. |
Apps that use Amazon S3 (or other cloud storage)
You almost never need an S3 pattern. Two cases:
- S3 as backend storage for assets/uploads/downloads loaded by your pages → no pattern needed: Captured as resources/API of the monitored page. Presigned URLs match fine (query ignored).
- S3 objects opened directly as their own tab: add a pattern matching the URL style you use:
https://*.s3.amazonaws.com/* https://s3.amazonaws.com/* https://*.s3.*.amazonaws.com/* # regional, e.g. bucket.s3.us-east-2.amazonaws.com
A typical Internal App
UI at https://app.contoso.com, REST API at https://api.contoso.com, files in S3, HTTPS‑only:
https://app.contoso.com/*
That’s it. The api.contoso.com calls and S3 loads are captured automatically because they’re made by the monitored pages. Add an S3 pattern only if users open bucket URLs as standalone tabs; add https://api.contoso.com/* only if users open the API host directly.
Pattern Matching Examples
Verified against the extension’s matching engine. Each row may list several equivalent patterns.
| URL Pattern | Examples of Matches | Examples of Non‑Matches |
|---|---|---|
*://*:**://*:*/* | http://netskope.com:9888https://netskope.com/foo | file://contoso.comftp://contoso.com |
*://**://*/* | http://netskope.comhttp://netskope.com:80/foohttp://netskope.com/foo?a=5#taghttps://netskope.com:443/foo | http://netskope.com:443 (non‑std for http)https://netskope.com:80 (non‑std for https)wss://contoso.com:8080/foo (non‑default port) |
*://contoso.com:80/path | http://contoso.com/pathhttp://contoso.com:80/pathhttps://contoso.com:80/path | http://contoso.com:443/pathhttps://contoso.com/path (:443 ≠ :80) |
*://contoso.com*://contoso.com/*://contoso.com/* | http://contoso.comhttps://contoso.com/foohttps://contoso.com/foo?a=5#tag | http://other.comhttp://contoso.com:8080https://contoso.com:80 |
*://192.168.0.1:* | http://192.168.0.1/foo?a=5#taghttp://192.168.0.1:798/foo | http://192.168.0.2/foo |
*://[fe80::7d15:f81e:c9c7:d2d9] | http://[fe80::7d15:f81e:c9c7:d2d9]/foohttp://[fe80::7d15:f81e:c9c7:d2d9]:80/foo | http://[fe81::7d15:f81e:c9c7:d2d9] |
*://*contoso**://*contoso*/* | http://contoso.com/foohttp://contoso.mail.com/foohttps://acontosoy.com/foo | http://contosi.com |
*://*.contoso.* | http://mail.contoso.com/foohttps://smtp.contoso.other.com/foo | http://contoso.com (apex excluded) |
https://*/path | https://contoso.com/pathhttps://a.contoso.com/pathhttps://other.com/pathhttps://mozilla.com/path?foo=1 | http://contoso.com/path (http)https://contoso.com/path/ (trailing slash)https://contoso.com/a |
https://*/path/ | https://contoso.com/path/https://a.contoso.com/path/https://contoso.com/path/?foo=1 | https://contoso.com/path (no trailing slash)https://contoso.com/a |
https://bar/test/foo | https://bar/test/foohttps://bar///test////foo (slashes collapse) | https://bar/t%65st/foo (no %‑decoding) |
https://bar/t%65st/foo | https://bar/t%65st/foo | https://bar/test/foo (no %‑decoding) |
https://hh/*/b/*/ (corrected) | https://hh/a/b/c/https://hh/d/b/f/https://hh/a/b/c/d/#section1https://hh/a/b/c/d/?foo=bar | https://hh/b/c/ (nothing before /b/)https://hh/a/b/ (no segment after /b/) |
Corner Cases & FAQs
Path matching is exact, not “starts with.” …/reports matches only that page, not …/reports/ or …/reports/2024. Use …/reports/*, …/reports*, or …/* for the whole app.
Trailing slash matters /path ≠ /path/. A bare host (https://app.contoso.com) matches all paths — the simplest “whole app” pattern.
The wildcard host spans dots. *.contoso.* matches mail.contoso.com, mail.contoso.co.uk, smtp.contoso.other.com. Powerful but easy to over‑scope.
*.host.com excludes the apex.
Add a separate host.com pattern for the root domain.
No port = default port only. https://app.contoso.com/* won’t match :8443. Use :*.
Query strings can’t go in a pattern and don’t affect matching.
Why presigned S3 / signed CDN URLs still match a path pattern.
Fragments (#…) are ignored.
You can’t target an SPA hash route (…/#inbox) — match the host.
Resources are captured by the page, not by patterns.
A monitored page’s CDN/API/S3 traffic is captured even though those hosts aren’t listed. Adding a CDN host as a pattern captures nothing unless users open it as a top‑level page.
Over‑broad patterns capture everything. *://*/* monitors every site — volume and privacy concern. Scope to your apps.
WebSockets aren’t recorded
Even with a */ws/wss scheme (RUM is HTTP Resource Timing based).
IDNs need punycode.
café.fr → xn--caf-dma.fr; münchen.de → xn--mnchen-3ya.de.
Cross‑origin timing detail depends on the server.
A cross‑origin resource is always counted, but detailed sub‑timings require a Timing-Allow-Origin response header. Missing it means the resource still appears with limited timing — a server header, not a pattern setting.
urlExclusions remove traffic from a monitored page.
Same syntax; use to drop noisy hosts/paths (analytics, telemetry). Exclusions only remove — never add capture.
Quick Troubleshooting Checklist
IDN host not matching?
Convert to punycode.
No data at all?
Confirm a pattern matches the page URL the user lands on (path‑exactness, apex‑vs‑subdomain). Try the bare‑host …/* form first.
Only the landing page, not the rest?
You pinned a path; switch /page to /* (or /section/*).
Works on app.contoso.com but not contoso.com?
Add the apex pattern.
Nothing on a non‑standard port?
Add :*.
Missing a sub‑app on another domain?
It loads as its own page; add a pattern.
CDN/S3/API requests “missing”?
They’re attributed to their parent page; open the monitored page’s detail, not a standalone host.

