How to Design a Front-End Application

All the steps and considerations when building a form to collect an applicants information.

This guide is written with the Dynamic Application in mind. The process for the static application is nearly identical, but you'll need to gather the associated data for each risk and coverage parameter from the Appendix.

To design a front-end application, you'll need to have a good grasp on risk and coverage parameters. To refresh your memory, an application is essentially a series of questions for a set of products, categorized as risk values (each question is a risk_parameter) and coverage values (each question is a coverage_parameter).

Since the Dynamic Application is….well, dynamic, Herald provides metadata for each parameter to help you render them on-screen with proper validation.

In this guide, we’ll teach you:

  1. How to format each question on screen, using the property’s text, input_type, and schema to style each question.
  2. How to render nested questions that are child_risk_values of a parent parameter.
  3. To allow multiple values for parameters with creates_array: true.
  4. When to update your application to check for new, conditional questions or a complete application status. Any affects_conditions: true parameter could yield additional questions.
  5. How to build front-end validation using schema.
  6. Which questions you should require, since parameters can be required_for: [quote], bind, or totally optional.
  7. How to structure your application for a great user experience!

1. Formatting each question

For every risk and coverage parameter, we’ll include some useful information to help you render it on screen. The 3 pieces of metadata you should use when formatting individual parameters text, schema, and input_type.

Property Type Description
text String A description of the risk or coverage parameter, which you should format as the label of the input. Today, all of Herald’s text is written to speak to agents.
schema Object A JSON schema describing the expected value. Defines things such enum values for multiple choice questions, or min and max limits requirements for numbers.
input_type String String meant to assist in customizing inputs beyond what is denoted by the JSON schema. There are 14 total input types, e.g. 'short_text', 'long_text', 'address'.

Any number of conditional questions can appear when using the Dynamic Application, so it’s important to build logic to handle every situation. For the most part, parameters are either text inputs, number inputs, multiple choice questions, or objects. We strongly recommend having unique styling in place for each of the 14 input types.

Let’s take a look at a few different parameters based on their input_type.

Location


  {
    "risk_parameter_id": "rsk_yor8_location",
    "instance": "location_1",
    "value": null,
    "text": "Location",
    "input_type": "address",
    "relevant_products": [
      "prd_mc4r_herald_general_liability"
    ],
    "creates_array": true,
    "affects_conditions": true,
    "required_for": [
      "quote"
    ],
    "schema": {
      "type": "object",
      "properties": {
        "line1": {
          "type": "string"
        },
        "line2": {
          "type": "string"
        },
        "line3": {
          "type": "string"
        },
        "organization": {
          "type": "string"
        },
        "city": {
          "type": "string"
        },
        "state": {
          "type": "string",
          "enum": [
            "AL",
            "AK",
            "AZ",
            ...
            "WY"
          ]
        },
        "postal_code": {
          "type": "string",
          "pattern": "^\\d{5}$"
        },
        "country_code": {
          "type": "string",
          "enum": [
            "USA"
          ]
        }
      },
      "required": [
        "line1",
        "city",
        "state",
        "postal_code",
        "country_code"
      ]
    },
  }
   
  

2. Rendering nested questions

Since some questions have a parent/child relationship, it’s important to visually communicate this hierarchy. You’ll also need to associate the child parameter with the parent when submitting values, with the child parameter nested beneath the parent. Child parameters are nested under the parent in an array:

Property Type Description
child_risk_values +
child_coverage_values
Array Signifies that the parameter is a parent, and the array contains all of the child parameters. The name of this property depends on if it is a risk or coverage value. Learn more about the parent/child relationship.

Let’s use the example of an applicant with multiple locations. The applicant may have different class codes under each location, like a manufacturing plant in a San Francisco location and a sales department in Los Angeles. In the application response, each location will have a class code nested below it within the child_risk_values array.

It’s important to render each class code visually below the correct location. This way the applicant knows which class code to submit for each instance of class code. Otherwise, they could see 2 class code inputs without the context of what each of them are for.

Location 1

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Location 2

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Copied

