×Overview
×About Formsort
Creating accounts
Providing feedback
×Flows and Variants
Flows
×Variants
Creating a new variant
Limits
×Steps and Questions
Steps
Groups
Questions
×Drafts and Publishing
Drafts
Live preview
×Publishing
Responder lifecycle
Superseding
Resetting the answers / responder (even in prod)
×Customization
Sharing style sets
×Variables and schemas
Answer variable names
×Using variables in templates
Formatting variables with template functions
Schema
×Conditions and Logic
×Conditional steps and questions
Advanced logic
×Terminal steps
Redirect URLs
Validation
×Passing data in
Passing answers via URL search parameters
Passing in answers that are not collected within the flow
×Answers API (derived or computed answers)
Result accessor
Choices API
×Getting data out
Templated redirect URL
×Webhook
Shape of the data
Testing webhooks
Signing requests
Cookies
×Analytics
Event lifecycle
Segment
Google analytics
Fullstory
×Google Tag manager
Built-in analytics
×Security
Don't send to third party analytics
Don't send to formsort
×Testing
Setting up weights for A/B testing
×Deep integration
CNAME
<iframe> or embed

Overview

About Formsort

Formsort allows you to rapidly prototype, deploy and optimize beautiful and secure online form flows that enable meaningful customer interactions.

Creating accounts

To access formsort as a creator or editor of flows, you must have an account.

Account creation is still in beta: if you have a collaborator who does not have an account but needs one, fill out the request account form.

Providing feedback

It's much easier for us to build what you need if you tell us what you're trying to achieve. Drop us a line at hello@formsort.com with any bugs, feature suggestions, or use cases you'd like to explore with us.

Flows and Variants

Flows

When you sign in, you're brought to your list of flows. Think of a flow as a way to collect information to fulfill a specific goal within your organization: for example, a new user sign-up flow, a collecting-feedback flow, a matching-to-an-agent flow.

Variants

Within a flow, you can create variants. These can be wildly different from one another in terms of style and content, but should still have the same goal and collect the same information as the other variants in the flow. You might use a variant to try out a new visual style or a new content ordering of your questions.

Creating a new variant

Every flow comes with a main variant by default.

To create a new variant, go into an existing variant and click Save as... at the top, or in the actions column of the variants list.

Limits

There are no limits to the number of flows you can create, or the number of variants that a flow may have.


Later, in Testing, you'll see how to A/B test different variants against one another.

Steps and Questions

Steps

Steps help organize flows into discrete groupings of questions. They are displayed one step at a time. They help users measure progress towards completing the flow, and help you segment the information you collect and responses you provide to your users into logical fragments.

Steps can easily be reordered by dragging and dropping, and can be given their own labels, which are shown to users. Steps by themselves do not collect any information.

By default, when a user is going through a flow, the current index of the step they are on is present in the URL, so that they can use browser navigation to navigate back and forth within a flow.

To delete a step, select its container and hit Delete, or click "Remove step" at the bottom of the question options.

Groups

If you have many steps, and would like to organize them into categories, you may create groups on the left hand side of the studio editor. Reordering groups will keep the order of steps within each group the same.

By default, groups are not visible to users completing your flows, but you may set the progress bar style to show the groups to emphasize progression through phases of your flow.

Questions

Within a step you can add one or more questions or pieces of content. These are the building blocks that help create the set of information you're collecting from your user.

Most question types collect answers from a user. Currently, we support the following question types, but are always adding more:

  • address
  • boolean (yes / no)
  • confirmation
  • date
  • email
  • number (including sliders)
  • phone
  • postal code
  • select a choice (or multiple)
  • text

Some content blocks don't collect any answers -- they merely exist to provide information back to a user.

  • divider: space between questions
  • image content: images
  • informational: text (and optionally images or videos)
  • map
  • video content

Questions may be rearranged within a step or between steps via drag-and-drop.

A question can be made optional, in which case it is not required to be answered to continue in the flow.

To delete a question, select the container and hit Delete, or click "Remove question" at the bottom of the question options.

Drafts and Publishing

Drafts

As you edit anything in formsort, your changes are automatically saved every few seconds (you can also force a save with Cmd/Ctrl+S).

Drafts are not visible to users without formsort accounts from your organization until they are published.

Live preview

