Skip to content

Fetching CRM Analytics & Einstein Discovery Metadata with sf CLI: WaveDashboard, WaveRecipe, DiscoveryStory

How to retrieve CRM Analytics (Wave) and Einstein Discovery metadata from Salesforce using sf CLI, including what can and cannot be retrieved via the Metadata API.

This article is part of the Salesforce Admin Git & sf CLI series, a complete guide to version control and metadata management for Salesforce admins. Articles are standalone; no need to read in order.


TL;DR

  • CRM Analytics Metadata API type names all use the Wave* prefix (WaveDashboard, WaveRecipe, WaveDataflow, WaveDataset) regardless of the current product name
  • WaveDataset retrieves the dataset schema and container only, not the actual data rows. The dataset will be empty in the target org until you re-run the recipe or dataflow
  • WaveRecipe must always be deployed alongside its companion WaveDataflow of the same API name, or the deploy will fail
  • CRM Analytics and Einstein Discovery types do not support source tracking. Always use --metadata or --manifest, never sf project pull

What You'll Learn

  • The correct Metadata API type names for CRM Analytics and Einstein Discovery components
  • Which components are metadata (retrievable) vs data (not retrievable)
  • How to retrieve dashboards, lenses, recipes, dataflows, and discovery stories using sf CLI
  • The WaveDataset metadata vs data distinction: why datasets are empty after deployment
  • Known limitations: WaveXmd wildcard bug, WaveRecipe + WaveDataflow pairing requirement
  • How to use package.xml for CRM Analytics retrieves

The Problem

Your org has CRM Analytics dashboards, Einstein Discovery stories, and recipes built up over years. You want to version-control them, but CRM Analytics has some surprising rules about what counts as metadata and what's just data. This article maps out exactly what you can retrieve and what you can't.

Common questions this article answers:

  • How do I retrieve a CRM Analytics dashboard with sf CLI?
  • What type name do I use for sf project retrieve start? Is it WaveDashboard or something else?
  • What is the correct type name for Einstein Discovery stories?
  • Does retrieving a WaveDataset give me the actual data?
  • Why does deploying a WaveRecipe fail?

Quick Answer

Here are the commands you'll use most often:

# List all dashboards
sf org list metadata --metadata-type WaveDashboard --target-org myorg

# Retrieve all dashboards
sf project retrieve start --metadata WaveDashboard --target-org myorg

# Retrieve a specific dashboard
sf project retrieve start --metadata "WaveDashboard:My_Dashboard" --target-org myorg

# Retrieve Einstein Discovery stories
sf project retrieve start --metadata DiscoveryStory --target-org myorg

The product has been renamed several times (Wave Analytics, Einstein Analytics, Tableau CRM, CRM Analytics) but all Metadata API type names kept the original Wave prefix. Use WaveDashboard, WaveRecipe, WaveDataflow, and so on. For Einstein Discovery, the type is DiscoveryStory. There is no EinsteinDiscoveryStory type.

One critical distinction: WaveDataset retrieves the dataset schema (column definitions, field types, dataset name) but not the actual data rows. After deploying a WaveDataset to another org, the container exists but is empty. You must run the recipe or dataflow in the target org to populate it.


Section 1: CRM Analytics Metadata Type Names

The product has gone through four names since launch. The Metadata API type names were set when it was called Wave Analytics and have never changed.

What you see in Analytics Studio Metadata API type name
App WaveApplication
Dashboard WaveDashboard
Lens WaveLens
Dataflow WaveDataflow
Recipe WaveRecipe
Dataset (schema only) WaveDataset
Extended Metadata (XMD) WaveXmd
Custom Component WaveComponent
Analytics App Template WaveTemplateBundle
Geographic Data Configuration EclairGeoData
Einstein Discovery Story DiscoveryStory
Einstein Discovery AI Model DiscoveryAIModel
Einstein Discovery Goal DiscoveryGoal

The Discovery types (DiscoveryStory, DiscoveryAIModel, DiscoveryGoal) do not use a Wave prefix, but they also do not use Einstein as a prefix in the Metadata API.


Section 2: Metadata vs Data: The Critical Distinction

Before running any retrieve commands, it is worth being clear about what the Metadata API can and cannot give you.

Component Retrievable as metadata? What you get
Dashboard Yes (WaveDashboard) JSON definition: all charts, filters, layout
Recipe Yes (WaveRecipe) Recipe step definitions
Dataflow Yes (WaveDataflow) Dataflow JSON pipeline
Dataset schema Yes (WaveDataset) Container definition, field names (NOT the data rows)
Dataset rows (actual data) No Not in Metadata API. Must re-run recipe/dataflow in target org
Lens Yes (WaveLens) Exploration definition
Einstein Discovery Story Yes (DiscoveryStory) Story configuration

The dataset row distinction is the most common source of confusion. When you retrieve WaveDataset and deploy it to another org, you successfully create the dataset container with the correct schema. But the dataset will have zero rows. The data itself is runtime state: it lives in Salesforce's analytics engine, not in the Metadata API. To populate it, you need to re-run the recipe or dataflow in the target org.


