CRM Analytics, the platform once known as Einstein Analytics and Tableau CRM, stores its own copies of Salesforce data inside datasets, and those datasets do not automatically inherit whatever masking rule you applied to the underlying objects. A sandbox refresh that masks Accounts, Contacts, and Cases perfectly can still leave an untouched CRM Analytics dataset sitting right next to it, loaded with live customer names, emails, and phone numbers. If your masking tool only reaches standard and custom objects, your analytics layer is a compliance gap that's just waiting for an auditor, or a curious QA contractor, to find it.
Most teams don't build masking programs with this in mind. They think in terms of records: Contact.Email, Lead.Phone, Case.Description. CRM Analytics thinks in terms of extracted, transformed, and loaded datasets that live in a separate repository with their own refresh schedule. Those two worlds rarely get reconciled, and that's the problem this article is about.
Why CRM Analytics Datasets Sit Outside the Masking Perimeter
A masking job that runs SOQL updates against Salesforce records changes what's stored in the object. It does not touch the Analytics repository, because the repository isn't part of the object model at all. Datasets are built by dataflows or recipes that extract fields, join them, transform them, and load the result into a columnar store designed for dashboards and lenses, not for record-level governance.
Picture a recipe called Customer 360 that pulls Contact.Email, Contact.Phone, Contact.MailingAddress, and Opportunity.Amount into one dataset feeding a revenue dashboard. Your masking tool scrambles the Contact and Opportunity records perfectly. The dataset built from last night's run still shows the real customer, because it was extracted before the masking job touched anything, and it will keep showing real data until someone reruns the recipe against the now-masked records.
Dataflows and Recipes Keep Re-Extracting Live PII
Here's the part that trips up even careful admins: dataflows and recipes run on their own schedule, independent of your sandbox refresh cadence. A nightly dataflow doesn't know or care that a masking job ran at 2am. It just pulls whatever is currently in the objects at execution time.
If the extraction runs before your masking job finishes, or if the two jobs aren't sequenced at all, the dataset loads real PII straight into a sandbox that everyone assumes is clean. Order of operations matters here as much as the masking logic itself. Get the sequence wrong once and you've shipped a fully populated, browsable dataset of real customer data to a full copy sandbox that outside QA vendors can log into.
The fix isn't complicated, but it does require discipline: pause dataflow and recipe schedules before the masking job starts, let masking finish completely, then trigger the extraction so the dataset is built from already-masked records. Skip that ordering and you've built a very good masking process that quietly ships an unmasked side door.
The Sandbox Refresh Blind Spot Nobody Plans For
Analytics gets treated as a reporting bolt-on rather than a data store in its own right, and that framing causes teams to forget it exists when they plan a refresh. The admin refreshes the sandbox, runs the masking script against standard objects, checks the box, and declares the environment safe.
Meanwhile, anyone with the Analytics Cloud Analytics User permission can open a dashboard and see full customer names that the object-level field security would have hidden from them on the Contact record directly. That's a genuinely odd outcome: a sales rep with no field-level access to Contact.Email can still see it plainly in a chart, because CRM Analytics permissions and object-level security are two separate systems that don't talk to each other.
Dashboard caching adds another wrinkle. Even after you rerun the recipe against masked data, users with recently viewed dashboards may still see cached results from the pre-mask run until the app forces a recompute. It's a small detail, but small details are exactly what auditors like to poke at.
What GDPR Actually Expects From This Layer
Article 25 requires data protection by design and by default across processing activities, and nothing in that language carves out an exception for analytics repositories versus core objects. Article 32 requires appropriate technical measures for the security of processing, full stop. A regulator reviewing a breach doesn't care that the exposed data sat in a CRM Analytics dataset instead of a Contact record; identifiable personal data is identifiable personal data regardless of which Salesforce subsystem holds it.
Auditors have caught up to this too. Data protection impact assessments increasingly ask for an inventory of all environments and copies where personal data lives, not just a list of masked objects. If your documentation stops at "standard and custom objects are masked" and says nothing about CRM Analytics, Marketing Cloud Connect syncs, or CRM Analytics for Slack integrations, expect that gap to get flagged. Regulators don't grade on effort. They grade on exposure, and an unmasked dataset counts as exposure whether anyone noticed it or not.
Building a Masking Process That Actually Covers Analytics
Closing this gap means treating dataflows and recipes as a dependency of the masking job, not an afterthought that happens whenever it happens. That's a sequencing and governance change more than a technical one, and it's worth writing down as a repeatable process rather than tribal knowledge held by one admin.
- Inventory every dataflow and recipe that touches an object containing PII, and note their schedules.
- Disable or pause those schedules before the object-level masking job runs.
- Run the masking job to full completion, including any referential integrity checks.
- Trigger a manual or scheduled recipe run against the now-masked object data.
- Spot-check the resulting dataset in the CRM Analytics data manager to confirm masked values appear, not cached originals.
- Force a dashboard recompute or clear recently viewed history before re-enabling user access.
- Re-enable the original schedules once you've confirmed the dataset is clean.
For orgs with heavy CRM Analytics usage, it's worth building this into the same runbook that governs the sandbox refresh itself, with the analytics rerun as a named step that has to complete before the sandbox gets handed back to QA or offshore development teams. Treat it as a blocking dependency, the same way you'd treat a validation rule failure or a broken lookup, and the gap stops being a gap.
We've seen teams spend weeks perfecting field-level masking rules for Contact and Lead, then hand a sandbox to an outsourced QA vendor where a single dashboard shows every customer's real name, email, and deal size in one screen. That's not a small oversight. It's the kind of finding that turns a routine internal audit into an incident report, and it's entirely avoidable once dataflows and recipes are part of the masking conversation instead of an afterthought.
Frequently Asked Questions
Does masking Salesforce objects automatically mask CRM Analytics datasets?
No. CRM Analytics datasets are built by dataflows and recipes that extract and store their own copy of the data outside the standard object model. Masking a Contact or Account record does nothing to a dataset that was already extracted, and it won't affect future extractions unless the dataflow or recipe is rerun after the masking job completes.
Why would a user see real PII in a CRM Analytics dashboard when their Contact field access is restricted?
CRM Analytics permissions operate independently from Salesforce object-level and field-level security. A user can lack access to Contact.Email on the record itself but still see that same email plainly in a dashboard, because the dataset was built with the field included and dashboard visibility is governed by Analytics-specific permission sets, not the underlying object's security settings.
When should dataflows and recipes run relative to a sandbox masking job?
They should be paused before the masking job starts and only rerun after the masking job has fully completed. Running an extraction before masking finishes pulls live, unmasked PII into the dataset, and that dataset will keep showing real data until the recipe is triggered again against already-masked records.
Is an unmasked CRM Analytics dataset actually a GDPR risk, or just a technical oversight?
It's a genuine GDPR risk. Articles 25 and 32 require appropriate protection of personal data across processing activities and environments, with no carve-out for analytics repositories versus core Salesforce objects. An auditor or regulator treats identifiable data in a dataset the same as identifiable data in a Contact record.
How do I check whether a CRM Analytics dataset still contains real customer data after a sandbox refresh?
Open the dataset in the CRM Analytics data manager and inspect a sample of rows for fields like email, phone, and mailing address rather than relying on a dashboard view, which may show cached results. If the values match production records, the recipe or dataflow needs to be rerun against the masked object data and the dashboard cache cleared before granting user access.