Skip to content

Thirteen node types can be added to a campaign from the canvas palette: two triggers, four logic nodes, one message node, four comment actions, and two contact actions. Each type carries its own configuration keys and a fixed number of outputs, and those two things decide what an execution does at that node and where it goes next. Node types that exist in the runtime but have no palette tile are listed in the campaign graph schema.

Node typeCategoryOutputsRequired configWhat it does
trigger_commenttrigger1post_id when post_scope is specificStarts the campaign when someone comments on the page
trigger_dmtrigger1noneStarts the campaign when someone sends the page a direct message
conditionlogic2 (Match / No Match)match_type, plus text or keyword_list_id for the match types that read themMatches the message text and picks a branch, or parks the execution until a reply arrives
send_dmmessage1, plus one per postback buttonmessage_type and the keys that type readsSends a direct message: text, image, card, or text with buttons
reply_commentcomments1textReplies publicly under the comment that started the execution
send_commentcomments1text, post_idPosts a new comment on a named post
hide_commentcomments1noneHides the comment that started the execution
delete_commentcomments1noneDeletes the comment that started the execution
delaylogic1noneHolds the execution and continues it later
random_splitlogicone per armpathsSends each execution down one arm, chosen at random
add_tagcontact1tag_idsAdds tags to the contact
remove_tagcontact1tag_idsRemoves tags from the contact
stoplogic0noneEnds the execution
  • Category: trigger
  • Outputs: 1, and it connects only to a condition
  • Required config: post_id when post_scope is specific
KeyTypeWhat it sets
post_scopestringall or specific. An absent key counts as all.
post_idstringThe post a specific scope listens on. The settings panel offers the connected page’s posts.
unique_per_userbooleanTurns on the once-per-person restriction described below.

Starts an execution when a comment arrives on the connected page. With post_scope set to specific, only comments on the post named by post_id start the campaign; every other comment on the page is ignored.

unique_per_user restricts the campaign to a single execution per person.

{
"post_scope": "specific",
"post_id": "104857392017465_998234511",
"unique_per_user": true
}
  • Category: trigger
  • Outputs: 1, and it connects only to a condition
  • Required config: none
KeyTypeWhat it sets
unique_per_userbooleanTurns on the once-per-person restriction described below.

Starts an execution when someone sends the connected page a direct message. There is no post_scope key, because a direct message is not attached to a post. Comment actions are unavailable in a campaign whose trigger is trigger_dm.

unique_per_user is the same setting as on trigger_comment, and restricts the campaign to a single execution per person.

{
"unique_per_user": false
}
  • Category: logic
  • Outputs: 2 — output 0 is Match, output 1 is No Match
  • Required config: match_type, plus text or keyword_list_id for the match types that read them
KeyTypeWhat it sets
match_typestringany, contains, exact, or keyword_list. Decides the comparison and which keys below are read.
textstringThe text compared by contains and exact.
keyword_list_idnumberThe saved keyword list compared by keyword_list.
reverse_keywordsbooleanInverts the outcome of a keyword_list comparison.
wait_for_replybooleanParks the execution at this node instead of evaluating the message that reached it.
filter_imagesbooleanMedia filter on the incoming message.
filter_gifsbooleanMedia filter on the incoming message.
filter_linksbooleanMedia filter on the incoming message.

Evaluates the message and sends the execution down the Match or the No Match output. Keyword matching rules covers what each match type compares and which output it produces.

wait_for_reply parks the execution at this node instead of evaluating straight away, and it stays there until the person replies. Execution states covers how long a parked execution survives and what wakes it up.

The media filters are separate settings on the same node and take no part in the keyword comparison. Match comments with keyword lists covers building the list that keyword_list_id points at.

{
"match_type": "keyword_list",
"keyword_list_id": 41,
"reverse_keywords": false,
"wait_for_reply": true
}
  • Category: message
  • Outputs: 1, plus one extra output for every postback button
  • Required config: message_type and the keys that type reads
KeyTypeWhat it sets
message_typestringtext, image, card, or text_with_buttons. Decides which keys below are read.
textstringThe message text.
image_urlstringThe image for an image message, and the picture on a card.
titlestringThe heading on a card.
subtitlestringThe second line on a card.
buttonsarrayButtons on a card or a button message. Each entry carries an id, a type of web_url or postback, a title, and a url for a web_url button.
buttons_textstringOne button label per line, for a text_with_buttons message. Each line becomes a postback button whose payload is the label.

Sends one direct message to the person the execution is running for. message_type selects which keys are read: text for a plain message, image_url for an image, title, subtitle, and image_url for a card, and buttons_text for text with buttons.

Sender-name variables in text, title, and subtitle are substituted before the message is sent.

A postback button adds its own output to the node, so an execution can continue down a different branch depending on which button the person presses.

A node with nothing configured sends nothing, and the execution carries on to the next node.

{
"message_type": "text_with_buttons",
"text": "Thanks for commenting. Which size do you want?",
"buttons_text": "Small\nMedium\nLarge"
}
  • Category: comments
  • Outputs: 1
  • Required config: text
