
Salesforce Experience Cloudの初心者が「Salesforce Experience Cloudデータ セキュリティ ルール ブック」を読んで解説してみた
こんにちは、遠藤です。
「ゆるっとSalesforce #23」では「Experience Cloud権限設定入門」と銘打って「Salesforce Experience Cloudデータ セキュリティ ルール ブック」の読み合わせを行いました。
この「Salesforce Experience Cloudデータ セキュリティ ルール ブック」については、Dreamforce '23のセッション「Best Practices for Data Security in Experience Cloud」にて著者のSavio Joseさん自身が発表しています。
このルールブックではExperience Cloud上でデータをセキュアに公開するための12のルールとしてまとめています。
以下、日本語にわかりやすく訳してみました。

イベントでは、時間の関係で各ルールについての詳細は話せませんでしたが、以下ひとつひとつ解説していきます。
基本的に原文を読まなくても雰囲気をつかめるようにまとめているつもりですが、足りないところは元記事も参照してみてください。
また、Experience Cloudの権限設定について馴染みのない方は、Trailheadモジュール「パートナーとの CRM データの共有 | Salesforce Trailhead」を一度試しておくと良いかと思います。
ルール1: 細かく役割ごとのペルソナを定義する
これは単純なことのように聞こえますが、Experience Cloud の実装を計画しているときに私が経験した基本的なミスの 1 つです。一般的に、優先順位付けされた機能バックログに出くわします。これは素晴らしいことですが、サイトと相互作用するさまざまなペルソナのレンズを通してこれらの機能を見ることも同様に重要です。これにより、データ アクセス要件がわかるだけでなく、セキュリティおよび権限エンジンの原動力にもなります。
原文のCapabilityを日本語に訳するのが難しいですが、まずは実装に入る前に「サイトの利用者のペルソナ(役割)を定義し、ペルソナごとに必要な機能を洗い出す。」ということかと思います。

ペルソナとそれが利用する機能を整理することによって、実装ではそれらを権限セットにマッピングしていくことになると思われます。
原文ではルール3で取り上げていますが、この分析に基づいて以下のように整理します。

ルール2: ゲストユーザーアクセスを精査する
あらゆる種類のデータ漏洩は好ましくありませんが、認証されていない経路からの漏洩は、漏洩を容易にしてしまいます。ゲストユーザーペルソナの必要性を認識した場合、その目的を疑問視し、認証されていないアクセスを正当化するために、具体的な能力レベルまで検討する必要があります。
つまり、ゲストユーザーが必要だった場合は、ゲストユーザの権限はより気をつけて設計しなければならないという話です。
肯定的な面としては、ここ数年、Salesforce はゲストユーザのアクセスをロックする素晴らしい取り組みを行っており、その詳細はこちら(ゲストユーザのセキュリティポリシーとタイムライン)をご覧ください。ドキュメントが非常に充実しているため、詳細には触れませんが、ここでは重要なものをいくつか紹介します:
ここ数年、ゲストユーザーの権限を制限する機能が次々とリリースされセキュリティが強化されてきました。
ゲストユーザーの権限を制限する各機能についてはヘルプの「ゲストユーザーのセキュリティポリシーとタイムライン」にまとまっています。こちらのドキュメントは一度は目を通しておくと良さそうです。
その中からルールブックでは以下の機能をピックアップしています
ゲストユーザーはレコードの所有者にはなれない
共有ルールによってゲストユーザーに付与できる最大の権限は「参照」アクセス権
オブジェクト権限「すべて表示」および「すべて変更」を付与することができない
オブジェクト権限「編集」、「削除」を付与することができない
「公開グループ」「キュー」のメンバーにはなれない
ゲストユーザーによるフローの実行はサポートされなくなった
もし、あなたが正味の新しい組織でスタートするのであれば、すでにこれらの方針が自動的に適用される恩恵を受けていることになる。しかし、Winter '21以前にゲスト・ユーザーにレコードへのアクセスを許可していたサイトがある場合、それらのレコードを保護する措置を講じるまで、そのユーザーによるアクセスは保持されます。
Winter '21 より前に作成したSalesforce組織の場合、ゲストユーザーのセキュリティ強化がデフォルトでは無効なので改めてレビューする必要があります。
以下、セキュリティ強化機能のなかからいくつかを画面で確認してみましょう。
共有ルールによってゲストユーザーに付与できる最大の権限は参照アクセス権
ゲストユーザーの共有ルールの設定は、「共有設定」の各オブジェクト設定で「ルールタイプ」「条件に基づくゲストユーザーアクセス」を選択します。

