Markup Interaction Node

This node allows for mark-up language to be entered that expects input , specifically to add features into your flow which can be displayed in messenger.

When users interact with the timeline elements set up in these nodes, input events are set to the bot in msg.payload.markupInteract based on how they interacted.

When using this node if a user types a message instead of interacting with the available options the node will always output on the bottom port. The message the user typed will be available to the next node at msg.payload.user.message

Simple Outputs

The “Simple Outputs” option is used to disable the automatic generation of output ports based on the markup. When “Simple Outputs” is in use there will always be 2 outputs, the top port will be used on a successful interaction, the bottom port is for when the user types a message or an error occurs.

“Simple Outputs” is useful in situations where the number of output ports is unknown, for example generating a menu dynamically using VTL. The output from a node using “Simple Outputs” will be available at msg.payload.markupInteraction.result and will be in the form {“title”:“Option”,“id”:“1”}

Simple Outputs is currently supported by:

Lists

Please note, the following properties are required for this node to work

When using the fileUpload option with this node the result of the fileUpload will come from the top output port with 1 and many uploads. The result of the upload will be available in the next node at msg.markupInteraction.fileUpload

See “Switch” node further on in this document to understand how the bot can carry out different flows, based on what users select from these mark-up features.

Timeline Elements

Broadcast message

When a broadcast message is used in the markupInteraction node with the property interactionType=event, Outputs will be generated using the Options in the broadcast, or closes the broadcast.

For the following markup

<TimelineMessage>
  <BroadcastMsg
     title="Warning"
     body="This fund will be discontinued next month. We'll be moving you to another fund."
     style="warning"
     interactionType="event">
       <Option title="First Option" id="one" />
       <Option title="Second Option" id="two" />
  </BroadcastMsg>
</TimelineMessage>

When user closes the BroadcastMsg

{
  "interaction": {
    "action": "broadcastInteraction",
    "timestamp": 1598536867281,
    "value": {
      "id": "broadcastMessageClosed",
      "title": "broadcastMessageClosed"
    }
  }
}

When a user selects an option

{
  "interaction": {
    "action": "broadcastInteraction",
    "timestamp": 1598536867281,
    "value": {
      "id": "two",
      "title": "Second Option"
    }
  }
},
{
  "interaction": {
    "action": "broadcastInteraction",
    "timestamp": 1598536867281,
    "value": {
      "id": "broadcastMessageClosed",
      "title": "broadcastMessageClosed"
    }
  }
}

Button Prompts

<TimelineMessage>
<ButtonPromptContainer interactionType="event">
    <ButtonPrompt label="Option One" id="0"/>
    <ButtonPrompt label="Option Two" id="1"/>
    <ButtonPrompt label="Option Three" id="2"/>
</ButtonPromptContainer>
</TimelineMessage>
{
  "interaction": {
    "action": "buttonInteraction",
    "timestamp": 1598536867281,
    "value": {
      "id": "1",
      "title": "Option Two"
    }
  }
}

DetailView

Expect the following interactions to go out of the following ports

  • Middle Port: DetailPage Post Messages and Close events
  • Bottom port: Errors, and Utterances
<TimelineMessage>
  <DetailView
    title="ServisBOT"
    description="Check out our bots"
    url="https://servisbot.com"
    interactionType="event"
  />
</TimelineMessage>

It is possible for the page within the detail view to trigger markupInteractions, close the detailview, or both by sending a postMessage to the parent page.

Parent postMessage

Complete without Close
window.parent.parent.postMessage({
  type: "completeServisBotTask",
}, "https://mydomain.com");

Will send this markupInteraction:

{
  "contents": {
    "source": {
      "eventType": "TimelineMessage",
      "timestamp": 1607336789997,
      "id": "ntIo0MW2ed",
      "conversationId": "e7ceafc1-6726-40bd-8d2f-e2c0d5df8f04"
    },
    "interaction": {
      "action": "externalInteraction",
      "value": {
        "id": "ntIo0MW2ed",
        "option": "DETAIL_VIEW_CLOSED"
      },
      "timestamp": 1607352755214
    }
  },
  "contentType": "markupInteraction",
  "correlationId": "MLPKW1wEg",
  "timestamp": 1607352755215,
  "type": "TimelineMessage",
  "version": "v2"
}
Complete with Close
window.parent.parent.postMessage({
  type: "completeServisBotTask",
  closeOnComplete: true,
}, "https://mydomain.com");

