b2c-custom-objects について
Salesforce B2C Commerce の開発者向けに、標準オブジェクト以外の業務データを扱うカスタムオブジェクトの技術資料です。Script API、OCAPI、SCAPI によるスコープ、CRUD、検索、購入者の読み取り専用アクセスを説明します。
主な機能
- 01サイト・組織スコープ
- 02Script API の CRUD 操作
- 03OCAPI のデータ・検索エンドポイント
- 04SCAPI による購入者の読み取り専用アクセス
- 05カスタムオブジェクトの検索パターン
活用シーン
- 01サイト別・グローバル設定の保存
- 02外部連携データのキャッシュ
- 03ロイヤルティ階層やベンダーデータの管理
- 04インポートやジョブキューの一時保管
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ salesforcecommercecloud/ b2c-developer-tooling --skill b2c-custom-objectsインストール後、Claude Code で/b2c-custom-objectsを入力して読み込まれたか確認します。
同梱ファイルevals/trigger-evals.jsonreferences/OCAPI-SEARCH.md
詳細
B2C カスタムオブジェクト
カスタムオブジェクトは、標準のシステムオブジェクトに適合しないビジネスデータを保存します。サイトスコープおよび組織スコープ(グローバル)のデータに対応し、Script API と OCAPI を介した完全な CRUD 操作が可能です。
カスタムオブジェクトを使用する場面
| ユースケース | 例 |
|---|---|
| ビジネス設定 | サイトごと、またはグローバルに設定を保存する |
| インテグレーションデータ | 外部システムの応答をキャッシュする |
| カスタムエンティティ | ロイヤルティティア、カスタムプロモーション、ベンダーデータ |
| 一時的な処理 | ジョブ処理キュー、インポート用ステージング |
カスタムオブジェクトタイプ
カスタムオブジェクトは、Business Manager の Administration > Site Development > Custom Object Types で定義します。各タイプには次の項目があります。
- ID:一意の識別子(例:
CustomConfig) - キー属性:検索に使用する主キーのフィールド
- 属性:データ保存用のカスタム属性
- スコープ:サイトスコープまたは組織スコープ(グローバル)
Script API(CustomObjectMgr)
カスタムオブジェクトの取得
var CustomObjectMgr = require('dw/object/CustomObjectMgr');
// Get a single custom object by type and key
var config = CustomObjectMgr.getCustomObject('CustomConfig', 'myConfigKey');
if (config) {
var value = config.custom.configValue;
}
カスタムオブジェクトの作成
var CustomObjectMgr = require('dw/object/CustomObjectMgr');
var Transaction = require('dw/system/Transaction');
Transaction.wrap(function() {
// Create new custom object (type, keyValue)
var obj = CustomObjectMgr.createCustomObject('CustomConfig', 'newKey');
obj.custom.configValue = 'myValue';
obj.custom.isActive = true;
});
カスタムオブジェクトのクエリ
var CustomObjectMgr = require('dw/object/CustomObjectMgr');
// Query with attribute filter
var objects = CustomObjectMgr.queryCustomObjects(
'CustomConfig', // Type
'custom.isActive = {0}', // Query (uses positional params)
'creationDate desc', // Sort order
true // Parameter value for {0}
);
while (objects.hasNext()) {
var obj = objects.next();
// Process object
}
objects.close();
カスタムオブジェクトの削除
var CustomObjectMgr = require('dw/object/CustomObjectMgr');
var Transaction = require('dw/system/Transaction');
Transaction.wrap(function() {
var obj = CustomObjectMgr.getCustomObject('CustomConfig', 'keyToDelete');
if (obj) {
CustomObjectMgr.remove(obj);
}
});
タイプの全オブジェクトの取得
var CustomObjectMgr = require('dw/object/CustomObjectMgr');
// Get all objects of a type
var allConfigs = CustomObjectMgr.getAllCustomObjects('CustomConfig');
while (allConfigs.hasNext()) {
var config = allConfigs.next();
// Process
}
allConfigs.close();
CustomObjectMgr API リファレンス
| メソッド | 説明 |
|---|---|
getCustomObject(type, keyValue) | タイプとキーを指定して単一のオブジェクトを取得する |
createCustomObject(type, keyValue) | 新しいオブジェクトを作成する(トランザクション内) |
remove(object) | オブジェクトを削除する(トランザクション内) |
queryCustomObjects(type, query, sortString, ...args) | フィルターを使用してクエリする |
getAllCustomObjects(type) | タイプの全オブジェクトを取得する |
describe(type) | カスタムオブジェクトタイプのメタデータを取得する |
OCAPI Data API
カスタムオブジェクトの取得
GET /s/-/dw/data/v25_6/custom_objects/{object_type}/{key}
Authorization: Bearer {token}
注: サイトスコープのオブジェクトには /s/{site_id}/dw/data/v25_6/custom_objects/... を、組織スコープ(グローバル)のオブジェクトには /s/-/dw/data/v25_6/custom_objects/... を使用してください。
カスタムオブジェクトの作成
PUT /s/-/dw/data/v25_6/custom_objects/{object_type}/{key}
Authorization: Bearer {token}
Content-Type: application/json
{
"key_property": "myKey",
"c_configValue": "myValue",
"c_isActive": true
}
カスタムオブジェクトの更新
PATCH /s/-/dw/data/v25_6/custom_objects/{object_type}/{key}
Authorization: Bearer {token}
Content-Type: application/json
{
"c_configValue": "updatedValue"
}
カスタムオブジェクトの削除
DELETE /s/-/dw/data/v25_6/custom_objects/{object_type}/{key}
Authorization: Bearer {token}
カスタムオブジェクトの検索
POST /s/-/dw/data/v25_6/custom_objects_search/{object_type}
Authorization: Bearer {token}
Content-Type: application/json
{
"query": {
"bool_query": {
"must": [
{ "term_query": { "fields": ["c_isActive"], "operator": "is", "values": [true] } }
]
}
},
"select": "(**)",
"sorts": [{ "field": "creation_date", "sort_order": "desc" }],
"start": 0,
"count": 25
}
検索クエリのタイプ
| クエリタイプ | 説明 | 例 |
|---|---|---|
term_query | 完全一致/比較 | {"fields": ["c_status"], "operator": "is", "values": ["active"]} |
text_query | 全文検索 | {"fields": ["c_name"], "search_phrase": "test"} |
filtered_query | クエリとフィルターの組み合わせ。範囲検索には range_filter を使用します | {"query": {"match_all_query": {}}, "filter": {"range_filter":{"field": "c_count", "from": 1, "to": 10}}} |
bool_query | 複数のクエリを組み合わせる | {"must": [...], "should": [...], "must_not": [...]} |
match_all_query | すべてのレコードに一致 | {} |
Shopper Custom Objects API(SCAPI)
ストアフロントから読み取り専用でアクセスするには、Shopper Custom Objects API を使用します。この API には特定の OAuth スコープが必要です。
カスタムオブジェクトの取得(Shopper)
GET https://{shortCode}.api.commercecloud.salesforce.com/custom-object/shopper-custom-objects/v1/organizations/{organizationId}/custom-objects/{objectType}/{key}?siteId={siteId}
Authorization: Bearer {shopper_token}
必須スコープ
Shopper Custom Objects API を使用するには、SLAS クライアントで次のスコープを設定します。
sfcc.shopper-custom-objects- すべてのカスタムオブジェクトタイプへのグローバルな読み取りアクセスsfcc.shopper-custom-objects.{objectType}- タイプ固有の読み取りアクセス
注: SLAS クライアントに設定できるカスタムオブジェクトのスコープは最大 20 個です。
また、Business Manager でカスタムオブジェクトタイプの Shopper アクセスを有効にする必要があります。
検索可能なシステムフィールド
すべてのカスタムオブジェクトには、OCAPI 検索クエリで使用できる次のシステムフィールドがあります。
creation_date- オブジェクトの作成日時(Date)last_modified- オブジェクトの最終更新日時(Date)key_value_string- 文字列のキー値key_value_integer- 整数のキー値site_id- サイト識別子(サイトスコープのオブジェクト用)
ベストプラクティス
推奨事項
- 作成/更新/削除の操作ではトランザクションを使用する
- 使用後はクエリイテレーターを閉じる(
objects.close()) - 効率的に検索できるよう、意味のあるキー値を使用する
- 頻繁にクエリする属性にインデックスを設定する
- サイト固有のデータにはサイトスコープのオブジェクトを使用する
- 共有設定には組織スコープのオブジェクトを使用する
避けること
- 機密データを暗号化せずに保存する
- カスタムオブジェクトの種類を過剰に作成する
- 大量のトランザクションデータにカスタムオブジェクトを使用する
getCustomObject()が null を返す場合の処理を忘れる- クエリイテレーターを閉じずに放置する(リソースリークの原因になります)
一般的なパターン
設定ストア
var CustomObjectMgr = require('dw/object/CustomObjectMgr');
var Site = require('dw/system/Site');
function getConfig(key, defaultValue) {
var configKey = Site.current.ID + '_' + key;
var obj = CustomObjectMgr.getCustomObject('SiteConfig', configKey);
if (obj && obj.custom.value !== null) {
return JSON.parse(obj.custom.value);
}
return defaultValue;
}
function setConfig(key, value) {
var Transaction = require('dw/system/Transaction');
var configKey = Site.current.ID + '_' + key;
Transaction.wrap(function() {
var obj = CustomObjectMgr.getCustomObject('SiteConfig', configKey);
if (!obj) {
obj = CustomObjectMgr.createCustomObject('SiteConfig', configKey);
}
obj.custom.value = JSON.stringify(value);
});
}
処理キュー
var CustomObjectMgr = require('dw/object/CustomObjectMgr');
var Transaction = require('dw/system/Transaction');
// Add to queue
function enqueue(data) {
var key = 'job_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
Transaction.wrap(function() {
var obj = CustomObjectMgr.createCustomObject('JobQueue', key);
obj.custom.data = JSON.stringify(data);
obj.custom.status = 'pending';
});
}
// Process queue
function processQueue() {
var pending = CustomObjectMgr.queryCustomObjects(
'JobQueue',
'custom.status = {0}',
'creationDate asc',
'pending'
);
while (pending.hasNext()) {
var job = pending.next();
Transaction.wrap(function() {
job.custom.status = 'processing';
});
try {
var data = JSON.parse(job.custom.data);
processJob(data);
Transaction.wrap(function() {
CustomObjectMgr.remove(job);
});
} catch (e) {
Transaction.wrap(function() {
job.custom.status = 'failed';
job.custom.error = e.message;
});
}
}
pending.close();
}
詳細なリファレンス
- OCAPI 検索クエリ - 検索クエリの構文と例の全容