To see a preview of what your flow will look like to end users at any time, even before you have published, click "Live preview". Changes you make within the editor will sync in real time to the preview window. Within the preview window, you can choose which device size your flow is shown in.

Checking Show all within the preview window will cause logic to be ignored within the flow being previewed, so that you can see all steps or questions even if they would normally be disabled.

Publishing

When you are ready to send your flow to real users, you may publish your flow by clicking "Publish". This will make your flow available to anyone that you send the link to.

Responder lifecycle

When a user arrives at your flow, if they have not been seen before, they are given a unique identifier, the responder uuid. They are also given the latest published variant revision available for the flow variant they are requesting.

If they return again, their responder uuid will be used to retrieve any answers they may have provided up until that point. You may change this behavior within the style tab's behavior section, to either force the user to start from the beginning or review their answers up until that point. They will also continue on the same revision of the variant that they started on, even if new revisions have been published in the interim.

Superseding

If you'd like to force all users who have partially completed a flow to use the latest one, at the time of publishing you may choose to supersede existing variants. This is helpful if you had previously introduced a logical mistake or must ensure that everyone is on the latest version of a flow, even if they started on an older version.

Resetting the answers / responder (even in prod)

If you're testing and would like to completely restart a flow, including the responder uuid that you have been assigned, you may either clear your localStorage from within the javascript console, or hold down on your flow's logo for 3 seconds to restart.

Customization

It's possible to customize almost every aspect of your flow variant in the Style tab.

The easiest way to get a sense for this is to open the live preview window and see your changes take effect on your real flow. For this reason, we recommend fleshing out at least some of the steps and questions before trying to get the styling perfect.

Sharing style sets

When you publish a style set as a theme, it can be re-used in any flow in your organization. To save the current set of styles as a theme, click Edit... on the top-roght of the style editor tab.

Changes made to a variant sit on top of the base theme - you may revert any change made by hovering that particular setting and clicking Revert.

Variables and schemas

Answer variable names

Every question that you ask of a user will result in a piece of data captured. To more reliably refer to the data, both in your own systems as well as within formsort, each question's answer is given a variable name by default.

You should update these to something consistent that it not verbose but expresses the semantic meaning of the information collected (for example, first_name is a better-named variable than just name since you may end up collecting multiple names in a flow).

Using variables in templates

In most labels and text content blocks, you can use references to previously-captured variables to create templated strings. Just look for "See variables..." to browse the variables available to you, or just type a known variable using double-brackets syntax (eg. Hi, {{first_name}})

Formatting variables with template functions

There are a few template functions to help with displaying variables:

  • round
  • floor
  • ceil
  • uppercase
  • lowercase
  • capitalize
  • usd (eg 2000 -> $2,500)

To use these, add the pipe character and then the function name in the templated text you're writing. For example, to lowercase a variable called name, you'd write {{name | lowercase}}.

Schema

To see all of the answers that are collected in your flow and may end up in your answer sets, see the Schema tab.

Conditions and Logic

Variables can also be used to modify a flow's behavior once they are collected. This is useful for making flows dynamic and more personalized to a specific user's needs.

Conditional steps and questions

Steps and questions can be made conditional, wherein they only appear if a certain logical constraint holds true.

Currently, the following logical operators are supported:

  • eq: the variable equals the condition
  • noteq: the variable is set, but does not equal the condition
  • gt: the variable is greater than the condition
  • lt: the variable is less than the condition
  • regex: the variable matches the given regular expression
  • notregex: the variable does not match the given regular expression
  • isdef: the variable has been defined
  • isnotdef: the variable has not been defined

Advanced logic

If advanced logic is set, you may enter logic using the MongoDB Query and Projection operators. For example, if you were checking whether a user is over 18 years of age and lives in the USA or Canada, you could add the following as a condition:

{
  $and: [
    {
      $age: { $gte: 18}
    },
    {
      $country: { $in: ["USA", "Canada"]}
    },
  ]
}

See Passing data in for more advanced ways to enable arbitrarily complex logic for conditions, where you can calculate the logic on your own server.

Terminal steps

Steps can also be made terminal, meaning that they end the flow if they are reached. Together with setting a condition, you can use terminal steps to route users based on their previous answers, or disqualify users from continuing if they do not meet certain criteria.