Will send this markupInteraction:

{
  "contents": {
    "source": {
      "eventType": "TimelineMessage",
      "timestamp": 1607336789997,
      "id": "ntIo0MW2ed",
      "conversationId": "e7ceafc1-6726-40bd-8d2f-e2c0d5df8f04"
    },
    "interaction": {
      "action": "externalInteraction",
      "value": {
        "id": "ntIo0MW2ed",
        "option": "DETAIL_VIEW_CLOSED"
      },
      "timestamp": 1607352755214
    }
  },
  "contentType": "markupInteraction",
  "correlationId": "MLPKW1wEg",
  "timestamp": 1607352755215,
  "type": "TimelineMessage",
  "version": "v2"
}

Complete with Value

window.parent.parent.postMessage({
  type: "completeServisBotTask",
  closeOnComplete: true,
  message: { value: 2 },
}, "https://mydomain.com");

Will send this markupInteraction:

{
  "contents": {
    "source": {
      "eventType": "TimelineMessage",
      "timestamp": 1607353502910,
      "id": "LGBcEdB8ky",
      "conversationId": "d0dee183-3691-4b17-9d91-cffe10bb3c46"
    },
    "interaction": {
      "action": "externalInteraction",
      "value": {
        "id": "LGBcEdB8ky",
        "option": 2
      },
      "timestamp": 1607354765468
    }
  },
  "contentType": "markupInteraction",
  "correlationId": "ZBLfQvmdK",
  "timestamp": 1607354765468,
  "type": "TimelineMessage",
  "version": "v2"
}

Complete with String Value

window.parent.parent.postMessage({
  type: "completeServisBotTask",
  closeOnComplete: true,
  message: { value: JSON.stringify({type:'formSubmit', form:'window.form'}) },
}, "https://mydomain.com");

Will send this markupInteraction:

{
  "contents": {
    "source": {
      "eventType": "TimelineMessage",
      "timestamp": 1607354906404,
      "id": "sVzm_NR6v0",
      "conversationId": "86b05301-2e20-4928-84d1-15f92946bed1"
    },
    "interaction": {
      "action": "externalInteraction",
      "value": {
        "id": "sVzm_NR6v0",
        "option": "{\"type\":\"formSubmit\",\"form\":\"window.form\"}"
      },
      "timestamp": 1607354910944
    }
  },
  "contentType": "markupInteraction",
  "correlationId": "G1chGSYJD",
  "timestamp": 1607354910945,
  "type": "TimelineMessage",
  "version": "v2"
}

DetailViewLegacy (Deprecated)

This timeline element and node is Deprecated and will be removed from the platform in Jan 2020.

Expect the following interactions to go out of the following ports

  • Top port: Deprecated, never used.
  • Middle Port: Deprecated, never used.
  • Bottom port: Errors, DetailPage Post messages, utterances and detail view close
<TimelineMessage>
  <DetailViewLegacy
    title="ServisBOT"
    description="Check out our bots"
    url="https://google.com"
    interactionType="event"
  />
</TimelineMessage>
{
  "interaction": {
    "action": "externalInteraction",
    "timestamp": 1598536867281,
    "value": {
      "id": "UuYUOjT_pD",
      "title": "Detail View Closed"
    }
  }
}
<TimelineMessage>
  <Dropdown value="3" title="Select an appropriate option" description="When would you like to set it?" confirmButtonText="Select" interactionType="event">
    <DropdownItem id="1" title="Option 1" />
    <DropdownItem id="2" title="Option 2" />
    <DropdownItem id="3" title="Option 3" />
  </Dropdown>
