見出し画像

【第450回】 Marketing Cloud Next : API を使ってフローから離脱させる方法

Marketing Cloud Next Growth & Advanced Edition では、セグメントトリガーフロー、イベントトリガーフロー、オンデマンドフロー など、さまざまなフローを使ってリアルタイム施策や自動化を実現できます。

しかし運用していると、こんなケースはありませんか?

  • ✅ 購入完了したのにリマインドメールが送られ続ける

  • ✅ すでに対応済みなのにフォローアップが止まらない

  • ✅ 外部システム側で処理完了したためフローを終了したい

このような 「もうフローに残す必要がない個人」 を動的に離脱させるための仕組みが、Spring '26 の新機能リリースで登場した Exit Individuals from a Flow Action(REST API)です。

この API を使うと、
実行中のフローから特定の個人(Individual)を即座に退出させる
ことができます。


ユースケース例

🛒 購入リマインドフロー

  1. カート放棄

  2. 1 日後リマインド

  3. 3 日後再通知

  4. 7 日後クーポン送付

途中で、外部 EC サイトで購入完了

このままだと
❌ 「まだ購入していませんか?」メールが送られる
⇒ そこで、Exit Individuals API でフローから離脱させる


対応フロータイプ

このアクションは、以下のフローで利用可能です。

  • セグメントトリガーフロー

  • イベントトリガーフロー

  • オンデマンドフロー


API仕様