「ルールタイプ」「条件に基づくゲストユーザーアクセス」を選択した場合、選択可能な権限は確かに「参照のみ」となっています。

参照
オブジェクト権限「編集」、「削除」、「すべて表示」および「すべて変更」を付与することができない
ゲストユーザープロファイルは以下の手順で開くことができます。
1. ワークスペースの「ビルダー」を開き設定アイコンをクリック
2. 「<サイト名>プロファイル」をクリック

以下、ゲストユーザープロファイルのオブジェクト権限の設定です。
設定可能なのは、「参照」と「作成」のみとなっています。

では、ゲストユーザーがレコードを更新または削除可能するユースケースが必要な場合にどうするかというと、システムモードで実装します。詳しくはルール12を参照ください。
参照: ゲストユーザープロファイルの設定
「Authenticated and Guest User Access Report and Monitoring」アプリを活用する
記事中で紹介されているSalesforce Labアプリの「Authenticated and Guest User Access Report and Monitoring」を使って、ゲストユーザーのアクセス権の変更をプロアクティブに監視することができるそうです。
こちらのアプリはヘルプでも紹介されています。
参照: ゲストユーザーが使用可能なレコードの検出
使い方は、アプリをインストールした後に、チェックしたいユーザーにVisualforce「uar.UserAccessReport」とそのApexコントローラー「uar.UserAccessReportController」の権限を付与します。
ゲストユーザーでチェックしたい場合はゲストユーザープロファイルに付与する必要があります。
権限を付与したらコミュニティのURLにパス「/apex/uar__useraccessreport」を付けて開きます。
例: https://sea-goldengate-1955-dev-ed.scratch.my.site.com/UrsaMajor/apex/uar__useraccessreport
以下実際にゲストユーザーで出力したレポートになります。

このアプリの使い方については Authenticated and Guest User Access Report and Monitoring | George Abboud | Substack に詳しい説明がありますので、実際に運用する際はこちらのドキュメントを読む必要がありそうです。
サイトはページごとに公開する
サイトを公開する場合は、全体を公開するのではなく、ページレベルで公開を有効にすることをお勧めします。これにより、サイト全体を制限付きに保ちつつ、公開が必要な特定のページのみを開放することで、より詳細な制御が可能になります。
こちらは、読んでいただいたとおりですが、ゲストユーザーへの公開はサイト単位ではなくなるべくページ単位にしましょうという話です。
個別ページの公開を設定するには、サイトの「ビルダー」 の上部のページのプルダウンからページの「ページの設定」を開きます。

「プロパティ」タブの「ページアクセス」で「公開」選択します。

サイト全体の公開設定は、サイトの「ビルダー」 の「設定」を開き「全般」にあります。

ゲストユーザー用のページまたはコンポーネントのオーディエンス バリエーションを活用する
公開されているページについて、利用者ターゲティングを活用することで、どのデータを利用可能にするかをさらに制限することができます。
例えば、メンバープロファイルページを考慮する場合、ゲストユーザーが全ての情報にアクセスする必要があるか、それとも一部の情報のみかを問うべきです。例としては、コミュニティのニックネームや公開可能な最新の投稿のみかもしれません。これらの決定を事前に行い、ペルソナと能力のマッピング作業の一部として文書化することが重要です。これにより、チームの全員がゲストユーザーがアクセスできる内容を正確に把握できます。
サイトのページまたはコンポーネントのバリエーションを作成し、それをゲストユーザー向けとしてオーディエンスを設定することができます。
各バリエーションの作成方法とオーディエンスの設定方法は以下を参照ください。
LWRサイトはオーディエンスによる切り替えとは仕組みが異なりますが同様のことができるようです。
ゲストユーザーアクセスのテスト
以下は、ゲストユーザーアクセスをテストする箇所について、ルールブックにはありませんが、Dreamforce のセッションで紹介されていたものです。
ブラウザのシークレットウィンドウを利用してサイトを参照する
各公開ページを参照してアクセスレベルを検証する
オブジェクトページを参照する
グローバル検索をテストする
各オブジェクト詳細ページへの直リンクにアクセスする
ルール3: 権限セットと権限セットグループでユーザーのアクセス権限を管理する
これは、Experience Cloud固有の話ではないですが、プロファイルによるオブジェクト権限の設定はSpring ‘26でサポートされなくなります。
今から構築するサイトでは、プロファイルによる権限設定はやめましょうという話です。
参照: Permissions Updates | Learn MOAR Spring '23 - Salesforce Admins
実装面でもプロファイルはモノリシックで運用管理が権限セットより劣ります。レコードタイプの割り当てが必要など特別な理由がない場合は権限セットを利用しましょう。
またルールブックでは権限セットを便利に利用するための2つの機能についても紹介されています。
まだベータですが、権限セットおよび権限セットグループなどを自動で割り当てる設定が可能になります。
試すには、「ユーザー管理設定」で「ユーザーアクセスポリシー(ベータ)」を有効化します。