</TimelineMessage>
{
  "interaction": {
    "action": "dropdownInteraction",
    "timestamp": 1598536867281,
    "value": {
      "id": "2",
      "title": "Option 2"
    }
  }
}

FileUpload

FileUpload

<TimelineMessage>
    <FileUpload
    promptText="Could you post a picture of the other vehicle?"
    promptButtonText="Upload Picture"
    retryButtonText="Replace"
    confirmButtonText="Complete"
    confirmationText="All set!"
    interactionType="event">
        <UploadItem fileType="image/\*" name="vehicle"/>
    </FileUpload>
</TimelineMessage>

Single file upload

{
  "interaction": {
    "action": "fileUpload",
    "timestamp": 1598536867281,
    "value": ["s3urlforfile"]
  }
}

Multi-file upload

{
  "interaction": {
    "action": "fileUpload",
    "timestamp": 1598536867281,
    "value": ["s3urlforfirstfile", "s3urlforsecondfile"]
  }
}

List

<TimelineMessage>
    <List type="disc" selectable="true" preventRetries="true" interactionType="event" >
      <Item title="Item one" id="1"/>
      <Item title="Item two" id="2" />
      <Item title="Item three" id="3" />
    </List>
</TimelineMessage>
{
  "interaction": {
    "action": "listItemInteraction",
    "timestamp": 1598536867281,
    "value": {
      "id": "1",
      "title": "Item One"
    }
  }
}

SecureFileUpload V1

<TimelineMessage>
    <SecureFileUpload
    promptText="Could you post a picture of the other vehicle?"
    promptButtonText="Upload Picture"
    retryButtonText="Replace"
    confirmButtonText="Complete"
    confirmationText="All set!"
    interactionType="event">
        <UploadItem fileType="image/\*" name="vehicle"/>
    </SecureFileUpload>
</TimelineMessage>

Single file upload

{
  "interaction": {
    "action": "secureFileUpload",
    "timestamp": 1598536867281,
    "value": [{
      "docId": "first-doc-id",
      "name": "vehicle"
    }]
  }
}

Multi-file upload

{
  "interaction": {
    "action": "secureFileUpload",
    "timestamp": 1598536867281,
    "value": [{
      "docId": "first-doc-id",
      "name": "doc1"
    },
    {
      "docId": "second-doc-id",
      "name": "doc2"
    }]
  }
}

SecureFileUpload V1 Ports

  • Top Port: The file was processed by ServisBOT and may have passed or failed.
  • Bottom Port: The user typed a message and did not interact with the markup, or there was an error.

SecureFileUpload V2

Single file upload markup sample

<TimelineMessage>
    <SecureFileUpload
    promptText="Could you post a picture of the front of your drivers license?"
    promptButtonText="Upload Picture"
    retryButtonText="Replace"
    confirmButtonText="Complete"
    confirmationText="All set!"
    interactionType="event"
    version="2"
    preventRetries="true">
        <UploadItem fileType="image/\*" name="drivers-license-front"/>
    </SecureFileUpload>
</TimelineMessage>

Single file upload markup interaction sample

{
    "version": 2,
    "status": "Passed",
    "numberOfDocuments": 1,
    "numberOfDocumentsPassed": 1,
    "numberOfDocumentsFailed": 0,
    "passedDocuments" : ["drivers-license-front"],
    "failedDocuments" : [], 
    "documents": {
        "drivers-license-front": {
            "notification": "SB:::FileProcessorPipelinePassed:::29cbdf4f-8163-473e-9d44-488ab889fd70",
            "status": "Passed",
            "stage": "FileProcessorPipeline",
            "docId": "29cbdf4f-8163-473e-9d44-488ab889fd70",
            "metadata": {
              "contentLength": 106858,
              "contentType": "image/jpeg",
              "submissionDetails": {
                "submissionId": "7d3bbf4a-03e4-4ed6-8837-8d5653701292",
                "fileIndex": 0,
                "fileCount": 1
              },
              "fileExtension": "jpg"
            },
            "pipelineResults": {
                "validation": {
                    "status": "Passed",
                    "contentLengthCheck": {
                        "status": "Passed"
                    },
                    "fileTypeCheck": {
                        "status": "Passed"
                    },
                    "validationWebhookCheck": {
                      "webhookResponse": {
                        "statusCode": 200,
                        "documentStatus": "ACCEPTED"
                      }
                    }
                },
                "processing": {
                    "status": "Passed",
                    "documentValidCheck": {
                        "status": "Passed"
                    },
                    "deliveryWebhookCheck": {
                      "webhookResponse" : {
                        "statusCode": 200,
                        "documentStatus": "ACCEPTED"
                      }
                    }
                }
            }
        }
    }
}