KeyTypeWhat it sets
textstringThe reply posted under the triggering comment.

Posts a public reply under the comment that started the execution. Sender-name variables in text are substituted before the reply is posted.

The node is unavailable in a campaign triggered by trigger_dm, and the canvas refuses to place it downstream of a delete_comment.

{
"text": "Sent you the price list in a DM."
}
  • Category: comments
  • Outputs: 1
  • Required config: text, post_id
KeyTypeWhat it sets
textstringThe comment posted on the named post.
post_idstringThe post the comment is published on.

Posts a new top-level comment on the post named by post_id. There is no fallback to the post the execution came from: without post_id the node does nothing and the execution carries on to the next node.

The node is unavailable in a campaign triggered by trigger_dm.

{
"text": "Restocked today — sizes S to XL are back.",
"post_id": "104857392017465_998234511"
}
  • Category: comments
  • Outputs: 1
  • Required config: none
KeyTypeWhat it sets
also_block_userbooleanBlocks the comment’s author in the same step. Facebook only.

Hides the comment that started the execution.

also_block_user blocks the comment’s author in the same step and works on Facebook only — the option is disabled on an Instagram campaign.

  • Category: comments
  • Outputs: 1
  • Required config: none
KeyTypeWhat it sets
also_block_userbooleanBlocks the comment’s author in the same step. Facebook only.

Deletes the comment that started the execution. also_block_user works on Facebook only, the same as on hide_comment.

Downstream of this node the canvas refuses reply_comment and hide_comment, because the comment those nodes would act on no longer exists.

  • Category: logic
  • Outputs: 1
  • Required config: none
KeyTypeWhat it sets
delay_secondsnumberHow long the execution waits, from 1 to 31536000 seconds.
only_if_no_replybooleanCancels the rest of the execution if the person replied while the wait was running.

Holds the execution and schedules it to continue later. delay_seconds is clamped to between 1 and 31536000 seconds (365 days), and a value outside that range is clipped without an error. A node with no value configured waits 60 seconds.

only_if_no_reply is checked when the wait elapses: if the person replied at any point during it, the execution completes at the delay instead of continuing down the branch.

{
"delay_seconds": 3600,
"only_if_no_reply": true
}
  • Category: logic
  • Outputs: one per entry in paths
  • Required config: paths
KeyTypeWhat it sets
pathsarrayOne { "percent": number } entry per output. Each percentage is 0 to 100 and the total cannot exceed 100.

Splits traffic between branches: each execution follows one arm, chosen at random. Set one percentage per arm in the canvas; each is 0 to 100 and the total cannot exceed 100.

Treat the percentages as the split you are asking for rather than a guaranteed ratio, and confirm the actual distribution in the execution history before relying on it for anything that matters.

With no percentages configured the node falls back to two equal arms.

The chosen arm decides which output the execution follows. If that output has no connection, the execution completes at this node.

{
"paths": [{ "percent": 70 }, { "percent": 30 }]
}
  • Category: contact
  • Outputs: 1
  • Required config: tag_ids
KeyTypeWhat it sets
tag_idsarrayThe numeric identifiers of the tags to add.

Adds the named tags to the contact the execution is running for, alongside the tags that contact already carries.

When the execution has no contact behind it, the node changes nothing and the execution carries on to the next node.

{
"tag_ids": [12, 19]
}
  • Category: contact
  • Outputs: 1
  • Required config: tag_ids
KeyTypeWhat it sets
tag_idsarrayThe numeric identifiers of the tags to remove.

Removes the named tags from the contact the execution is running for, and leaves that contact’s other tags in place. Contact fields lists the rest of the contact record.

When the execution has no contact behind it, the node changes nothing and the execution carries on to the next node.

{
"tag_ids": [19]
}
  • Category: logic
  • Outputs: 0
  • Required config: none

Ends the execution as soon as it is reached, and records that the flow was stopped. The node has no output, so nothing can be connected after it.

Eight further node types exist in the runtime, carry no palette tile and no settings panel, and never appear in a campaign built on the canvas. Campaign graph schema names them and says what an execution does at each. Treat them as runtime-only rather than as features.

  • Outputs are numbered from 0. A condition uses 0 for Match and 1 for No Match, a random_split uses one number per arm in configured order, and every other node continues from 0.
  • An execution follows the connection leaving the output the node selected. When that output carries no connection, the execution completes at that node.
  • A node whose action raises an error records the error against the execution and does not advance, so the execution goes no further than that node.
  • An execution that arrives at a node it has already visited ends with a cycle error naming that node. Every node runs at most once per execution.
  • A node type the runtime does not recognise is passed over with a warning, and the execution continues from output 0.
  • A comment action that has no comment to act on does nothing, and the execution continues.
  • Palette tiles are filtered by the campaign’s platform, so the palette on an Instagram campaign can offer fewer node types than the palette on a Facebook one.
  • Which node types may follow which is enforced while a connection is dragged, not when the campaign is saved. Campaign graph schema lists those constraints.
  • In a test execution, add_tag and remove_tag record what they would have done and leave the contact untouched, and a delay ends the test run instead of scheduling a resume.