Click Protection
Replace URLs with safe redirect links that scan on every click
Overview
Click Protection replaces URLs in record fields with safe redirect links. When a user clicks a protected link, bowbridge performs a fresh scan of the original URL before redirecting. If the URL is clean, the user is redirected transparently. If the URL is malicious, a block page is shown with threat details.
Click Protection replaces all URLs in enabled fields, including URLs that were clean at the time of record creation. This is intentional: a URL that was safe yesterday can become malicious today.
How It Works
- A user clicks a protected redirect link in a record field
- The system looks up the original URL from the mapping record
- A fresh scan is performed on the original URL in real time
- If the URL is clean, the user is redirected to the original destination transparently
- If the URL is malicious, a block page is displayed with security details and the reason for the block
URL Replacement Examples
When Click Protection is enabled, URLs in record fields are replaced with redirect links that point to a scanning page within your Salesforce org.
Simple Text Field
https://partner-site.com/shared-documenthttps://yourorg.my.salesforce.com/apex/URLSafeRedirect?id=a1B5g00000AbCdERich Text or Long Text Field with Multiple URLs
Please review the proposal at https://vendor-portal.com/proposal
and the contract at https://legal-docs.com/contract/2026Please review the proposal at https://yourorg.my.salesforce.com/apex/URLSafeRedirect?id=a1B5g00000AbCdE
and the contract at https://yourorg.my.salesforce.com/apex/URLSafeRedirect?id=a1B5g00000FgHiJWhat Users See When a URL is Blocked
When a user clicks a protected link and the scan detects a threat, a block page is displayed with:
| Field | Example |
|---|---|
| Blocked URL | https://sophostest.com/malware/index.html |
| Status | BLOCKED |
| Security Result | malicious |
| Productivity Result | nsfw |
| Security Score | 10 / 100 |
| Productivity Score | 10 / 100 |
| Reason | Security score 10 (Malicious); Productivity score 10 (NSFW) |
| Matched Category | Shown when the URL was blocked by a category rule (e.g. Gambling) |
Enabling Click Protection
Click Protection is configured per field in the URL Scan Settings.
| Toggle | Effect |
|---|---|
| Scan Enabled | URLs in this field are scanned when the record is saved |
| Click Protection | URLs in this field are replaced with safe redirect links |
Restoring Protected Links
If Click Protection needs to be rolled back for existing records, use Restore All Protected URLs in URL Scan Settings. The restore action rewrites original URLs back into affected records as a background job and writes an Audit Trail entry.
See URL Scan Settings for details.
Adding URL Scanning Triggers to Objects
URL scanning and Click Protection require a Salesforce trigger on each object you want to protect. The trigger fires after records are created or updated and passes control to the URL scanning logic provided by the installed package.
Trigger Code
The trigger code is the same for every object. Only the object name in the trigger definition changes:
trigger YourObjectTrigger on YourObject__c(after insert, after update) {
Triggers.prepare()
.bind(YourProvidedUrlScanningHandler.class)
.afterInsert()
.afterUpdate()
.execute();
}Replace YourObjectTrigger with a descriptive trigger name and YourObject__c with the API name of the object you want to scan.
Examples for Standard Objects
trigger AccountTrigger on Account(after insert, after update) {
Triggers.prepare()
.bind(YourProvidedUrlScanningHandler.class)
.afterInsert()
.afterUpdate()
.execute();
}trigger CaseTrigger on Case(after insert, after update) {
Triggers.prepare()
.bind(YourProvidedUrlScanningHandler.class)
.afterInsert()
.afterUpdate()
.execute();
}trigger LeadTrigger on Lead(after insert, after update) {
Triggers.prepare()
.bind(YourProvidedUrlScanningHandler.class)
.afterInsert()
.afterUpdate()
.execute();
}trigger OpportunityTrigger on Opportunity(after insert, after update) {
Triggers.prepare()
.bind(YourProvidedUrlScanningHandler.class)
.afterInsert()
.afterUpdate()
.execute();
}If an object already has a trigger, do not create a second one. Salesforce does not guarantee execution order for multiple triggers on the same object. Instead, add the URL scanning handler binding to the existing trigger.
Deploying Triggers to Production
Apex code cannot be created or edited directly in production orgs. The Salesforce UI for Apex development (Developer Console, Setup) is read only in production environments. To add a new trigger, you must deploy it from a sandbox or local project.
The most common approach for organizations that manage changes through the Salesforce UI:
Create or refresh a Sandbox
Go to Setup → Sandboxes in your production org and create a new sandbox (or refresh an existing one) to get a copy of your production environment.
Create the trigger in the Sandbox
Open the sandbox and create the trigger using one of these methods:
- Setup → Apex Triggers → New
- Developer Console → File → New → Apex Trigger
- VS Code with Salesforce Extensions
Enter the trigger code as shown above and save.
Verify test coverage
All Apex code in production requires a minimum of 75% code coverage across the org. Run all tests in the sandbox to confirm they pass:
Setup → Apex Test Execution → Select Tests → Run
Create an outbound Change Set
Go to Setup → Outbound Change Sets in the sandbox. Create a new change set and add the trigger as a component.
Upload to Production
Click Upload on the change set. This sends it to the production org for deployment.
Deploy in Production
In your production org, go to Setup → Inbound Change Sets. Find the uploaded change set and click Deploy. Salesforce will run all tests before completing the deployment.
Configure Objects and Fields
After the trigger is deployed, go to the bowbridge app Settings → URL Scan and configure the scanned fields for the new object.
For teams using version control and the Salesforce CLI:
Create the trigger file
Add a new .trigger file in your project under force-app/main/default/triggers/:
trigger AccountTrigger on Account(after insert, after update) {
Triggers.prepare()
.bind(YourProvidedUrlScanningHandler.class)
.afterInsert()
.afterUpdate()
.execute();
}Also create the corresponding .trigger-meta.xml:
<?xml version="1.0" encoding="UTF-8"?>
<ApexTrigger xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>65.0</apiVersion>
<status>Active</status>
</ApexTrigger>Deploy to the target org
sf project deploy start --source-dir force-app/main/default/triggers --target-org your-org-aliasSalesforce runs all tests automatically when deploying to production.
Configure Objects and Fields
After deployment, go to Settings → URL Scan in the bowbridge app and configure the scanned fields for the new object.
If bowbridge is installed as a managed package, triggers for default objects are included automatically. You only need to create triggers manually for custom objects or standard objects not covered by the package.