参照: Enable User Access Policies (Beta)
以下のような画面で、ユーザーの作成または更新をトリガーに権限セット、権限セットグループ、キュー、グループ、パッケージライセンスを割り当てることができます。

項目作成時に項目レベルセキュリティを権限セットで設定可能に
オブジェクトの項目作成ウィザードで、今までは項目レベルセキュリティの設定はプロファイルに対して行っていましたが、この機能を有効化すると権限セットに項目レベルセキュリティを設定することができるようになります。

余談ですが、この記事を執筆している現在では、パッケージ開発で2GPはプロファイルを追加できなくなっていますし、パッケージ開発に含まれる権限設定は権限セットに指定する必要があります。パッケージ開発用のスクラッチ組織では常にこの機能をOnにしておくほうが便利かもしれません。
ルール4: 個人を特定できる情報(PII)を定義し保護する
まずビジネスの観点から、どのようなデータポイントがPIIとみなされるのかについてコンセンサスを得る必要がある。そして、必要に応じてプラットフォームの機能を活用し、カスタム処理を行うことでアクセスを確保する必要がある。
こちらは、この通りでSalesforceには個人情報(PII)を保護する機能があるので、活用しましょうという話ですね。
「ユーザー管理設定」を開き「拡張個人情報管理」を有効化すると、個人情報項目を非表示にできます

識別されたユーザ PII フィールドは、ユーザオブジェクトの PersonalInfo_EPIM というフィールドセットに追加できます。このようなフィールドすべてについて、Experience Cloud サイトのプロファイル ページには空白のフィールドが表示されるか、名前フィールドの場合はニックネームに置き換えられます。詳細については、この詳細ドキュメントを参照してください。
オブジェクトマネージャーで「ユーザー」を開くと項目セット「PersonalInfo_EPIM」が確認できます。こちらの項目セットに含まれるフィールドがPIIとして認識されます。

以下、デフォルトの選択状態から「会社名」と「役職」を外して動作を確認してみます。

以下のように、サイトでユーザーを表示してみると「役職(Title)」と「会社名(Company Name)」が参照可能になりました。
「PersonalInfo_EPIM」に追加されている項目(赤枠)は非表示になっています。「名前」はニックネームが表示されます。

カスタム処理が必要なケース
このEPIM設定の利点は、すべてのOOBコンポーネントとAPIが一度設定されるとこのPII設定を尊重することですが、カスタム処理が必要ないくつかの注意点があります。
ところで「OOBコンポーネント」とは、Out-of-the-Boxコンポーネントの頭文字で、標準で提供されるコンポーネントのことらしいです。
で、EPIM設定を利用しても、以下の注意が必要です。
EPIM設定はApexでは強制されない
EPIMはユーザーオブジェクトしかサポートされていない
ルール5: グローバル設定とサイトごとの設定を把握し、点検する
ここでよく見かける落とし穴は、特定のOOTB(Out Of The Box)コンポーネントが意図した通りに機能するために特定の設定の有効化が必要であるにも関わらず、時間的な制約がある時にはすべてのオプションを有効にする簡単な方法を選びがちであり、これによって意図せずアクセスを開放してしまうことがあるという点です。これらの設定がグローバル組織レベルと個々のサイトレベルで管理されていることを理解することが重要です。
これらの設定がグローバル組織レベルと個々のサイトレベルで管理されていることを理解することが重要です。
標準コンポーネントを使用するために必要なオプションがすぐに探せない場合、とりあえずすべてのオプションを有効化してしまうケースが見受けられるということです。
グローバル設定
1.デジタルエクスペリエンス > 設定
「ロールとユーザー設定」に含まれる以下の設定は、理由がない限りデフォルトのままにしたほうが良いとのことです。