Section 3: List Components First

Before retrieving, list what exists in your org to confirm API names.

# List all CRM Analytics apps
sf org list metadata --metadata-type WaveApplication --target-org myorg

# List all dashboards
sf org list metadata --metadata-type WaveDashboard --target-org myorg

# List all recipes
sf org list metadata --metadata-type WaveRecipe --target-org myorg

# List all dataflows
sf org list metadata --metadata-type WaveDataflow --target-org myorg

# List all datasets
sf org list metadata --metadata-type WaveDataset --target-org myorg

# List Einstein Discovery stories
sf org list metadata --metadata-type DiscoveryStory --target-org myorg

The output shows the exact API names you need for targeted retrieves. This step is especially useful when dashboards or stories have spaces or special characters in their labels. The API name will be different from the display name.


Section 4: Retrieve CRM Analytics Metadata

# Retrieve all dashboards
sf project retrieve start --metadata WaveDashboard --target-org myorg

# Retrieve a specific dashboard
sf project retrieve start --metadata "WaveDashboard:My_Dashboard" --target-org myorg

# Retrieve all recipes
sf project retrieve start --metadata WaveRecipe --target-org myorg

# Retrieve a recipe AND its companion dataflow together (required)
sf project retrieve start --metadata "WaveRecipe:MyRecipe" "WaveDataflow:MyRecipe" --target-org myorg

# Retrieve all Wave types together
sf project retrieve start --metadata WaveApplication WaveDashboard WaveLens WaveDataflow WaveRecipe WaveDataset WaveXmd --target-org myorg

WaveRecipe + WaveDataflow must be retrieved and deployed together. When you create a Recipe in Analytics Studio, Salesforce automatically generates a companion WaveDataflow with the same API name. The WaveDataflow is the execution engine; the WaveRecipe holds the transformation steps. When deploying to another org, you must include both or the deploy will fail with: A Recipe must specify a Dataflow.


Section 5: Retrieve Einstein Discovery Metadata

# List Einstein Discovery stories
sf org list metadata --metadata-type DiscoveryStory --target-org myorg

# Retrieve all Discovery stories
sf project retrieve start --metadata DiscoveryStory --target-org myorg

# Retrieve a specific story
sf project retrieve start --metadata "DiscoveryStory:My_Story" --target-org myorg

# Retrieve all Einstein Discovery components
sf project retrieve start --metadata DiscoveryStory DiscoveryAIModel DiscoveryGoal --target-org myorg

The common mistake here is using EinsteinDiscoveryStory as the type name. That type does not exist. Old tutorials and documentation sometimes referenced it speculatively or used internal names. The registered Metadata API type has always been DiscoveryStory.


Section 6: WaveXmd: The Wildcard Bug

WaveXmd stores field labels, aliases, formatting rules, and conditional highlighting for both datasets and dashboards.

# CAUTION: This only retrieves Dataset XMD, NOT Dashboard XMD (known bug)
sf project retrieve start --metadata WaveXmd --target-org myorg

# Workaround: specify dashboard XMD names explicitly
sf project retrieve start --metadata "WaveXmd:My_Dashboard" --target-org myorg

There is a known Salesforce bug where using the * wildcard for WaveXmd returns only Dataset XMD entries. Dashboard XMD is silently skipped. If you need to version-control Dashboard XMD (which includes the conditional formatting and field display rules for dashboards), you must retrieve it by explicit name. Check the Salesforce Known Issues portal for current status on this bug.


Section 7: Retrieve Using package.xml

For repeatable retrieves across environments, use a package.xml manifest.

sf project retrieve start --manifest package.xml --target-org myorg

A complete manifest for CRM Analytics and Einstein Discovery:

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>*</members>
        <name>WaveApplication</name>
    </types>
    <types>
        <members>*</members>
        <name>WaveDashboard</name>
    </types>
    <types>
        <members>*</members>
        <name>WaveLens</name>
    </types>
    <types>
        <members>*</members>
        <name>WaveDataflow</name>
    </types>
    <types>
        <members>*</members>
        <name>WaveRecipe</name>
    </types>
    <types>
        <members>*</members>
        <name>WaveDataset</name>
    </types>
    <types>
        <members>*</members>
        <name>DiscoveryStory</name>
    </types>
    <version>62.0</version>
</Package>

Do NOT use * for WaveXmd in a manifest. You will hit the wildcard bug and miss all Dashboard XMD. Instead, add explicit entries for any Dashboard XMD you want to track:

    <types>
        <members>My_Dashboard</members>
        <members>Another_Dashboard</members>
        <name>WaveXmd</name>
    </types>

Section 8: MDAPI Format

If you need the traditional MDAPI directory format instead of source format:

sf project retrieve start --metadata WaveDashboard --target-org myorg --target-metadata-dir mdapi-output --unzip

This places the retrieved files in the mdapi-output directory in the MDAPI folder structure. Use source format (the default) for ongoing version control. It is easier to diff and review in pull requests.


Section 9: No Source Tracking