Multi-file upload markup sample

<TimelineMessage>
    <SecureFileUpload
    promptText="Could you post a pictures of the front and back of your drivers license?"
    promptButtonText="Upload Picture"
    retryButtonText="Replace"
    confirmButtonText="Complete"
    confirmationText="All set!"
    interactionType="event"
    version="2"
    preventRetries="true">
        <UploadItem fileType="image/\*" name="drivers-license-front"/>
        <UploadItem fileType="image/\*" name="drivers-license-back"/>
    </SecureFileUpload>
</TimelineMessage>

Multi-file upload markup interaction sample

{
    "version": 2,
    "status": "Failed",
    "numberOfDocuments": 2,
    "numberOfDocumentsPassed": 1,
    "numberOfDocumentsFailed": 1,
    "passedDocuments" : ["drivers-license-front"],
    "failedDocuments" : ["drivers-license-back"],
    "documents": {
        "drivers-license-front": {
            "notification": "SB:::FileProcessorPipelinePassed:::29cbdf4f-8163-473e-9d44-488ab889fd70",
            "status": "Passed",
            "stage": "FileProcessorPipeline",
            "docId": "29cbdf4f-8163-473e-9d44-488ab889fd70",
            "metadata": {
              "contentLength": 106858,
              "contentType": "image/jpeg",
              "submissionDetails": {
                "submissionId": "7d3bbf4a-03e4-4ed6-8837-8d5653701292",
                "fileIndex": 0,
                "fileCount": 2
              },
              "fileExtension": "jpg"
            },
            "pipelineResults": {
                "validation": {
                    "status": "Passed",
                    "contentLengthCheck": {
                        "status": "Passed"
                    },
                    "fileTypeCheck": {
                        "status": "Passed"
                    },
                    "validationWebhookCheck": {
                      "webhookResponse": {
                        "statusCode": 200,
                        "documentStatus": "ACCEPTED"
                      }
                    }
                },
                "processing": {
                    "status": "Passed",
                    "documentValidCheck": {
                        "status": "Passed"
                    }
                }
            }
        },
        "drivers-license-back": {
            "notification": "SB:::FileProcessorPipelinePassed:::2345dgdf-8163-473e-9d44-488ab889fd70",
            "status": "Failed",
            "stage": "FileProcessorPipeline",
            "docId": "2345dgdf-8163-473e-9d44-488ab889fd70",
            "metadata": {
              "contentLength": 106858,
              "contentType": "image/jpeg",
              "submissionDetails": {
                "submissionId": "7d3bbf4a-03e4-4ed6-8837-8d5653701292",
                "fileIndex": 1,
                "fileCount": 2
              },
              "fileExtension": "jpg"
            },
            "pipelineResults": {
                "validation": {
                    "status": "Passed",
                    "contentLengthCheck": {
                        "status": "Passed"
                    },
                    "fileTypeCheck": {
                        "status": "Passed"
                    }
                },
                "processing": {
                    "status": "Failed",
                    "documentValidCheck": {
                        "status": "Failed"
                    }
                }
            }
        }
    }
}

SecureFileUpload V2 Notes

  • To start using version 2 of the SecureFileUpload node please contact ServisBOT, to enable version 2 for your organization.