この API は「API version 66.0」(Spring '26)以降で動きます。

--- メソッド 
POST 

--- エンドポイント
https://[私のドメイン名].my.salesforce.com/services/data/v66.0/actions/custom/exitIndividualsFromFlow/flow_API_name

--- ヘッダー 
Content-Type:application/json 
Authorization:Bearer [アクセストークン] 

--- ボディ
{
  "inputs": [
    {
      "individualId": "003R000000ExAmPlE",
      "flowVersionId": "301R000000AbCdEfG",
      "description": "Customer completed purchase via external portal."
    }
  ]
}
  • フローバージョン(flowVersionId)は任意です。指定がない場合は、すべてのバージョンから退出します。

  • 説明(description)も任意です。


実装イメージ(活用パターン)

パターン①:外部EC完了トリガー

EC → Webhook → Lambda → REST API → Exit Flow

パターン②:CRM更新トリガー

Opportunity Closed Won → Apex → Callout → Exit Flow

パターン③:サポート完了

Case Closed → Event-Triggered Flow → Exit Flow


取引先責任者のページに強制退出画面を作る

最後に、画面フローを作成して連絡先の退出画面を作成してみます。
具体的には、以下のような流れになります。

Contact レコード
↓(クイックアクション)
Screen Flow

Contact → IndividualId 取得

Flow API 名を手入力

Apex(Invocable)

POST /actions/custom/exitIndividualsFromFlow/{flowApiName}

設定手順

1. Named Credential の作成

この作成方法については、以下の 2 つの記事をご確認ください。

  • 以下の記事で「コンシューマー鍵」と「コンシューマーの秘密」を取得するところまで進めてください。

  • 上で取得した「コンシューマー鍵」と「コンシューマーの秘密」を使って、Named Credential(指定ログイン情報)を作成してください。

  • 「データグラフのスケジュール実行」セクションの 手順 1 ~ 24 を実行してください。下の Apex をそのまま利用する場合は、Named Credential の Name(API 名)を「SelfOrg」と命名してください。


2. Apex クラス を登録

以下を登録してください。
設定で登録されている Named Credential(指定ログイン情報)の Name(API 名)が「SelfOrg」であるか、再度確認してください。

public with sharing class ExitIndividualsFromFlowAction {

    public class Request {
        @InvocableVariable(required=true)
        public String individualId;

        @InvocableVariable(required=true)
        public String flowApiName;
    }

    public class Result {
        @InvocableVariable public Boolean success;
        @InvocableVariable public Integer statusCode;
        @InvocableVariable public String message;
        @InvocableVariable public String responseBody;
    }

    @InvocableMethod(label='Exit Individual From Flow')
    public static List<Result> run(List<Request> requests) {

        List<Result> results = new List<Result>();

        for (Request req : requests) {
            Result r = new Result();

            try {
                String apiName = (req.flowApiName == null) ? '' : req.flowApiName.trim();

                HttpRequest httpReq = new HttpRequest();
                httpReq.setMethod('POST');
                httpReq.setEndpoint(
                    'callout:SelfOrg/services/data/v66.0/actions/custom/exitIndividualsFromFlow/' +
                    EncodingUtil.urlEncode(apiName, 'UTF-8')
                );
                httpReq.setHeader('Content-Type', 'application/json');
                httpReq.setTimeout(120000);

                Map<String,Object> body = new Map<String,Object>{
                    'inputs' => new List<Object>{
                        new Map<String,Object>{ 'individualId' => req.individualId }
                    }
                };
                httpReq.setBody(JSON.serialize(body));

                HttpResponse res = new Http().send(httpReq);

                r.statusCode = res.getStatusCode();
                r.responseBody = res.getBody();
                r.success = (r.statusCode >= 200 && r.statusCode < 300);

                if (r.success) {
                    r.message = 'Successfully exited';
                } else {
                    r.message = r.responseBody;

                    if (r.statusCode == 400 && !String.isBlank(r.responseBody)) {
                        String errCode = extractFirstErrorStatusCode(r.responseBody);

                        if (errCode == 'INDIVIDUAL_NOT_IN_FLOW') {
                            r.message = 'This individual is not currently in the flow (no exit required)';
                        }
                    }
                }

            } catch (Exception e) {
                r.success = false;
                r.message = 'Exception: ' + e.getMessage();
            }

            results.add(r);
        }

        return results;
    }

    private static String extractFirstErrorStatusCode(String jsonText) {
        try {
            Object root = JSON.deserializeUntyped(jsonText);

            if (!(root instanceof List<Object>)) return null;
            List<Object> rootList = (List<Object>)root;
            if (rootList.isEmpty()) return null;

            Object first = rootList[0];
            if (!(first instanceof Map<String,Object>)) return null;
            Map<String,Object> firstMap = (Map<String,Object>)first;

            Object errorsObj = firstMap.get('errors');
            if (!(errorsObj instanceof List<Object>)) return null;
            List<Object> errors = (List<Object>)errorsObj;
            if (errors.isEmpty()) return null;

            Object e0 = errors[0];
            if (!(e0 instanceof Map<String,Object>)) return null;
            Map<String,Object> e0Map = (Map<String,Object>)e0;

            Object statusCodeObj = e0Map.get('statusCode');
            return (statusCodeObj == null) ? null : String.valueOf(statusCodeObj);

        } catch (Exception ignore) {
            return null;
        }
    }
}

3. 画面フローの作成

1. 新規で「画面フロー」を作成します。

2. 今回、以下の 5 つの「変数」を作ります。

(1)recordId
API Name:recordId
Data Type:Text
Available for input:ON

(2)varIndividualId
・API Name:
varIndividualId
Data Type:Text

(3)varMessage
・API Name:
varMessage
・Data Type:Text

(4)varStatusCode
API Name:varStatusCode
・Data Type:Number
・Decimal Places:0

(5)varSuccess
・API Name:
varSuccess
・Data Type:Boolean

3. 「レコードを取得」要素を設定します。

  • 表示名:Get Contact

  • API 名:Get_Contact

  • Object:Contact

  • Condition Requirements:All Conditions Are Met (AND)

  • Field:Contact Id

  • Operator:Equals

  • Value:{!recordId}(変数)

  • How Many Records to Store:Only the first record(デフォルト)

  • How to Store Record Data:Automatically store all fields(デフォルト)

4. 「割り当て」を設定します。

  • 表示名:Set IndividualId

  • API 名:Set_IndividualId

  • Set Variable Values:varIndividualId(変数) = {!Get_Contact.Id}

5. 「画面」要素を配置して、以下を入力します。

  • 表示名:Input Flow API Name

  • API 名:Input_Flow_API_Name

6. 「テキスト」コンポーネントをドラッグアンドドロップして、以下を入力して、要素を保存します。

  • 表示名:Flow API Name

  • API 名:varFlowApiName(← 入力されたフローの API 名が、この変数に格納されます。)

  • 必須:ON


4. Apex アクション

1. Action を配置して、作成した ApexExitIndividualsFromFlowAction)を選択します。

