Skip to content

5 · End-to-End Example

This walks the entire pipeline using an example request from a Salesforce "Apply Discount" action. The goal: detect and record whenever an agent grants a discount / account credit. We reconstruct the finished policy from scratch.


Step 1 — Capture

In Salesforce, with DevTools → Network open and the log cleared, the agent clicks Apply discount. One Fetch/XHR request appears in the Network list.

Step 2 — Find the request

Click the single Fetch/XHR POST to acme.my.salesforce.com/services/apexrest/discount and open its Payload (request body) tab. The body carries an action of ApplyDiscount, which is exactly the action we want.

{
  "action": "ApplyDiscount",
  "record": {
    "opportunityId": "0065g00000ABCDE",
    "discount": { "amount": 17, "currency": "USD" },
    "reason": "LOYALTY_CREDIT",
    "notes": "Discount for testing"
  }
}

Key facts to record:

Fact Value Feeds into
URL https://acme.my.salesforce.com/services/apexrest/discount Application
Method POST Application
mimeType application/json → JSON Search DSL
Direction data is in request.postData Rule Apply To: Request
Identifying field action == "ApplyDiscount" Data Type condition
Value of interest record.discount.amount (the discount) Data Type traversal

Step 3 — Read the shape (plain English)

"In the request whose action is ApplyDiscount, the discount amount is at record.discount.amount."

Single value, no arrays → a straight Object traversal with a Condition to pin the action.

Step 4 — Custom Data Type

Translate the sentence node-by-node:

  • "only ApplyDiscount"Condition with HasKey: action and HasValue: ApplyDiscount
  • "go into record"ObjectKey: record
  • "then discount"Value: { Object: { Key: discount }}
  • "the value at amount"Value: { Object: { Key: amount }}
{
  "Search": {
    "Object": {
      "Condition": {
        "HasKey":   { "Value": "action" },
        "HasValue": { "Value": "ApplyDiscount" }
      },
      "Key": { "Value": "record" },
      "Value": {
        "Object": {
          "Key": { "Value": "discount" },
          "Value": { "Object": { "Key": { "Value": "amount" } } }
        }
      }
    }
  }
}
Field Value
Type (ID) APPLY_DISCOUNT
Name Apply Discount (Salesforce)

Step 5 — Application

A single endpoint handles the action, so the Application is broad and the Data Type does the discrimination. Reuse a shared Salesforce Discount Application (Full URL: acme.my.salesforce.com/services/apexrest/discount, method POST). If creating fresh:

Field Value
Name Salesforce Discount
Definition Full URL → acme.my.salesforce.com/services/apexrest/discount
Method POST

Step 6 — Wire it up (standard config, not HAR-derived)

The capture work is done — you have the Application and the Custom Data Type. The rest is normal Shield configuration (see Mask Formats · Obfuscations · Rules in the admin docs). For this use case — detect & record, not hide:

Object Setting
Mask Format Detect Only
Obfuscation Data Type Apply Discount (Salesforce) + Detect Only, Store Value: YES (so the granted amount lands in the activity log)
Rule Action Detect; Apply To: Request (data was in request.postData); Application Salesforce Discount; the Obfuscation above

Step 7 — Verify

Re-fire the request (repeat the action in Salesforce with the rule live) and confirm an activity-log entry appears showing APPLY_DISCOUNT detected with the stored amount. If it doesn't fire, check, in order: Application URL/method match → Search finds the action → the record.discount.amount path is exact. (See the full troubleshooting checklist.)


The same pipeline, response side

For contrast, a HubSpot "hide contact list" policy runs the opposite direction — and the only structural differences come straight from the captured message:

Step Apply Discount (this page) Hide Contact List
Data lives in request.postData response.content
Apply To Request Response
URL match acme.my.salesforce.com/services/apexrest/discount Regex api\.hubapi\.com\/crm\/v3\/objects\/contacts\?.*
DSL needs object traversal object traversal with a Condition per array element (type == contact)
Mask Format Detect Only Fully Obfuscate
Action Detect Block

Same five objects, same procedure — the message dictates every difference. That's the whole method: read the message, describe the location, choose the action.


← Back to the overview.