Custom Mapping Configuration
Using a mapping file to tell the browser protector exactly which html elements to unprotect automatically or to automatically select a data element when trying to unprotect.
Custom Mapping Configuration
Custom mappings allow administrators to explicitly tell the Browser Protector which HTML elements on a specific site need to be protected or unprotected.
Custom mappings are defined under the optional customMappings key in the extension configuration JSON.
Structure Overview
customMappings
└── domains[]
├── domain — hostname to scope the rules to
├── page[]
│ ├── path[] — URL path segments to scope rules to (empty = all paths on the domain)
│ └── mappings[] — groups of attribute-based rules
│ ├── attributeName — HTML attribute to inspect (e.g. id, class, aria-label)
│ ├── value — expected attribute value; omit to match on attribute presence alone
│ └── entries[]
│ ├── dataElement — Protegrity data element name to use for the operation
│ ├── operation — "protect" or "unprotect"
│ ├── splitSegments — (optional) split text content into individual tokens before processing
│ └── parentConditions[] — (optional) ancestor element constraints for narrowing matches
└── title[]
├── path[] — URL path segments to scope title rules to (empty = all paths on the domain)
└── algo — identifier for the page title unprotection algorithm to use
Domain Matching
| Pattern | Behavior |
|---|
example.com | Matches example.com and www.example.com only |
*.example.com | Matches all subdomains (app.example.com, crm.example.com, etc.) |
Exact domain entries take precedence over wildcard entries.
To read more about domain rules, go here.
Path Matching
- An empty
path array applies the mapping rules to every page on the matched domain. - When paths are provided, they are matched as substrings of the current URL path (e.g.
"/accounts" matches /accounts/list).
Parent Conditions
parentConditions can optionally restrict a mapping so it only fires when the target element has a specific ancestor within a certain number of DOM levels. Each condition can check the ancestor’s tag name, an attribute name, and/or an attribute value.
Example
The following configuration unprotects any element on crm.example.com that has aria-label="customer-ssn", using the SSN data element:
"customMappings": {
"domains": [
{
"domain": "crm.example.com",
"page": [
{
"path": [],
"mappings": [
{
"attributeName": "aria-label",
"value": "customer-ssn",
"entries": [
{
"dataElement": "SSN",
"operation": "unprotect"
}
]
}
]
}
]
}
]
}
When the extension detects an element such as:
<span aria-label="customer-ssn">***-**-1234</span>
This example html element will match the custom mapping rule above, allowing the Protegrity browser protector to know this is an element that when selected, will use the SSN data element for unprotection.
Page Title Unprotection
The title array within a domain entry enables unprotection of protected values embedded in the browser’s page <title>. This is useful for single-page applications (such as Salesforce) that reflect record data in the tab title after navigation.
Each title entry specifies:
path — URL path scope (empty array = applies to all pages on the domain)algo — the name of the page title extraction algorithm to use
The extension monitors the <title> element for changes and re-runs unprotection on navigation or if the title changes.
Example
"customMappings": {
"domains": [
{
"domain": "myorg.example.com",
"title": [
{
"path": ["/example/r/User"],
"algo": "Example_Algo"
}
]
}
]
}
For a title such as example Title, the extension will unprotect and rewrite the title with the plaintext result.
Notes
- Attribute matching is case-insensitive.
- Class attribute matching supports partial class list matching (i.e. the configured value only needs to appear as one class in a multi-class attribute).
1 - Domain Matching Rules
Domain matching rules for custom mapping matching customization.
Exact Match Rules (config does NOT start with *)
Config: example.com
| Hostname (from URL) | Matches? | Reason |
|---|
example.com | ✅ | Exact |
www.example.com | ✅ | www. stripped → example.com |
example.com/about | ✅ | Path ignored; hostname = example.com |
example.com/login?next=/ | ✅ | Query ignored; hostname = example.com |
hr.example.com | ❌ | Only www. is stripped; hr. is not |
sub.example.com | ❌ | Subdomain not stripped |
app.hr.example.com | ❌ | Multi-level subdomain, no match |
notexample.com | ❌ | Different hostname |
example.com.evil.com | ❌ | Normalized to example.com.evil.com |
Config: www.example.com
| Hostname | Matches? | Reason |
|---|
example.com | ✅ | Config strips www. → example.com |
www.example.com | ✅ | Both strip www. |
hr.example.com | ❌ | hr.example.com !== example.com |
www.hr.example.com | ❌ | Strips to hr.example.com !== example.com |
Config: hr.example.com
| Hostname | Matches? | Reason |
|---|
hr.example.com | ✅ | Exact |
www.hr.example.com | ✅ | www. stripped → hr.example.com |
example.com | ❌ | Parent domain, not matched |
other.example.com | ❌ | Sibling subdomain |
app.hr.example.com | ❌ | Child subdomain; only www. is stripped |
Wildcard Rules (config starts with *)
Both *example.com and *.example.com normalize to base example.com.
| Hostname | Matches? | Reason |
|---|
example.com | ✅ | === base |
www.example.com | ✅ | Strips www. → === base |
hr.example.com | ✅ | Ends with .example.com |
app.hr.example.com | ✅ | Ends with .example.com |
a.b.c.example.com | ✅ | Ends with .example.com |
notexample.com | ❌ | Does not equal or end with .example.com |
other.com | ❌ | Unrelated |
example.com.evil.com | ❌ | Ends with .com, not .example.com |
Exact vs. Wildcard Priority
When both example.com (exact) and *.example.com (wildcard) are in config,
exact entries are evaluated first. Wildcard is only used as a fallback.
| Hostname | Rule used |
|---|
example.com | Exact example.com wins |
www.example.com | Exact example.com wins |
hr.example.com | No exact match → wildcard used |
app.hr.example.com | No exact match → wildcard used |
Things That NEVER Affect Matching
| Component | Example | Effect |
|---|
| Path | /about, /login | Ignored |
| Query string | ?id=123&next=/home | Ignored |
| Hash | #section-2 | Ignored |
| Port | :8080, :443 | Ignored |
| Protocol | https://, http:// | Ignored |
2 - Sibling Match Criteria
The Sibling Match feature lets you unprotect a value only when a nearby element matches context you define, such as label text, element type, direction, or attribute values. Instead of unprotecting every selector match on the page, it adds a nearby-context check so the same selector can be safely reused in different UI sections.
Overview
Sibling matching is configured through siblingMatchCriteria on a mapping entry. It is a context filter: your primary mapping still finds candidate elements, and siblingMatchCriteria decides whether each candidate should be unprotected based on what appears near it.
Use it when:
- The same target element pattern appears in multiple places on a page
- Only one section should be unprotected
- A nearby label or marker identifies the correct context
How to Think About It
Treat it as an “anchor” check:
- The mapping finds a candidate target element.
- The feature looks around that target for a nearby element that matches your criteria.
- If a match is found, the target is unprotected.
- If no match is found, that target is skipped.
This keeps rules precise without requiring fragile or overly specific selectors.
siblingMatchCriteria Fields
labelText (optional) — Text that should appear on the nearby anchor element.elementType (optional) — Expected tag name of the anchor element (for example, label, div, span).attributeName (optional) — Attribute that must exist on the anchor element.attributeValue (optional) — Optional expected value for attributeName.direction (optional) — Where to look relative to the target (left or right).distance (optional) — How far the search can expand through nearby structure.
If you provide multiple fields, they are treated as one combined match. In other words, the same nearby element must satisfy all specified criteria.
HTML Matching Example
Example target and nearby context:
<div class="field-row">
<div title="Account Name">Account Name</div>
<a data-special-link="true">PTY:93f2a1...</a>
</div>
Example mapping entry:
{
"targetElement": "a",
"attributeName": "data-special-link",
"attributeValue": "true",
"entries": [
{
"dataElement": "deName",
"operation": "unprotect",
"siblingMatchCriteria": {
"labelText": "Account Name",
"elementType": "div",
"attributeName": "title",
"attributeValue": "Account Name",
"direction": "left",
"distance": 2
}
}
]
}
In this example, the link is only unprotected when the matching context element (<div title="Account Name">) is present on the left. The same a[data-special-link="true"] elsewhere on the page will be skipped if that context is missing.
Additional Example: Right-Side Match
<div class="field-row">
<span class="value" data-tokenized="true">PTY:0ab123...</span>
<span data-role="field-label">Phone</span>
</div>
{
"targetElement": "span",
"attributeName": "data-tokenized",
"attributeValue": "true",
"entries": [
{
"dataElement": "dePhone",
"operation": "unprotect",
"siblingMatchCriteria": {
"labelText": "Phone",
"attributeName": "data-role",
"attributeValue": "field-label",
"direction": "right"
}
}
]
}
This configuration only unprotects tokenized values when the matching “Phone” label is found to the right.
3 - Table Column Unprotection
The Table Column Unprotection feature lets you unprotect an entire column in an HTML table by specifying its header text, eliminating the need to write individual selector rules per cell. The feature automatically handles complex table structures—including merged cells, deeply nested content, and component-based tables—and provides optional filtering to apply unprotection only to specific tables.
Overview
The Table Column Unprotection feature allows you to target entire table columns using columnMatchCriteria on a mapping entry. Rather than creating selector-based rules that match individual cells row by row, you define a single column mapping that identifies the column by its header label and automatically unprotects all qualifying data cells beneath it.
This is ideal for:
- Protecting sensitive columns in data tables (email, phone, SSN, etc.)
- Avoiding repetitive selector rules when the same column appears across multiple page layouts
- Working with component-based tables (e.g., Salesforce Lightning) where cell markup is complex and nested
How It Works: From Configuration to Unprotection
When a mapping entry includes columnMatchCriteria, the unprotection process follows these steps:
Locate the column — The feature searches the page for <table> elements and finds the target column by matching its header text against columnLabel.
Collect data cells — Once the column is identified, all <td> elements in that column are gathered, along with any <th scope="row"> elements (used by component-based tables to mark per-row headers like “Account Name” or “Contact ID”).
Extract values and unprotect — For each data cell, the feature locates the actual value text (which may be wrapped in nested elements) and sends it for unprotection. The feature intelligently skips visually-hidden helper markup (like “Edit” buttons or sorting labels) to ensure only intended values are unprotected.
Apply filters (optional) — If you’ve specified an attributeName and attributeValue, unprotection only occurs if the target element (table, cell, or header) carries that attribute.
Configuration: columnMatchCriteria
A column mapping entry uses the columnMatchCriteria object to specify which column to unprotect:
columnLabel (required, string) — The visible text of the column header. Matching is case-insensitive and punctuation-tolerant (e.g., “Email Address:” matches configured "email address"). The feature searches the table’s header region (<thead> or leading <th> rows) for a header whose text normalizes to this value.
columnNumber (optional, number, 1-based) — A performance hint: the logical position of the column (e.g., columnNumber: 3 for the third column). When provided, the feature checks this column position first. If the header at that position doesn’t match columnLabel, the feature automatically falls back to a full-column search. This lets you optimize for tables with known column orders while remaining robust to layout changes.
Filtering with Attributes
Like selector-based mappings, you can use attributeName and attributeValue to narrow down which tables or cells are processed:
targetElement — Specifies what to check for the attribute:
"table" — Check the <table> element itself; only process columns in tables carrying the attribute."th" — Check the header cell; only process if the column header carries the attribute."td" (or empty) — Check data cells; only process if at least one data cell in the column carries the attribute.
attributeName and attributeValue — Standard attribute filtering. If attributeName is omitted or empty, no filtering is applied.
Example: If you set targetElement: "table" and attributeName: "data-pii-table", column unprotection only runs on tables marked with data-pii-table.
Handling Multi-Token Values
If a cell contains space-separated values (e.g., “John Doe” or “Open - NotContacted”), use splitSegments: true to unprotect each token individually. This is necessary when your unprotection service requires single-token inputs.
{
"columnMatchCriteria": {
"columnLabel": "Full Name"
},
"splitSegments": true
}
Column Identification Robustness
The feature handles various header and cell markup patterns:
- Wrapped headers — Headers with nested elements (
<th><span>Email</span></th>) are recognized by their visible text content. - Merged headers — Tables with
colspan/rowspan are supported; columns are correctly identified even when headers or data cells span multiple logical positions. - Component markup — Salesforce Lightning, custom Web Components, and other complex nested layouts work correctly because the feature targets the actual value node, not the container.
- Hidden helper text — Helper elements (like “Edit X” button labels or sort indicators) are automatically excluded from unprotection.
Idempotency and Precedence
Idempotency — If a cell is already marked as unprotected (via a previous rule or pass), it is skipped. This prevents redundant unprotection and allows you to layer multiple mapping strategies without conflicts.
Precedence — Column mappings are applied after selector/attribute mappings. This two-phase approach ensures that targeted, specific rules (e.g., a particular field with a unique attribute) take priority, and column mappings only unprotect cells that haven’t already been claimed.
Limitations
- Requires real HTML tables — Only
<table> markup is supported. Tables built from <div> or other grid elements are not detected. - Separate header and data tables — If a page renders headers and data in separate
<table> elements (e.g., sticky headers), the feature may not find the data cells. In such cases, use selector-based mappings as a fallback. - Single column per mapping — Each
columnMatchCriteria identifies one column. If you need to unprotect multiple columns, create multiple mapping entries.
Example Configurations
HTML Matching Examples
Example A: Match by header label
<table>
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>Jane Doe</td>
<td>PTY:a82b9...</td>
<td>Active</td>
</tr>
</tbody>
</table>
{
"entries": [
{
"dataElement": "deEmail",
"operation": "unprotect",
"columnMatchCriteria": {
"columnLabel": "Email"
}
}
]
}
This configuration unprotects values in the Email column across matched tables.
Example B: Match only tables with an attribute
<table data-pii-table="true">
<thead>
<tr>
<th>Employee</th>
<th>SSN</th>
</tr>
</thead>
<tbody>
<tr>
<td>Alex Smith</td>
<td>PTY:9e13f...</td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr>
<th>Employee</th>
<th>SSN</th>
</tr>
</thead>
<tbody>
<tr>
<td>Sam Lee</td>
<td>PTY:0a44c...</td>
</tr>
</tbody>
</table>
{
"targetElement": "table",
"attributeName": "data-pii-table",
"attributeValue": "true",
"entries": [
{
"dataElement": "deSSN",
"operation": "unprotect",
"columnMatchCriteria": {
"columnLabel": "SSN"
}
}
]
}
Only the first table is processed because it matches the table-level attribute criteria.
Simple: Unprotect the “Email” column
{
"targetElement": "th",
"attributeName": "",
"entries": [
{
"dataElement": "deEmail",
"operation": "unprotect",
"columnMatchCriteria": {
"columnLabel": "Email"
}
}
]
}
With fast path hint: Unprotect “Phone” at column 2, fallback to search if mismatch
{
"entries": [
{
"dataElement": "dePhone",
"operation": "unprotect",
"columnMatchCriteria": {
"columnLabel": "Phone",
"columnNumber": 2
}
}
]
}
Filtered: Unprotect “SSN” only in PII tables
{
"targetElement": "table",
"attributeName": "data-pii-table",
"entries": [
{
"dataElement": "deSSN",
"operation": "unprotect",
"columnMatchCriteria": {
"columnLabel": "SSN"
}
}
]
}
Split tokens: Unprotect “Full Name” with token separation
{
"entries": [
{
"dataElement": "deName",
"operation": "unprotect",
"splitSegments": true,
"columnMatchCriteria": {
"columnLabel": "Full Name"
}
}
]
}