これらのオプションについては、ヘルプの「ロールとユーザー設定の定義」に解説があります。
「パートナー取引先またはカスタマー取引先で有効になっていない取引先責任者の表示をユーザーに許可」
外部ユーザーが社内の連絡先情報にアクセスすることは非常に稀であり、この機能はデフォルトでオフになっています。この機能を有効にすることを決定する場合は、その後の影響に非常に注意する必要があります。
この設定は、検証してみましたがわかりませんでした。ヘルプ「ロールとユーザー設定の定義」には以下の説明があります。
取引先責任者が各自の取引先責任者レコードの親レコードに関連付けられている場合に、ユーザーが参照アクセス権を持つ非公開取引先の取引先責任者を表示できるようにします。
しかし、このオプションが無効のままでも「ユーザーが参照アクセス権を持つ非公開取引先の取引先責任者」は参照できました。共有設定的には問題ないような気がしますが、機能の理解が間違っているのか。こちらは要調査検証です。
参照: サイトで有効になっていない取引先責任者をサイトユーザが表示できない
「セルフ登録、ユーザー作成、およびログインで標準外部プロファイルの使用を許可」
デフォルトで標準の外部プロファイルが無効になっているのは、実装に不要かもしれないいくつかのオブジェクトとシステムの権限が事前に有効になっているためです。さらに、ルール2で述べられているように、プロファイルから権限セットへの移行が推奨されています。
「標準の外部プロファイル」とは、一般的に、「Partner Community User」や「Customer Community User」など、コミュニティやポータルにアクセスする外部ユーザーに付与するプロファイルのことです。
基本的にはこれらは使わずコピーして使うものらしいです。そもそも今後は権限セットを使うようにするべきとのこと。
余談ですが、今回発表するにあたって、トレイルヘッド モジュール「パートナーとの CRM データの共有 | Salesforce Trailhead」を改めて試してみましたが、こちらは標準のプロファイルを使用しているので、このオプションを有効化する必要がありました。

「エクスペリエンスビルダーサイトのゲストユーザーにはバッジを非表示にする」
この設定はデフォルトで有効になっており、認識バッジを利用している場合でも、登録メンバーのみにこの機能を提供することをお勧めします。
レコグニションバッジ という機能があるらしく、このバッジの表示非表示
2.ユーザー表示設定
「ポータルユーザー表示」と「サイトユーザー表示」の2つのオプションがあります。

「ユーザー表示設定」が無効な場合、共有設定上参照できないユーザーを表示しようとすると「Page not available」が表示されます。

参照: Experience Cloud サイトでのユーザー表示設定の制御
「ポータルユーザー表示」を有効にすると「デフォルトの外部アクセス権」に関係なく、同じカスタマー/パートナーポータル取引先に属するポータルユーザーは互いに参照することができるようになります。
以下の図では取引先「Edge Communications」と「Express Logistics and Transport」があり、それぞれにパートナー マネージャーとパートナー ユーザー ロールのユーザーが居ます。
取引先「Edge Communications」のローズは、共有設定では上位のロール階層のショーンは参照できませんが、「ポータルユーザー表示」を有効にすると参照可能になります。

「サイトユーザー表示」を有効にすると「デフォルトの外部アクセス権」に関係なく、サイト内の他の取引先に属するポータルユーザーも参照することができるようになります。
ただし、この設定は、サイトごとの設定の「このサイトの他のメンバーを表示」を併せて有効化する必要があります。
以下の場合、取引先「Edge Communications」のローズは、他の取引先「Express Logistics and Transport」のパートナーユーザー バーバラとデイビスも参照可能になります。

サイトごとの設定
サイトごとの設定は「サイトのワークスペース > 管理 > 詳細」で行います。

