はじめに
Experience Cloud の「Customer Service」のテンプレートでサポートサイトを作り、ログインしない人(ゲスト)にも「Contact Support」から問い合わせ(ケース)を送ってほしい。よくある要件です。
ところが、ゲストでフォームを開くと、欄が1つも出ずに次の文だけが出ます。
Looks like you don't have access to create a case. Ask your community manager for access.
ゲストのプロファイルに「ケースの作成」を付けても、項目の権限を足しても、公開し直しても、この文のままでした。原因は 設定ファイル(メタデータ)に出てこない、画面だけの設定が2つ 要ることでした。
この記事では、フォームを出すまでに要った3つの設定と、出したあとに「ゲストに社内のデータが見えていないか」を確かめる方法をまとめます。確かめ方には、テストが何も確かめずに合格していた という落とし穴も入れました。
対象読者
- Experience Cloud(Aura の Customer Service のテンプレート)で、ログインなしの問い合わせフォームを作る管理者
- サイトを外に出す前に、ゲストに何が見えるかを確かめたい方
対象外
- LWR のテンプレートのサイト(確かめていません)
- Web-to-ケース(HTML のフォームを自社サイトに置く方法)。こちらはサイトを使いません
- ログインする顧客のユーザー(共有セットなど)。最後に一言だけ触れます
検証の環境
Developer Edition から作ったスクラッチ org に、Customer Service のテンプレートでサイトを作って検証しました(この記事ではサイト名を「Sample Support」とします)。設定は Salesforce CLI で反映し、画面でしか変えられないところは画面で変えました。Claude Code を道具に使い、「動くはず」「動かないはず」を先に書いてから、結果と突き合わせています。
結論: 要ったのは3つ
| # | 設定 | どこで | メタデータで運べるか |
|---|---|---|---|
| 1 | ゲストのプロファイルに Case の 参照 + 作成 | プロファイル | 運べる(Profile) |
| 2 | Guest Access to the Support API にチェック | サイトの詳細(Classic の画面) | 運べない(画面だけ) |
| 3 |
Selected Quick Actions に GuestCommunityCase を入れる |
同じ画面 | 運べない(画面だけ) |
1だけでは、公開し直してもフォームは出ませんでした。2と3を足して公開し直すと、欄(Subject・Description・Web Email)と Submit が出ました。
なお、Web の項目(SuppliedEmail など)の項目レベルセキュリティは 要りませんでした。後の「つまずき」で書きます。
手順
1. ゲストのプロファイルに Case の参照 + 作成
ゲストのプロファイルは、サイトを作ると1つできます(名前は「Sample Support Profile」のように「<サイト名> Profile」)。
最初に「作成」だけを付けて反映したら、反映が失敗しました。
Permission Create Case depends on permission(s): Read Case
作成には参照が必須です。編集・削除・すべて参照・すべて編集は付けません。
<Profile xmlns="http://soap.sforce.com/2006/04/metadata">
<objectPermissions>
<allowCreate>true</allowCreate>
<allowDelete>false</allowDelete>
<allowEdit>false</allowEdit>
<allowRead>true</allowRead>
<modifyAllRecords>false</modifyAllRecords>
<object>Case</object>
<viewAllRecords>false</viewAllRecords>
</objectPermissions>
</Profile>
「参照を付けたら、ゲストに社内のケースが見えてしまうのでは」と心配になりますが、見えませんでした(後の「確かめ方」で書きます)。ゲストの共有設定は、どのオブジェクトも「非公開」に固定されていて、変えられないためです(公式ヘルプのゲストユーザーの節)。
ここまでで公開し直しても、まだ「Looks like you don't have access to create a case」のままでした。
2・3. サイトの詳細で「Guest Access to the Support API」と「Selected Quick Actions」
ここが本題です。サイトの詳細の Classic の編集画面(URL は /0DM で始まるサイトのレコードの /e)に、次の2つがあります。
- Guest Access to the Support API … チェックを入れる
-
Selected Quick Actions …
GuestCommunityCaseを選んで右に移す
保存して、サイトを公開し直すと、フォームの欄が出ました。
画面へのたどり方
次の順でたどれました(検証の組織で、URL を打たずに押してたどって確かめました)。
- 設定 → Digital Experiences → All Sites
- サイトの行の Workspaces
- Administration → Pages
- いちばん下の Go to Force.com → サイトの詳細が開く(URL は
/0DMで始まる) - Edit を押すと、「Guest Access to the Support API」と「Selected Quick Actions」がある
設定のクイック検索で「Sites」と打って出る画面は、検証の組織では Sites のドメインを登録する案内だけで、サイトの一覧は出ませんでした(Sites のドメインを登録済みの組織なら一覧が出るかもしれません。未確認)。
メタデータに無いことの確かめ
- 2・3を画面で変える前と後で、サイト(
CustomSite)を取り出して比べたら 差分なし -
CustomSiteのファイルにallowGuestSupportApiと書いて反映すると、「invalid at this location」で失敗
メタデータ API のリファレンスの CustomSite の項目の一覧にも、この2つに当たる項目は見当たりませんでした。
つまり、この2つは CLI では運べず、組織ごとに画面で設定する ことになります。Sandbox で作って本番に移すときは、手順書に必ず書いておかないと、本番だけフォームが出ない、ということになります(変更セットでも運べないか、本番への移行そのものは試していません。公式に「手で設定し直す」と書いたページも見つかりませんでした。メタデータに無いことからの推測です)。
送った結果
フォームから送ると「Your case was created.」と出て、ケースができました。できたケースを SOQL で見ると、次のとおりでした。
-
所有者・作成者はゲストではなく、サイトの既定の所有者(検証では管理者)
- 公式ヘルプ「Best Practices and Considerations When Working with the Site Guest User Record」には、設定「Reassign new records created by guest users to the default owner」を有効にすると既定の所有者になる、とあります。ところが検証の組織の「共有設定」の画面には、この設定が見当たりませんでした(あったのは「Secure guest user record access」のチェックだけ)。新しい組織では常に既定の所有者になる、と書いた第三者の記事もありますが、公式では確かめられていません
- 自分の組織で確かめるときは、ゲストで1件送り、
OwnerIdを SOQL で見るのが確実です
- Origin(発生源)は空。「Web」などを入れたいなら、アクションの既定値で入れます
- 送ったゲスト本人にも、そのケースは見えない(ケースの URL を開くとログイン画面に回されました)
「送った問い合わせの状況をあとで見たい」という要件なら、ゲストではなくログインする顧客のユーザーが要ります。
つまずき: 権限を足し続けて3回変わらなかった
最初は、ケースの作成 → メールの項目 → Web の残り3項目、と権限を1つずつ足しては公開し直しました。3回とも同じ文のままでした。
しかも、あとで足した項目の権限は要りませんでした。フォームが出るようになったあとで、Web の4項目(SuppliedEmail・SuppliedName・SuppliedCompany・SuppliedPhone)の権限を外して試した結果です。
- 3項目を外し、
SuppliedEmailだけ残す → フォームは出て、送るとケースができた -
SuppliedEmailも外す(プロファイルに Supplied の項目の権限が1つも無いことを SOQL で確かめた)→ それでも Web Email の欄は出て、送るとケースができ、SuppliedEmailにも値が入った
このフォームは、ゲストの項目レベルセキュリティを見ずに保存しているように見えます(仕組みは推測です)。件名・説明の項目は、ゲストのプロファイルに最初から編集が付いていました。
3回目のあとで足すのをやめ、「ゲストがケースを作る条件」を公式のヘルプで調べて、サイトの詳細の2つに行き着きました。2回足して変わらなかった時点で調べに切り替えるべきでした。画面だけの設定は、プロファイルや取り出したファイルをいくら見ても出てきません。
確かめ方: ゲストに社内のデータが見えていないか
フォームを出すためにケースの参照を付けたので、「社内のケースが見えていないか」を確かめます。2つの方法でやりました。
(1) Apex のテストで、ゲストとして照会・書き換えをしてみる
System.runAs でゲストユーザーになり、社内の取引先・ケースを照会・書き換えします。
@IsTest
private class SampleGuestAccessTest {
static User guest() {
// ゲストの名前は「Site Guest User <サイト名>」。頭で決め打ちしない
List<User> us = [SELECT Id FROM User
WHERE UserType = 'Guest' AND IsActive = true
AND Name LIKE '%Sample Support%' LIMIT 1];
return us.isEmpty() ? null : us[0];
}
@IsTest
static void guestCannotSeeInternalCases() {
User g = guest();
// ゲストが見つからなければ落とす。黙って合格させない
Assert.isNotNull(g, 'ゲストユーザーが見つからない(サイト名・名前の形を確かめる)');
Account a = new Account(Name = '社内の取引先');
insert a;
insert new Case(Subject = '社内のケース', AccountId = a.Id);
System.runAs(g) {
Assert.areEqual(0, countOrDenied('SELECT COUNT() FROM Case WHERE AccountId = \'' + a.Id + '\''),
'ゲストに社内のケースが見えている');
}
}
// 「見えない」の形は2つ: オブジェクトごと拒否(SecurityException)か、0件
static Integer countOrDenied(String q) {
try { return Database.countQuery(q); }
catch (System.SecurityException e) { return 0; }
}
}
書き換えも同じように Database.update(..., false) で試し、失敗することを確かめます。
落とし穴: テストが「何も確かめずに合格」していた
最初のテストは、ゲストを Name LIKE 'Sample Support%' で探し、見つからなければ何もしない 書き方でした。結果は 2件とも合格・100%。
ところが実物のゲストの名前は「Sample Support Site Guest User」ではなく 「Site Guest User Sample Support」 でした。ゲストが見つからず、テストは何も試さずに合格していたのです。
直したことは2つです。
- 名前は
'%Sample Support%'のように前後どちらでも当たる形で探す -
ゲストが見つからなければ
Assert.isNotNullで落とす。前提が無いテストを合格にしない
直したら、今度は失敗しました。既定のゲストは、照会しただけで「0件」ではなく Access to entity 'Case' denied(拒否)になったためです。拒否も「見えない」と数える形(上の countOrDenied)にして、合格しました。拒否だったか0件だったかは、System.debug に結果を書いてデバッグログで確かめました(テストのログは、トレースフラグを付けないと残りません)。
合格の数字だけを見ず、「テストが本当にゲストを見つけて動いたか」をログで1回見る。これが今回いちばんの教訓です。
(2) ログインしないブラウザで、外から開いてみる
シークレットウィンドウなど、ログインしていないブラウザで次を開きます(先に、社内の取引先とケースを1つずつ作っておきます)。
| 開くもの | 期待 | 結果 |
|---|---|---|
| サイトのトップ | 開く | 開いた(Contact Support などが出る) |
社内の取引先 /s/account/<Id>
|
見えない | 「Invalid Page」 |
社内のケース /s/case/<Id>
|
見えない | ログイン画面に回された |
| サイトの検索で社内の名前 | 出ない | 結果なし |
認証なしの REST の照会 /services/data/vXX.X/query
|
拒否 | 401 INVALID_SESSION_ID
|
どれも社内の名前は出ませんでした。
おまけ: ゲストがサイトに入れるまでの「公開」は3段だった
フォーム以前に、ゲストがサイトを開けない、でも詰まりました。公開は次の3段でした。
-
sf community publish(中身を出す)… これだけでは状況は「Under Construction」のまま - Network の
<status>をLiveにして反映 … 状況が Live になる。それでも外からはログイン画面に回された - ExperienceBundle の
config/<サイト>.jsonのisAvailableToGuestsをtrue(画面の「Public can access the site」)にして反映し、もう一度 publish … ゲストが入れた
「公開のボタンが成功した」だけで「公開した」と言わず、ログインしないブラウザで開くまで確かめるのが安全です。
まとめ
- ゲストに Contact Support のフォームを出すには、プロファイル(Case の参照 + 作成)に加えて、サイトの詳細の「Guest Access to the Support API」と「Selected Quick Actions」 が要る
- この2つは メタデータに無く、画面だけ(Workspaces → Administration → Pages → Go to Force.com → Edit)。CLI で運べないので、手順書に書く
- Web の項目(
SuppliedEmailなど)の権限は要らなかった - できたケースの所有者はサイトの既定の所有者。Origin は空。送ったゲストにも見えない
- ゲストのテストは、ゲストが見つからなければ落ちる ように書く。名前は「Site Guest User <サイト名>」
- 外に出す前に、ログインしないブラウザで、社内のレコードの URL・検索・REST を開いて確かめる
筆者は Salesforce の設定の代行・相談を受けています(連絡先は Qiita のプロフィールに)。
参考
- ヘルプ「Secure Guest Users' Sharing Settings and Record Access」 https://help.salesforce.com/s/articleView?id=sf.networks_secure_guest_user_sharing.htm&language=en_US
- ヘルプ「Best Practices and Considerations When Working with the Site Guest User Record」 https://help.salesforce.com/s/articleView?id=sf.networks_guest_user_record_best_practices.htm&language=en_US&type=5
- Salesforce CLI コマンドリファレンス「community Commands」 https://developer.salesforce.com/docs/atlas.en-us.sfdx_cli_reference.meta/sfdx_cli_reference/cli_reference_community_commands_unified.htm