CRM Analytics and Einstein Discovery types do NOT support source tracking. You cannot use sf project pull to auto-detect changes made in Analytics Studio. Always use --metadata or --manifest.

# This will NOT detect CRM Analytics changes — do not use for Wave types
sf project pull --target-org myorg

# Use this instead
sf project retrieve start --metadata WaveDashboard WaveRecipe --target-org myorg

Build a habit of retrieving all CRM Analytics types explicitly, either through a manifest or a scripted --metadata command, whenever you make changes in Analytics Studio.


Section 10: After Deployment: Re-run Dataflows and Recipes

Deploying CRM Analytics metadata to a target org is only half the work. After the deploy completes:

  1. Dataset schemas are present in the target org but contain zero rows
  2. Navigate to Analytics Studio in the target org and manually run the recipe or dataflow to populate the data
  3. Before running, confirm that data connections are set up correctly in the target org: SFDC local connectors pointing to the right objects, and any external connectors configured and authenticated
  4. Einstein Discovery stories also need to be re-run against the data in the target org after the initial deploy

Plan for this as a distinct step in any deployment runbook. Deploying the metadata is a prerequisite, but it is not sufficient on its own for CRM Analytics to be functional in the target org.


Troubleshooting

"No such metadata type: EinsteinDiscoveryStory" The correct type name is DiscoveryStory, not EinsteinDiscoveryStory. The Einstein prefix does not appear in any Metadata API type name for Discovery components.

WaveRecipe deploy fails with "A Recipe must specify a Dataflow" You must deploy the companion WaveDataflow alongside the WaveRecipe. Both share the same API name. Retrieve and deploy them together: sf project retrieve start --metadata "WaveRecipe:MyRecipe" "WaveDataflow:MyRecipe" --target-org myorg.

Dashboard XMD not retrieved with wildcard Known bug: --metadata WaveXmd only retrieves Dataset XMD. Retrieve Dashboard XMD by explicit name: --metadata "WaveXmd:My_Dashboard". Alternatively, add explicit member entries in your package.xml.

Dataset deployed but empty in target org Expected behaviour. WaveDataset metadata carries the schema and container definition only, not the data rows. Re-run the recipe or dataflow in the target org to populate it.

No components returned by list command CRM Analytics must be enabled in your org and requires a CRM Analytics license. If the org has no license, these metadata types will not be available and list commands will return zero results.


Frequently Asked Questions

What is the correct type name for a CRM Analytics dashboard?

WaveDashboard. The product has been renamed from Wave Analytics to Einstein Analytics to Tableau CRM to CRM Analytics over the years, but all Metadata API type names kept the original Wave prefix from 2014. The Metadata API type names have never been updated to match the product rename.

If I retrieve and deploy WaveDataset, does the data come with it?

No. WaveDataset metadata moves the schema (column definitions, field names, dataset name, type) but not the actual data rows. After deploying a WaveDataset to a new org, the dataset container exists but is empty. You must run the recipe or dataflow in the target org to populate it.

What happened to the "EinsteinDiscoveryStory" type name I see in old tutorials?

It never existed as a registered Metadata API type. The correct type name has always been DiscoveryStory. Old tutorials that reference EinsteinDiscoveryStory were either speculative or referencing internal names that were never exposed in the Metadata API. Use DiscoveryStory in all sf CLI commands.

Can I retrieve CRM Analytics components from a managed package?

Analytics components in managed packages (with a namespace prefix) can be retrieved for inspection but are read-only. You cannot modify or deploy them back. Only your custom unpackaged analytics components are retrievable and deployable to other orgs.

What does WaveXmd contain and why is the wildcard broken?

WaveXmd (Extended Metadata) stores field labels, aliases, formatting rules, and conditional highlighting for both datasets and dashboards. A known Salesforce bug causes --metadata WaveXmd (wildcard) to return only Dataset XMD entries. Dashboard XMD must be retrieved by explicit name. Check the Salesforce Known Issues portal for the current status of this bug.


Key Takeaways

  • Wave* prefix for everything: CRM Analytics type names all start with Wave regardless of the current product name
  • DiscoveryStory not EinsteinDiscoveryStory: DiscoveryStory is the correct Metadata API type name for Einstein Discovery stories
  • Dataset schema is not dataset data: WaveDataset retrieves the container and schema only, not the actual rows
  • WaveRecipe requires WaveDataflow: always retrieve and deploy them together or the deploy will fail
  • WaveXmd wildcard bug: use explicit names for Dashboard XMD, not *
  • No source tracking: use --metadata or --manifest for all CRM Analytics retrieves

What's Next?

Recommended Reading:

Action Items:

  1. Run sf org list metadata --metadata-type WaveDashboard --target-org myorg to see your dashboards
  2. Retrieve one dashboard: sf project retrieve start --metadata "WaveDashboard:YourDashboard" --target-org myorg
  3. Open the JSON file. Dashboards are stored as JSON, not XML, and are human-readable

Resources & References


Tags: #salesforce #sfcli #crm-analytics #einstein-discovery #metadata #versioncontrol