Redirect URLs

You may set a redirect url, which can use variables defined up until that point in the flow, which terminated users will be redirected to. These redirect URLs may be templated using variables you've collected.

For example, if you collect a variable that you've given the name first_name, you could pass this variable to the redirect landing page by setting the redirect URL to https://example.com?first_name={{first_name}}.

Validation

Your flow is constantly checked for validation errors which would result in logical inconsistencies. If you are unable to publish, you will see a list of logical problems that you need to resolve before the flow can safely be shown to users in a way that it can be completed without jumpiness or inconsistency.

Passing data in

Often, you will want to start a flow with some answers prefilled, or will need to reach outside of the formsort world to get some data you need to build robust flows.

Passing answers via URL search parameters

The easiest way to set answers in a flow from outside is to set them in the url search parameters in the URL to the flow, using the variable names as keys

For example, if I have a variable first_name, I could pass a first name into a flow by appending ?first_name=Hélène to the URL of a flow. If you're passing multiple answers at once, separate the answers with an ampersand, for example ?first_name=Hélène&last_name=Wilson.

Answers passed with the wrong type, or to non-existent variable names, are ignored when loading the flow.

Passing in answers that are not collected within the flow

You may find that you need to pass in data that isn't collected within the questions themselves. For example, you may track what source a user comes from using a ?utm_source= parameter, that you may want to either pass on when redirecting at the end of the flow, or use within the flow.

To allow acceptance of variables not used in the flow, access the Schema tab and complete Add external variable... at the bottom.

Answers API (derived or computed answers)

Often, you will want to calculate a new answer based on the answers provided within a flow. For example, given a zip code, you may want to find the closest store to that location, or fetch pricing for a product the user may be interested in purchasing. This data lives in your own systems, and would be tedious to recreate in formsort or keep in sync, since your system is the source of truth.

This is also possible using Add external variable..., when you also enable Is this variable computed from an API. Then, you will be allowed to specify a URL (in which you can use templated variables) that will be fetched whenever all the dependent answers are collected. If you implement a JSON GET endpoint at that URL, you will have access to that answer within formsort.

Result accessor

Let's say we're fetching some data from a url https://example.com/api/v1/closest_store?zipcode={{zipcode}}.

The API result, depending on how we implement it, might look something like this:

{
  "ok": true,
  "store": {
    "name": "Bob's Burgers", 
    "employeeCount": 4
  }
}

The result accessor is the way we would access the piece of data we need using Javascript syntax.

So, if we wanted to define a derived answer named closest_store_name, we could use the result accessor store.name.

Note that it's possible to access within arrays using array indexes. So if your API result looks like:

{
  "prices": [
    {
      "product": "Apple",
      "price_usd": 1
    },
    {
      "product": "Banana",
      "price_usd": 2
    }
  ]
}

You can access the first price with prices[0].price_usd.

If the API fails to load, or the result does not have the correct variable type at the accessor path, the answer will not be set.

Choices API

A related API is the Choices API, which allows for dynamically fetching the list of choices provided to the user in a select question. If you wanted to have the user pick between nearby stores, you might want to use this API, by checking Load choices dynamically? on any select question.

The expected shape of the returned JSON looks like:

[
  {
    label: "",
    value: "",
  }
]

If you'd like to display images on the select options (for example when using the button style), you may also pass the imageUrl attribute for each chioce.

[
  {
    label: "",
    value: "",
    imageUrl: "http://example.com/image.png",
  }
]

Getting data out

Information you collect is only useful if you can access it. The Integrations tab in the variants page is where you can define and customize the ways you can receive information collected in your flows.

Templated redirect URL

The simplest way to pass data into another system is by using answer variables in a redirect url for any terminal steps. Read more about this in Conditions and logic.

Webhook

The most robust way to receive data during a flow's progress and completion is to set up an endpoint for ingesting webhooks. Formsort can send data to this endpoint after each step, or only at the end of the flow (onfinalize_).

Shape of the data

The webhook is a POST of JSON data in the following shape:

{
  ...answers,
  [responder uuid alias?]: string
  "variant_label": string,
  "variant_uuid": string,
  "finalized": boolean
}

If you'd like the responder uuid to be included, you can give it an alias in the webhook configuration.

