ファネルとトリガー
ファネルはグラフ。実行は行。待機は時間。
それがモデルのすべてであり、この製品が持つ難しい性質はすべてこの3文から生まれます。稼働中のファネルを安全に編集できるのはこのためです。リトライが二重送信にならないのもこのためです。火曜日に購読解除した人が木曜日に何も受け取らないのもこのためです。
実行時に実際に起きること
ファネルを公開すると不変のバージョンが書き込まれます。誰かが入ると行が1つ現れます。このコンタクトのための1回の実行で、そのバージョンに固定され、現在のノードと起床時刻、そして固有のコンテキストを保持します。
ワーカーは起床時刻を過ぎた実行をリースします。SKIP LOCKED で取得するため、2つのワーカーが同じ実行を取ることはありません。待機または終端に達するまでノードを実行し、次の起床時刻を書き込んでから手放します。
ノードは実行・コンタクト・ノードの純粋な関数であり、その副作用は実行自体の進行と同じトランザクションでコミットされます。この1つの性質こそがリトライを安全にするものです。「送信」と「進行」の間の0.5秒でワーカーが kill されても、両方かどちらも残らないかのどちらかで、片方だけが残ることはありません。
また、時刻をデータベースではなくアプリが供給するため、今書き込まれた行は今すぐ期日になります。データベースの時計をデフォルトとするスケジュール列は、書き込まれた瞬間にはまだ期日ではなく、それを作ったまさにそのティックを逃します。メッセージが1時間遅れるまで何もないように見えるバグです。
- 1リース
wake_at <= now()、FOR UPDATE SKIP LOCKED。リースのないキューはデフォルトで二重送信します。 - 2実行待機または終端に達するまでノードを順に実行します。それぞれがステップを書き込みます。何を決定し、何を出力したか。
- 3コミット副作用と進行を1つのトランザクションで。これがすべての仕掛けです。
- 4スリープ次の
wake_atを書き込みます。下流の行はまだ存在せず、存在する必要もありません。
コンタクト・バージョンごとに1実行
14のトリガー
実行を開始できるもの
その一部はあなたが行うことです。ほとんどは顧客が行う、あるいは行わないことです。そして行動の欠如は、行動そのものと同じくらい良いトリガーになります。
到着したとき
form_submit、list_join、contact_created、tag_added、segment_enter。セグメントはライブの述語なので、「セグメントに入る」は表現できるすべての「〜になった」をカバーします。3回の注文、90日間の沈黙、しきい値を超える支出など。
何かをしたとき
サイトスニペットからの page_visit、message_opened、link_clicked、booking_made、payment_made。メッセージが開かれること自体がコンタクト上のイベントなので、1つのファネルが自分の送った最後のものへの反応を待つことができます。
時刻、またはあなた
オフセット付きの date_field。誕生日、更新日、「1年経過」、7日前、3日後など。繰り返しには schedule。自分の判断で送るお知らせには manual。
あなたのアプリケーション
api_event は、自分のコードから自分のトークンで投稿するカスタムイベントです。製品が知っていることはすべてトリガーになります。有効化、同僚の招待、上限への到達、キャンセル、エクスポート。これがメーリングツールを製品の一部に変えるものです。
再入場、一度だけ決める
ファネルは再入可能かそうでないかのどちらかであり、データベースがそれを強制します。特に指定しない限り、コンタクト・ファネルごとに1実行です。同じ秒に同じトリガーが2回発火しても、誤って2つの実行が生まれることはありません。
入場条件
トリガーが発火すると、入場仕様がこの特定のコンタクトが対象かどうかを判断します。扉の前にあるセグメント述語です。最初のステップに条件ノードを置くより安価で、グラフを「誰が入れるか」ではなく「何が起きるか」について保てます。