In both of the markup interaction samples above you can consider the following:

  • status - The possible values are Passed or Failed, if any document has a status of Failed then the top level status will be Failed.
    • The status key can be found in multiple places within the markup interaction and the possible values are always Passed or Failed.
  • passedDocument - The names of the documents that passed. The names are taken from the UploadItem markup name attribute, and will be sorted alphabetically.
  • failedDocuments - The names of the documents that failed. The names are taken from the UploadItem markup name attribute, and will be sorted alphabetically.
  • documents - An object containing the details of each document that was uploaded, the top level keys are named after the UploadItem markup name attribute.
    • pipelineResults - Contains the results of the steps in the pipeline
      • validation - Contains the details on the validation results in the pipeline
        • validationWebhookCheck - Details about the response of the validation webhook call, this is optional and may not be present.
          • statusCode - A valid HTTP status code
          • documentStatus - The document status returned by the webhook, possible values are ACCEPTED, INVALID, EXPIRED, UNKNOWN
      • processing - Contains the details on the processing results in the pipeline (OCR extraction, delivery webhook rules)
        • deliveryWebhookCheck - Details about the response of the delivery webhook call, this is optional and may not be present
          • statusCode - A valid HTTP status code
          • documentStatus - The document status returned by the webhook, possible values are ACCEPTED, INVALID, EXPIRED, UNKNOWN

SecureFileUpload V2 Ports

  • Top Port: The file was successfully processed and is considered a valid file according to the organization’s configuration.
  • Middle Port: The file was processed and was not considered a valid file according to the organization’s configuration.
  • Bottom Port: The user typed a message and did not interact with the markup, or there was an error.

The markup interaction samples above contain fields which may not always be present, as the pipeline results are dependent on an organization’s configuration, always access the keys with caution.

Star Rating

<TimelineMessage>
  <StarRating
    title="Can you please rate our service today?"
    maxValue="5"
    preventRetries="true"
    interactionType="event"
  />
</TimelineMessage>
{
  "interaction": {
    "action": "starRatingInteraction",
    "timestamp": 1598536867281,
    "value": {
      "id": "3",
      "title": "3 out of 5"
    }
  }
}

Static Map

<TimelineMessage>
  <StaticMap
    title="Please confirm your location"
    interactionType="event"
  />
</TimelineMessage>

When user accepts location

{
  "interaction": {
    "action": "staticMapInteraction",
    "timestamp": 1598536867281,
    "value": {
      "id": "up2WGoZsXA",
      "lat": 52.00,
      "lng": 52.00
    }
  }
}

When user denies location

{
  "interaction": {
    "action": "staticMapInteraction",
    "timestamp": 1598536867281,
    "value": {
      "id": "up2WGoZsXA",
      "title": "Location Denied"
    }
  }
}

Suggestion Prompt

<TimelineMessage>
  <SuggestionPrompt interactionType="event">
    <Option title="30 x 30" id="0" />
    <Option title="32 x 32" id="1" />
    <Option title="33 x 32" id="2" />
    <Option title="34 x 34" id="3" />
    <Option title="35 x 34" id="4" />
    <Option title="v36 x 36" id="5" />
    <Option title="v37 x 35" id="6" />
    <Option title="v38 x 36" id="7" />
  </SuggestionPrompt>
</TimelineMessage>
{
  "interaction": {
    "action": "suggestionPromptInteraction",
    "timestamp": 1598536867281,
    "value": {
      "id": "1",
      "title": "32 x 32"
    }
  }
}

Calendar

Expect the following interactions to go out of the following ports

Top Port: User selected a date from the calendar Bottom port: Errors, and Utterances

<TimelineMessage>
  <Calendar title="When would you like to set it?"
    dateTime="1562112000000"
  maxDate="1562457600000"
  epochFormat="true"
  interactionType="event"
  minDate="1562112000000"/>
</TimelineMessage>
{
  "interaction": {
    "action": "dateTimeInteraction",
    "value": {
      "id": "Wed Jul 03 2019 01:00:00 GMT+0100 (Irish Standard Time)",
      "title": "Wed Jul 03 2019",
      "epochFormat": 1562112000000000
    },
    "timestamp": 1612951063146
  }
}