It's possible to change the shape of the data, for example to nest the answers under their own key, or put them into an array.

Testing webhooks

You can send a test webhook with dummy data for a variant with the Send test webhook button, or just inspect a sample webhook body with the View webhook payload button.

Signing requests

If you'd like the requests to be signed to ensure that they are authentic requests from formsort, you can enable the sign security.

The payloads will be signed with the following Python code. You can obtain the key in the Integrations tab when this option is enabled.

def as_bytes(v):
    return v.encode("utf8")


def hmac_sign(k, m):
    key = as_bytes(k)
    message = as_bytes(m)
    return (
        base64.urlsafe_b64encode(hmac.new(key, message, hashlib.sha256).digest())
        .rstrip(b"=")
        .decode("utf8")
    )

Cookies

If you would like formsort to set cookies at the root domain of your integration with answer values, you may pick specific answer variables to set in the Schema tab by checking the Store in cookie checkbox. These cookies will be set using the answer variable as the key on the root domain. For example, if your flow is at flow.example.com, any variables with Store in cookie set will be placed on the .example.com domain.

Analytics

Event lifecycle

You may choose to receive any or all of the following events:

  • FlowLoaded when the flow is initially loaded.
  • StepLoaded whenever a step is loaded (even if for a second time, such as with backward navigation)
  • UrlOpened whenever a user is redirected to a URL outside of your flow
  • StepCompleted whenever a step is completed (all the required answers were provided and the user clicked next)
  • EmailCollected the email identifying the user has been collected (if the email question collecting the answer has Identifies responder? set to true)
  • FlowFinalized the flow has been completed because the user completed all steps or reached a terminal step

Segment

Segment is by far the most dynamic integration option, which allows you to pick and choose other third-party providers to send data to within Segment.

Google analytics

When provided a Google Analytics ID, every step load is counted as a page view event. Additionally, you may send any of the lifecycle events to GA.

Fullstory

When a fullstory ID is set, all flow sessions will be recorded.

Google Tag manager

Our GTM form integration allows for sending of any of the lifecycle events to GA.

Built-in analytics

Analytics directly within formsort to allow understanding the results of improvements and A/B tests without using external tools. To access analytics on the relative performance of your variants within a flow, see the analytics tab.

Security

If you are collecting sensitive information from your customers, there are multiple ways to reduce your exposure of leaking that information in the Schema tab of a variant.

Don't send to third party analytics

Variables with this checked will be excluded from any payloads sent to third-party integrations in the Integrations tab.

Don't send to formsort

Variables with this checked will be excluded from any payloads sent to Formsort. If you have a webhook configured, they will be sent to that webhook URL directly from the user's browser, meaning that formsort does not receive nor handle this data.

Note that with this enabled, if a user returns to an already-started flow, they will have to re-enter their sensitive information since it will not be retrievable from Formsort.

Testing

Normally, when you navigate to a specific variant's url, for example /client/formsort/flow/onboarding/variant/main, you will always get the latest published revision of that variant (in this example, main). If you'd like to split your traffic between two or more variants, setting up A/B tests within formsort is simple.

Setting up weights for A/B testing

When clicking into a flow, you will see a list of all variants. For published variants, you will see the weight that they are currently assigned. If you're created multiple variants in a flow, by using Save as... within a variant, you'll see multiple variants. You can adjust the weights to alter the traffic split between the variants.

Then, instead of using the /variant/{{name}} URL, simply link to the flow itself, in our example /client/formsort/flow/onboarding/. A variant will be randomly selected according to the weights, and if the user abandons and then returns on the same browser, they will stay on the same revision of the same variant, just like when accessing the variant directly.

In the analytics events, the label of the variant is provided as variant_label, so you can evaluate downstream the relative performance of the variants within a flow.

Deep integration

Once published, without any work, your flows become available under the flow.formsort.com domain.

CNAME

If you'd like to host a flow under your own domain, or a subdomain of a domain that you own, you can set up a CNAME.

Please contact us at hello@formsort.com to get this set up.

Once configured, it's possible to change the particular flow and variant that a CNAME points to.

<iframe> or embed

The alternative integration option is to iframe a variant or a flow. This allows formsort to operate only a part of your website. Our integration wrapper allows for passing of events like when the form is completed or abandoned to the parent container, to allow you greater control.