{
  "risk_parameter_id": "rsk_yor8_location",
  "instance": "location_1",
  "value": null,
  "text": "Location",
  "input_type": "address",
  "affects_conditions": true,
  "creates_array": true,
  "required_for": ["quote"],
  "child_risk_values": [
    {
      "risk_parameter_id": "rsk_km7k_gl_class_code_by_location",
      "value": null,
      ...
    },
  ]
},
{
  "risk_parameter_id": "rsk_yor8_location",
  "instance": "location_2",
  "value": null,
  "text": "Location",
  "input_type": "address",
  "affects_conditions": true,
  "creates_array": true,
  "required_for": ["quote"],
  "child_risk_values": [
    {
      "risk_parameter_id": "rsk_km7k_gl_class_code_by_location",
      "value": null,
      ...
    },
  ]
}
 

This segues nicely into our next step.

3. Allowing multiple values

Parameters that can have multiple values have the property creates_array: true. Inherently, parents parameters can have multiple values, because the children parameters are specifically related to a unique instance of a parent. While multiple values are always the case for parents, standard parameters can have multiple values as well. for Some examples of this are:

  • Class code for a specific location. Some applicants have multiple locations, performing different types of work at each one.
  • Payroll for a specific class code. Some appliances have multiple professions, and are required to submit an exposure basis for each one.
  • Property Limits for a specific building. Some applicants have multiple buildings, and have the option to choose unique limits for each one depending on its size and value.
  • A field for domain names, that allows for applicants with multiple domains.

To build a front-end that supports multiple values, you should pay attention to the following metadata: creates_array, instance, and required_for.

Property Type Description
creates_array Boolean True if multiple values can be submitted with the same parameter ID. For example, since an application can have more than one location, the associated risk value will have creates_array: true.
instance String Unique identifier to distinguish different instances of risk or coverage parameter that have the same parameter ID. Ex: if you have 2 locations, they would have the instances location_1 and location_2 respectively. Only relevant when creates_array: true.
required_for Array Array of actions that require this value. When a parameter can have multiple values, this property communicates how many values are required. For example, most carriers only require one location, but support multiple. In this case, the first instance of location would be required_for: quote, and the second would be optional (required_for: [ ])

To support these cases, you need to give applicants the option to add a value. All values that have creates_array: true can have any number of instances. We also recommend giving them the option to remove instances. Let's continue with our same example. Class code below location is a parameter that can have multiple values. Here's a draft of how you could allow an applicant to add multiple class codes.

Add Class Code
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Remove Location -
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Copied

{
  "risk_parameter_id": "rsk_yor8_location",
  "instance": "location_1",
  "value": null,
  "creates_array": true,
  "required_for": ["quote"],
  "child_risk_values": [
    {
      "risk_parameter_id": "rsk_km7k_gl_class_code_by_location",
      "instance": "location_1.gl_class_code_by_location_1",
      "value": null,
      "text": "Class code",
      "input_type": "short_text",
      "affects_conditions": true,
      "creates_array": true,
      "required_for": ["quote"],
      "schema": {
          "type": "string"
      }
    },
    {
      "risk_parameter_id": "rsk_km7k_gl_class_code_by_location",
      "instance": "location_1.gl_class_code_by_location_2",
      "value": null,
      "text": "Class code",
      "input_type": "short_text",
      "affects_conditions": true,
      "creates_array": true,
      "required_for": [],
      "schema": {
          "type": "string"
      }
    }
  ]
}
 

To power this feature on your front-end, we recommend building logic to add an Add + button to every parameter that has creates_array: true.

When somebody clicks that button, it should display an additional input. Similarly to how you'd clone that input on the front-end, you should also clone that input in the backend, sending in a 2nd instance of that parameter but with a different value.

As stated above, each instance of the parameter will be assigned an instance. Our guide to using instance outlines how to use this property to map values below the correct parent when making a request.

4. Updating the application

As we discussed at length in our Dynamic App doc, the dynamic application handles conditionality for you. As you collect and submit values, additional conditional questions can come back. Any risk or coverage parameter that can potentially yield additional parameters is given the property affects_conditions: true.

Property Type Description
affects_conditions Boolean True if the value potentially impacts the relevance of other risk or coverage values.

As you update your application and receive new questions, you’ll need somewhere to put them! Some ways we’ve seen this handled:

  • You could render them on the same screen as you continually update the application, making a PUT request after each value is entered.
  • You could collect the values for the initial set of questions, make a PUT request, and put the next level of conditional questions on the following screen.
  • You could ask each question 1 step at a time for a more conversational approach, inserting each new question with a null value in a following step.