各オプションを利用するかどうかは、サイトのユースケースに依るかと思いますので、このセクションで挙げられているオプションの説明の翻訳だけ載せておきます。
「ニックネーム表示」については、ルール4で確認済みです。PIIとして設定している場合はニックネームを表示します。
この設定はデフォルトで有効になっており、名前と姓は個人情報(PII)と見なされるため、推奨されています。
ログインユーザー向けの設定
「このサイトの他のメンバーを表示」
サイトの他のメンバーを表示するには、共有設定の「サイトユーザー表示」を有効にし、その後にこの設定を有効にする必要があります。
前述しましたが、共有設定「ユーザー表示設定」の「サイトユーザー表示」を有効にする必要があります。
ゲストユーザー向けの設定
ゲストユーザー向けの設定は、原文の説明のとおりだと思いますので翻訳だけ載せています。
「ゲストユーザーがサイトで使用可能なアセットファイル、ライブラリファイル、CMS コンテンツを表示できるようにする」
この設定は、ページまたはサイトレベルで公開アクセスが有効になっている場合に自動的に有効になります。トピックス、ブランディング、または外部用に共有されるCMSコンテンツに関連する画像などのアセットへのアクセスを提供します。
「公開 Chatter API 要求へのアクセス権をゲストユーザーに付与」
コミュニティフォーラムの実装に関連しており、注目のトピックやフィードなどのOOTBチャターベースのコンポーネントを活用する場合に適用されます。
「ゲストユーザーがこのサイトの他のメンバーを表示できるようにする」
この設定を無効にすると、ゲストユーザーはメンバーの詳細へのアクセスが完全に制限されますが、コミュニティフォーラムの実装で公開ディスカッションを閲覧する必要がある場合には、この設定を有効にする必要があります。そうでない場合、ユーザーは投稿を見ることができません。
これらのニュアンスを理解することが重要です。したがって、この場合、この設定を有効にしても、メンバープロファイルページを非公開にするか、ルールで述べたようにゲスト向けの観客バリエーションを使用することができます。
ルール6: 適切なクリックジャック保護を有効にする
参照: Experience Cloud サイトのクリックジャック保護の有効化
ルール7: 適切なコンテンツセキュリティポリシー(CSP)を有効にする
参照: Lightning コミュニティのコンテンツセキュリティポリシー | Lightning コミュニティ開発者ガイド | Salesforce Developers
ルール8: 外部ユーザーアクセスの組織全体のデフォルトを制限する
可能な限り「デフォルトの外部アクセス権」を非公開にし、必要に応じてアクセスをオープンにする。最初のうちはオープンな共有モデルが使えるように見えても、アプリケーションが成長するにつれて、データアクセスをロックダウンしなければならないシナリオがしばしば発生します。後でそれを行うよりも、前もってプライベートモデルで始める方が簡単です。利用できるさまざまな共有メカニズムについては、Salesforce のドキュメントに詳しく説明されています。
組織全体のデフォルトとは「共有設定」の「デフォルトの外部アクセス権」のことです。