2. 表示名と API 名を決め、以下の 2 つをマッピングします。

  • 表示名:Exit Individual From Flow

  • API 名:Exit_Individual_From_Flow

Set Input Values:

  • flowApiName = {!varFlowApiName}(画面上からの変数)

  • individualId = {!varIndividualId}(変数)

一旦、ここまでで実装は成立していますが、以下に結果を表示するための画面を作成します。


5. 出力応答の割り当て

最初に作成した残り 3 つの変数に、Apex からの出力応答 を割り当てます。
割り当て」要素を配置してください。

  • 表示名:Set Result

  • API 名:Set_Result

Set Variable Values:

  • varSuccess = {!Exit_Individual_From_Flow.success}

  • varStatusCode = {!Exit_Individual_From_Flow.statusCode}

  • ‎varMessage = {!Exit_Individual_From_Flow.message}


6. 成功と失敗の分岐の作成

「決定」要素を配置して

  • 表示名:Check Success

  • API 名:Check_Success

  • 左のパス名:Success

  • 右のパス名:Failure

  • 左の条件:{!Exit_Individual_From_Flow.success} = True


7. 成功画面の作成

左のパスに「画面」要素を配置して、設定画面を表示したら、表示名と API 名を設定します。

  • 表示名:Success Exit Completed

  • API 名:Success_Exit_Completed

続いて、Display Text を配置して、以下を入力して「保存」します。

  • API 名:Success_Display

  • テキスト本文:
    Exit successful

    • Status: {!varStatusCode}


8. 失敗画面の作成

右のパスにも「画面」要素を配置して、以下を入力します。

  • 表示名:Error Exit Flow

  • API 名:Error_Exit_Flow

こちらも、Display Text を配置して、以下を入力して「保存」します。

  • API 名:Failure_Display

  • テキスト本文:
    Exit failed

    • Status: {!varStatusCode}

    • Details: {!varMessage}


9. フローの保存と有効化

フローを保存して有効化してください。

  • フロー名:Exit Individual From Flow

  • API 名:Exit_Individual_From_Flow


10. 取引先責任者のアクションに設定

1. 設定 > オブジェクトマネージャーから「取引先責任者」の「Buttons, Links, and Actions」を選択して「新しいアクション」をクリックします。

2. 以下で入力します。

  • アクションタイプ:Flow

  • フロー:Exit Individual From Flow

  • 表示名:Exit Flow

  • API 名:Exit_Flow

3. 新しいアクションの保存後、取引先責任者の「ページレイアウト」に追加します。


11. 動作確認

1. フロー内に存在している「取引先責任者」のレコードを開いて、Exit Flow クイックアクションをクリックします。

2. 「Exit Flow」の画面が開きますので、Flow API 名(❌ 表示名)を入力して先に進みます。(例:オンデマンドフロー の Order_Confirmation_Flow)

3. 「退出されました」と表示されます。

4. その後のフローでは、先に進まなくなります。成功です。

5. フロー内に存在していない「取引先責任者」レコードの場合は、以下の通り「退出されませんでした」が表示されます。


いかがでしたでしょうか。

Marketing Cloud Next では、「開始する」だけでなく 「途中で止める」制御 も非常に重要です。

Exit Individuals API は、Flow をよりインテリジェントに運用するための必須テクニック と言えます。

リアルタイム施策や外部連携をしている方は、ぜひ活用してみてください。

今回は以上です。


次の記事はこちら

前回の記事はこちら

私の note のトップページはこちら