The ugcFilterRules feature in Amplitude's Session Replay SDK enables you to detect and sanitize sensitive user-generated content (UGC) in URLs before it's recorded in session replays and heatmaps. This helps ensure that personally identifiable or sensitive information isn't inadvertently captured.
UGC Filter Rules are configuration objects that define patterns to match URLs and specify replacement text. When the SDK captures URLs during session replay and heatmap recording, it applies these rules to sanitize or anonymize sensitive information such as:
UGC Filter Rules are configured as part of the interactionConfig when initializing the Session Replay SDK:
import { sessionReplay } from '@amplitude/session-replay-browser';
sessionReplay.init('YOUR_API_KEY', {
// ...
// Other Configs
// ...
interactionConfig: {
enabled: true,
ugcFilterRules: [
{
selector: 'https://example.com/user/*/profile',
replacement: 'https://example.com/user/USER_ID/profile'
},
{
selector: 'https://example.com/api/token=*',
replacement: 'https://example.com/api/token=REDACTED'
}
]
}
});
Each UGC Filter Rule is an object with two required properties:
type UGCFilterRule = {
selector: string; // Glob pattern to match URLs
replacement: string; // Text to replace the matched URL
};
selector: A glob pattern string that matches URLs. Supports * (any characters). Multiple wildcards can be used in domains and paths.replacement: The replacement text that will be used when the selector pattern matches a URL.https://*.domain.com/* - matches any subdomain and any pathhttps://site.com/*/* - matches two path segmentshttps://api.com/*/data/* - matches specific patterns with wildcardsThe selector field uses basic glob patterns for URL matching. The current implementation supports:
| Pattern | Description | Example |
|---|---|---|
* |
Matches any sequence of characters | https://example.com/* matches https://example.com/anything |
Key Features:
* in a single pattern (for example,, https://*.domain.com/*/*)* works in domain names (for example,, *.projecttool.com)* can be used in URL paths (for example,, /projects/*/boards/*)Note: Advanced glob features like **, [abc], {option1,option2}, and others are not currently supported.
Remove organization names and sensitive identifiers from project management URLs:
// Filter ticket URLs
{
selector: "https://*.projecttool.com/browse/*",
replacement: "https://ORG_NAME.projecttool.com/browse/TICKET_NUMBER"
}
// Filter project list URLs
{
selector: "https://*.projecttool.com/software/projects/*/list*",
replacement: "https://ORG_NAME.projecttool.com/software/projects/PROJECT_NAME/list"
}
// Filter board URLs
{
selector: "https://*.projecttool.com/software/projects/*/boards/*",
replacement: "https://ORG_NAME.projecttool.com/software/projects/boards/BOARD_ID"
}
// Filter wiki pages
{
selector: "https://*.projecttool.com/wiki/spaces/*/pages/*",
replacement: "https://ORG_NAME.projecttool.com/wiki/spaces/SPACE_NAME/pages/PAGE_NAME"
}
Remove repository details and sensitive paths:
// Filter repository file browser with branch and file paths
{
selector: "https://codehost.com/*/*/tree/*/*",
replacement: "https://codehost.com/USER/REPO/tree/BRANCH/FILES"
}
// Filter repository branch view
{
selector: "https://codehost.com/*/*/tree/*",
replacement: "https://codehost.com/USER/REPO/tree/BRANCH"
}
Remove user IDs from profile URLs:
{
selector: 'https://myapp.com/user/*/profile',
replacement: 'https://myapp.com/user/USER_ID/profile'
}
Before: https://myapp.com/user/12345/profile
After: https://myapp.com/user/USER_ID/profile
Remove sensitive query parameters:
{
selector: 'https://myapp.com/dashboard?token=*',
replacement: 'https://myapp.com/dashboard?token=REDACTED'
}
Before: https://myapp.com/dashboard?token=abc123xyz
After: https://myapp.com/dashboard?token=REDACTED
Filter complex URLs with multiple dynamic segments:
{
selector: 'https://api.example.com/users/*/documents/*/*',
replacement: 'https://api.example.com/users/USER_ID/documents/CATEGORY/DOCUMENT_ID'
}
Before: https://api.example.com/users/john123/documents/private/contract-2023.pdf
After: https://api.example.com/users/USER_ID/documents/CATEGORY/DOCUMENT_ID
Remove email addresses from URL paths:
{
selector: 'https://myapp.com/user/*/settings',
replacement: 'https://myapp.com/user/EMAIL_ADDRESS/settings'
}
Before: https://myapp.com/user/john.doe@company.com/settings
After: https://myapp.com/user/EMAIL_ADDRESS/settings
Rules are applied in order, and the first matching rule wins:
ugcFilterRules: [
// More specific rule - will match first
{
selector: 'https://example.com/user/*/profile/settings',
replacement: 'https://example.com/user/USER_ID/profile/settings'
},
// Less specific rule - will only match if first rule doesn't
{
selector: 'https://example.com/user/*/*',
replacement: 'https://example.com/user/USER_ID/ACTION'
}
]
import { sessionReplay } from '@amplitude/session-replay-browser';
sessionReplay.init('YOUR_API_KEY', {
interactionConfig: {
enabled: true,
ugcFilterRules: [
// Filter project management tool URLs
{
selector: "https://*.projecttool.com/browse/*",
replacement: "https://ORG_NAME.projecttool.com/browse/TICKET_NUMBER"
},
{
selector: "https://*.projecttool.com/software/projects/*/boards/*",
replacement: "https://ORG_NAME.projecttool.com/software/projects/PROJECT_NAME/boards/BOARD_ID"
},
// Filter code repository URLs
{
selector: "https://codehost.com/*/*/tree/*/*",
replacement: "https://codehost.com/USER/REPO/tree/BRANCH/FILES"
},
{
selector: "https://codehost.com/*/*/tree/*",
replacement: "https://codehost.com/USER/REPO/tree/BRANCH"
},
// Filter internal application URLs
{
selector: 'https://myapp.com/user/*/profile',
replacement: 'https://myapp.com/user/USER_ID/profile'
},
{
selector: 'https://api.myapp.com/*?token=*',
replacement: 'https://api.myapp.com/ENDPOINT?token=REDACTED'
},
// Filter admin URLs completely
{
selector: 'https://myapp.com/admin/*',
replacement: 'https://myapp.com/admin/ADMIN_SECTION'
}
]
}
});
The SDK validates UGC Filter Rules during initialization:
selector and replacement must be stringsselector must be a valid URL pattern (start with / or http:///https://)// ❌ Invalid - non-string selector
{
selector: 123,
replacement: 'replacement'
}
// Error: ugcFilterRules must be an array of objects with selector and replacement properties
// ❌ Invalid - non-string replacement
{
selector: 'https://example.com/*',
replacement: 456
}
// Error: ugcFilterRules must be an array of objects with selector and replacement properties
// ❌ Invalid - selector doesn't start with / or http(s)://
{
selector: 'example.com/path',
replacement: 'replacement'
}
// Error: ugcFilterRules must be an array of objects with valid globs
// ❌ Invalid - empty selector
{
selector: '',
replacement: 'replacement'
}
// Error: ugcFilterRules must be an array of objects with valid globs
// ❌ Invalid - whitespace-only selector
{
selector: ' ',
replacement: 'replacement'
}
// Error: ugcFilterRules must be an array of objects with valid globs
Place more specific patterns before general ones:
ugcFilterRules: [
// More specific patterns first
{
selector: 'https://codehost.com/*/*/tree/*/*',
replacement: 'https://codehost.com/USER/REPO/tree/BRANCH/FILES'
},
// Less specific patterns later
{
selector: 'https://codehost.com/*/*/tree/*',
replacement: 'https://codehost.com/USER/REPO/tree/BRANCH'
},
// Most general patterns last
{
selector: 'https://codehost.com/*/*',
replacement: 'https://codehost.com/USER/REPO'
}
]
Make replacements clear and meaningful:
// ✅ Good - descriptive
{
selector: 'https://*.projecttool.com/browse/*',
replacement: 'https://ORG_NAME.projecttool.com/browse/TICKET_NUMBER'
}
// ❌ Avoid - unclear
{
selector: 'https://*.projecttool.com/browse/*',
replacement: 'https://XXX.projecttool.com/browse/XXX'
}
Validate your glob patterns match expected URLs:
// Test with various URL formats
const testUrls = [
'https://mycompany.projecttool.com/browse/PROJ-123',
'https://codehost.com/username/repository/tree/main/src/components',
'https://myapp.com/user/john.doe@email.com/profile'
];
interactionConfig.enabled is true* patterns are supported*)* (any characters) is supported**, [abc], {option1,option2}, ranges, negation, etc. are not supportedImportant: The current implementation uses a simple glob-to-regex conversion. While it supports multiple wildcards and domain patterns, it doesn't support advanced glob features. This covers most common URL filtering scenarios effectively.
June 13th, 2025
Need help? Contact Support
Visit Amplitude.com
Have a look at the Amplitude Blog
Learn more at Amplitude Academy
© 2025 Amplitude, Inc. All rights reserved. Amplitude is a registered trademark of Amplitude, Inc.