開始できるものは14。次に起きることは16。
16のアクションと7のフローノード
ファネルにできること、そしてその判断方法
何かを送る
send_email、send_sms、send_push、send_letter。4つのチャネル、1つのグラフ。さらに、伝えるべき相手があなたの社員である場合は notify_team。
コンタクトを変更する
add_tag、remove_tag、add_to_list、remove_from_list、set_field。進みながら印を付けておくことが、次のファネルのセグメントをシンプルにします。
外へ手を伸ばす
任意の宛先への http_request、自分の接続アカウントに対する create_payment、予約リソースに対する book_slot。支払い者はあなたのままで、誰も弊社の顧客にはなりません。
ファネル間を移動する
enter_funnel と exit_funnel。ウェルカムシーケンスを1つ作り、4つの場所から呼び出します。3月には乖離し始める4つのコピーを維持する代わりに。
送信時に生成する
ai_generate はコンタクトごとに差し込み変数を埋めます。クォータに対して計測され、クリエイティブとコンタクト属性のハッシュでキャッシュされます。そうでなければ、毎回の送信で受信者ごとに支払うことになります。
待機、分岐、スプリット、結合
waitは期間、日時、曜日と時刻、またはオフセット付きの日付フィールドを受け取ります。conditionは「はい」と「いいえ」を持つセグメント述語です。splitは重み付きのA/B/nテストです。joinは分岐を再びまとめます。
goal — 最も重要なノード
ゴールに到達した人の実行はそこで終了します。予約した、購入した、返信した——その人についてはシーケンスの残りがキャンセルされます。戻ってきた翌日に「お会いできて寂しいです」メールが届くことはなく、それを防ぐのがこのノードです。
throttleとquiet_hours
スロットルは送信の集中を調整し、レート上限の低いメールボックスが停止に追い込まれないようにします。クワイエットアワーはメッセージを常識的な時間まで保留します——メッセージ層で適用され、グラフの各分岐にコピーされることはありません。
実行前にチェックされる
バリデータは、あなたに対してもAIに対しても同じことを拒否します
グラフは公開前にチェックされ、そのチェックは助言ではありません。ファネルを人が描いたかモデルが生成したかに関係なく、同じコードパスが使われます。生成されたファネルが信頼できる唯一の理由がこれです。
エントリはちょうど1つ
エントリノードが2つあると、リストの間違った半分に間違ったシーケンスが送られるまで、誰もその曖昧さに気づきません。
すべてのノードが到達可能
孤立した分岐は、ミスか、送信されると思っているのに実際には送られていないメッセージのどちらかです。どちらも知らされる価値があります。
ループには待機が必須
待機のないループは、送信を挟んだ無限ループです。このルールがあるからこそ、ファネルはインシデントにならずに済みます。
すべての送信にクリエイティブが存在
クリエイティブと件名のないsend_emailノードは公開できません。件名は正しいのに本文が空のメッセージは現実に起こる障害であり、ここで拒否されます。
すべての変数が既知
差し込み変数は公開時に検証されます。{{frist_name}}のようなタイプミスは編集中に気づけるものであり、4万件の受信箱に「こんにちは、」と届くものではありません。
次にシミュレーション
実際のコンタクトをグラフ全体でドライランし、通った経路と、送信されるはずのすべてのメッセージとその日付を読み返します。外部には何も出ていきません。
厄介なケース
素朴なエンジンを壊す7つの事柄
これらはすべて、決定論的なクロックを使ったテストになっています。どれも、現実に触れるまで完璧に正しく見える実装を壊すものだからです。
- 1自分自身にループするファネル正当で、よくある、問題のないパターンです——ただしループに待機が含まれていることが条件で、バリデータがそれを強制します。
- 2配信中に誰かが購読解除する抑制チェックはエンキュー時ではなく送信時に行われます。エンキュー時にチェックすると、待機中に離脱した人にもメールが送られてしまいます。
- 31万人がいる最中にファネルを編集する既存の人は、入った時点のバージョンを最後まで歩き続けます。新規の人は新しいバージョンを歩きます。
- 4同じトリガーが1秒に2回発火する実行は1回だけです。一意性は、チェック後に挿入するのではなく、インデックスとして実現されているからです。
- 5実行中にコンタクトが削除される実行は終了します。誰かに宛てたシーケンスが残るような削除は、削除ではありません。
- 6待機がサマータイムの切り替えをまたぐ「3日後の午前9時」は、時計の切り替えの前後どちらでも午前9時を意味します。
- 7送信と進行の間でワーカーが強制終了する送信効果と進行は1つのトランザクションです。両方起きたか、どちらも起きていないかのどちらかです。
決定論的クロック各テストはもっともらしい実装を壊します
キャンペーンはもう半分
ファネルは反応するものです。キャンペーンは一回性の配信です。オーディエンス、スケジュール、スロットル、送信。これは異なる種類の存在であり、ノードが1つのファネルのふりをするのではなく、意図的に分けて管理されます。
2つのルールが安全性を支えています。オーディエンスは一度だけ確定され、2回目の実行を拒否します。再解決すると送信開始後に参加した人全員が静かに追加され、重複排除インデックスが自ら作った重複を防ぐことでそれを隠してしまうからです。また、カウンターは配信イベントから再計算され、その場で加算されることはありません。そのため、再試行されたWebhookがレポートを水増しすることはありません。
どちらを使うか: 本人が何かをしたことがきっかけなら、それはファネルです。あなたが火曜日に決めたことがきっかけなら、それはキャンペーンです。後者を前者の形に無理に押し込めることで、マーケティングオートメーションは驚くほど多くの失敗を起こします。