Continuing with our example, we’ve now added a class code input below Location, with the ability to add multiple class codes. Since class code has affects_conditions: true, let’s update the application and see what comes back.

53731
16900
Update Application
Reset
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Conditional questions can come back anywhere after each update, they are not always placed at the bottom. For example, if State is question [ 1 ] and Name is [ 2 ], a conditional question based on State could be returned below [ 1 ]. In this case, Name would now be placed as question [ 3 ].
Copied

{
  "risk_parameter_id": "rsk_yor8_location",
  "instance": "location_1",
  ...
  "child_risk_values": [
    {
      "risk_parameter_id": "rsk_km7k_gl_class_code_by_location",
      "instance": "location_1.gl_class_code_by_location_1",
      "value": "53731",
      ...
      "child_risk_values": [
      {
        "risk_parameter_id": "rsk_xcv3_payroll_by_gl_class_code",
        "value": null,
        ...
      },
    },
    {
      "risk_parameter_id": "rsk_km7k_gl_class_code_by_location",
      "instance": "location_1.gl_class_code_by_location_2",
      "value": "16900",
      ...
      "child_risk_values": [
      {
        "risk_parameter_id": "rsk_w72m_gross_sales_by_gl_class_code",
        "value": null,
        ...
      },
    },
  ]
}
 

5. Building front-end validation

Alluded to in Step 1, Herald includes a schema object to describe the expected value. This property can help render items like enum values on screen, but it can also power front-end validation. Depending on the input_type, schema can define things such as:

  • Min and max values for number inputs.
  • Patterns, for inputs such as phone number.
  • Max characters, for things like FEIN number.

You can use the information denoted in the schema to power your own front-end validation. Here’s a few examples:

Must be a number between 100000 and 5000000


    {
      "coverage_parameter_id": "cvg_c02a_gl_each_occurrence_limit",
      "value": null,
      "text": "Each Occurrence Limit",
      "input_type": "integer",
      "relevant_products": [
        "prd_mc4r_herald_general_liability"
      ],
      "affects_conditions": false,
      "required_for": [],
      "schema": {
        "type": "integer",
        "minimum": 100000,
        "maximum": 5000000
      }
    },
     
    

6. Deciding which questions to require

A risk and parameter can either be optional or required depending on the product and event you are tracking toward. This is conveyed using the required_for array. If it is required for quote, it will be required_for: [”quote”]. If it is optional, the array will be empty like this [ ].

There is a chance that optional questions will still be required to bind a policy when you bridge to the carriers portal. If your goal is simply to get quotes in your platform as quickly as possible, you could choose to only show required_for: [”quote”] parameters. If you want to make a seamless experience after going to the carriers portal, it may be better to ask all questions up front. Here’s an example of how this appears in the application response.

Copied

{
  "coverage_parameter_id": "cvg_c02a_gl_each_occurrence_limit",
  "value": null,
  "text": "Each Occurrence Limit",
  "input_type": "integer",
  "relevant_products": [
    "prd_mc4r_herald_general_liability"
  ],
  "affects_conditions": false,
  "required_for": [],
  "schema": {
    "type": "integer",
    "minimum": 100000,
    "maximum": 5000000
  }
},
{
  "risk_parameter_id": "rsk_14kt_insured_contact_phone",
  "value": null,
  "text": "Applicant phone number",
  "input_type": "phone",
  "relevant_products": [
    "prd_mc4r_herald_general_liability"
  ],
  "affects_conditions": false,
  "required_for": ["quote"],
  "schema": {
    "type": "string",
    "pattern": "$\\d{10}^"
  }
},
 

7. Structuring your application

At last, it’s time to decide how to structure your application. Herald provides you with metadata to build an application that works for you. The most basic form of rendering our Dynamic Application response on screen is by making a 1-page application, where conditional questions appear on the same screen as updates are submitted. If a 1-page application works for you, you can simply make a PUT request every time a value is entered into an input.

If you’re looking to build a fully integrated application with an existing front-end, where you’d like to pick and choose where to place each individual question, our static application might be best for you. But we’re continually looking to improve our Dynamic Application API to support more use cases. If you’re still deciding what to build and want to chat, reach out!