ちなみに、現在はこの「デフォルトの外部アクセス権」はゲストユーザーには付与されませんが、Winter '20より古い組織では適用されてしまうので気をつける必要があります。
共有設定によるレコードレベルセキュリティの概念自体については、以下のヘルプに掲載されている動画がわかりやすいです。
参照: Experience Cloud サイトでの CRM データの共有
余談ですが、Dreamforceのセッションではルール6〜8までは時間の関係上割愛されていました。セッションではルール9がルール6として紹介されています。
また、以降は開発者向けのルールとなっています。
ルール9: Apexコントローラのアクションでは、オブジェクトアクセス(CRUD),項目レベルセキュリティ(FLS)を強制する
よく見落とされがちなのは、AuraEnabled アノテーションを持つ UI コントローラのパブリックメソッドがある場合、Salesforce フレームワークは、オーラサイト API を介してフロントエンドでこれを利用可能にしているということです。任意のサイトでは、以下のようにブラウザの開発ツールでネットワークタブを検査するだけで、すべてのサイト API を簡単に参照できます。
カスタムのLightningコンポーネントなどを配置しているケースの話です。コンポーネントでUI上操作不可となっている操作もコンポーネントから呼び出されるApexコントローラのAuraEnabledアクションでCURD・FLS のチェックをしていない場合、開発者が意図しない操作を直にAPI叩いて可能です。Apexは、必ずユーザーモードでクエリー・DML操作を記述しましょう。
ルールブックでは具体的に、ブラウザの開発コンソールを開いて、AuraEnabledアクションのパラメータを解析し、実際にPOSTMANから開発者が意図しないDML操作ができる例を解説しています。
SOQLの場合は「WITH USER_MODE」をつけます。
Account[] accounts = [SELECT Id FROM Account WITH USER_MODE];
オブジェクトの参照権限や項目レベルセキュリティ違反があれば例外がスローされます。
DML操作の場合は「as user」をつけるのが最も簡単な方法です。
insert as user account;
ルール 10: 画面(UI)とAPIからのデータアクセスは一貫させなければならない
前のルールで、開発者はUIの観点からすべてがロックダウンされており、私たちが見たように同じ操作を実行する他の手段がないと仮定しましたが、それは事実ではありませんでした。このルールの必要性をさらに強調するために、別の例を見てみましょう。
<<中略>>
カスタムコンポーネントを構築するときと同様に、活用するOOTBライトニングコンポーネントも、データを取得するためにUI APIなどの基礎となるSalesforce APIと連携します。これらのSalesforce APIは、実行ユーザーに付与されたオブジェクトのCRUD、FLS、およびレコードの可視性に厳密に準拠しています。このケースでは、実行ユーザーに連絡先フィールドへのアクセスを許可しているため、以前と同じコンセプトを使用して、今回は特にこの例でUI検索APIを使って悪用される可能性があります。
これは、数年前によく事故ってたやつですね。
オブジェクトの共有設定上公開されているものは、画面に表示しなくても公開されているので注意が必要です。
ルールブックでは、UI APIを介してレコードの情報を簡単に取得するデモを説明しています。
ルール 11: 暗黙的な共有を点検する
そもそも「暗黙的な共有」とはなにか?については、開発者ガイドの「暗黙的な共有 | 企業の規模に応じたレコードアクセス権の作成 | Salesforce Developers」に説明があります。
具体的には取引先の親子関係にともなうアクセス権限などがあります。
このルールもDreamforceのセッションでは割愛されていました。
ルール 12: 「Without Sharing」の使用は控える、必要な場合は適切な保護措置を行う
「without Sharing」は最後の手段とすべきですが、新しいゲストユーザーのセキュリティポリシーや、ポストログインフローとして行えなかった複数ステップの自己登録プロセスなど、特定のシナリオで使用する必要があるかもしれません。これらの場合、ゲストユーザーはレコードに対する編集権限を持っていないため、一部のロジックは「without Sharing」モードで実行する必要があります。フローを使用する場合は、「System Context Without Sharing — Access All Data」オプションでフローを保存して、ゲストユーザーがフローを実行できるようにします。
「without sharing」を指定したApexについては「ゲストレコードのデフォルト所有者の使用に関するベストプラクティスと考慮事項」の「Apex without sharing」に同様の言及があります。
オブジェクトの共有設定は非公開のまま、Apexはシステムモードでオブジェクト権限を無視して更新、削除を実装することになるため、最深の注意を払ってApexとそのテストを記述する必要があります。
ゲストユーザーがレコードを作成し、後で閲覧/更新できるカスタム実装では、レコードを識別しアクセスするために暗号化されたキー(例:暗号化されたレコードID)を使用し、そのレコードを作成した初期のゲストユーザーに対する露出を限定する必要があります。
Apexの場合は、Crypto クラスを使用して実装できそうですが、ベストプラクティスを知りたいところです。
SalesforceのExperience Cloudの学習サイトの記事「Article: Guest User Record Access Development Best Practices | Learn Experience Cloud」にユースケースごとの実装パターンが掲載されています。Cryptoクラスを使用したレコードIDの暗号化の例もあるので参考になりそうです。
まとめ
ルールブックをひととおり目を通してきましたが、Experience Cloudの権限には様々な設定があり、実際に構築・運用をしていないとすべてを把握するのは難しそうな印象でした。
また、このルールブックの内容だけでは把握しきれない内容もあり、各種参考リンクも一読、検証しておきたいところです。
AppExchangeベンダーとしては、ルール12の「非公開 & without sharing」パターンをパッケージに含めてもセキュリティレビューに通るのかは気になるところです。(なかなか実際にレビューに出す勇気はもてませんが)
以上、時間の都合上すべては検証できないない箇所もありましたが、多くは解説できたのではないかと思います。あくまで私はExperience Cloudの経験は浅いため実戦経験を伴う解説ではありませんが参考になれば幸いです。