AWS Business Intelligence Blog

Create custom charts in Amazon QuickSight using the Highcharts visual

We are excited to announce the Highcharts visual in Amazon QuickSight, a powerful new visual type that significantly enhances data visualization capabilities. This feature enables authors to create a wide array of chart types and design beautifully customized visualizations. Available at no additional cost, it empowers you to configure visuals using the Highcharts JSON schema, offering unprecedented flexibility to meet diverse visualization needs. With the Highcharts visual, QuickSight users can now craft even more impactful and tailored data representations to drive insights and decision-making.

Solution overview

With the Highcharts visual, you can now:

  • Create specialized visualizations like packed bubble charts and lollipop charts
  • Customize chart elements with granular control using the Highcharts JSON schema
  • Design visuals that match organizational branding guidelines
  • Build interactive visualizations with dynamic elements
  • Streamline dashboard creation entirely within QuickSight

This feature uses the Highcharts Core library to provide unprecedented visualization flexibility while maintaining the user-friendly approach of QuickSight. Authors can reference QuickSight fields and formatting in the JSON using QuickSight expressions. The JSON code editor includes contextual assistance features, providing autocomplete and real-time validation to achieve proper configuration. To maintain security, the Highcharts visual editor prevents the injection of CSS and JavaScript, or HTML code.

Whether you’re creating complex analytical dashboards or transitioning from other business intelligence (BI) platforms, Highcharts visual empowers you to build exactly the visualization you need.

Getting started

To add a Highcharts visual to an analysis, choose the Add visual icon and choose Highcharts visual. Alternatively, you can access the visual type selector from the secondary left pane by choosing Add.

The following screenshot highlights the key properties of the Highcharts visual.

Create a lipstick column chart (fixed column placement chart)

The clustered column chart is a commonly employed visualization technique for comparing two measures across multiple categories. However, when one measure serves as a reference or secondary metric to provide context for the primary measure, it’s advantageous to visually distinguish this hierarchical relationship.

The lipstick column chart addresses this need by presenting a clear visual hierarchy. It prominently displays the primary measure for each category in the foreground, while positioning the secondary measure behind it. This arrangement facilitates a precise comparison between the two values while maintaining a clear emphasis on the primary metric.

An additional benefit of the lipstick column chart is its space efficiency. By superimposing the two measures for each category, it offers a more compact alternative to traditional side-by-side comparisons, allowing for effective data representation in constrained visual spaces.

Let’s take an example of a column chart that displays Industries on the x-axis and two series, Current Year Sales and Prior Year Sales, on the y-axis. We will also add a third series called Target Sales as a marker and use conditional formatting to compare Current Year Sales vs. Prior Year Sales.

Step1: Create a column chart for Current Year Sales by Industry

  1. In your analysis, choose the Add visual icon (or choose ADD).
  2. From the Fields list, choose Industry and Current Year Sales (change the values to fit your use case).
  3. Expand the Display settings section and choose the paint brush icon next to Edit title.
  4. Enter Current Year Sales by Industry and choose Save.
  5. Expand the code editor section and enter the following code:
{
  "xAxis": {
    "categories": ["getColumn", 0]
  },
  "yAxis": {
    "min": 0,
    "title": {
      "text": "Amount ($)"
    }
  },
  "tooltip": {
    "headerFormat": "<span style='font-size:10px'>{point.key}</span><table>",
    "pointFormat": "<tr><td style='color:{series.color};padding:0'>{series.name}: 
</td><td style='padding:0'><b>${point.y:,.0f}</b></td></tr>",
    "footerFormat": "</table>",
    "shared": true,
    "useHTML": true
  },
  "plotOptions": {
    "column": {
      "borderWidth": 0,
      "grouping": false,
      "shadow": false
    }
  },
  "series": [
    {
      "type": "column",
      "name": "Current Year Sales",
      "color": "rgba(124,181,236,1)",
      "data": ["getColumn", 1],
      "pointPadding": 0.3,
      "pointPlacement": 0.0
    }
  ]
}

["getColumn", 0] and ["getColumn", 1] map to the first and second fields in the field wells, which are Industry and Current Year Sales, respectively.

  1. Choose APPLY CODE.

You should see the results as shown in the following screenshot.

Step 2: Add Prior Year Sales as an overlapping column

  1. From the Fields list, add Prior Year Sales to the VALUE field below Current Year Sales.
  2. Expand the Chart code section and modify the "series" array using the following code to add Prior Year Sales.

The pointPadding attribute for Current Year and Prior Year Sales are different. A higher pointPadding value makes the bar thinner. The pointPlacement values are the same for both fields, which makes both bars overlap in this case.

  "series": [
    {
      "type": "column",
      "name": "Current Year Sales",
      "color": "rgba(124,181,236,1)",
      "data": ["getColumn", 1],
      "pointPadding": 0.2,
      "pointPlacement": 0.0
    },
    {
      "type": "column",
      "name": "Prior Year Sales",
      "color": "rgba(18,5,3,0.7)",
      "data": ["getColumn", 2],
      "pointPadding": 0.4,
      "pointPlacement": 0.0
    }
  ]
  1. Choose APPLY CODE.

You should see the results as shown in the following screenshot.

Step3: Add a third series “Target Sales” as a marker

  1. From the Fields list, add Target to the VALUE field below Prior Year Sales.
  2. Expand the Chart code section and modify the "series" array using the following code to add Target Sales.

The new series is of "type": "line". The "color": "rgba(0,0,0,0)" property is used to make the line transparent and only show the marker.

"series": [
    {
      "type": "column",
      "name": "Current Year Sales",
      "color": "rgba(124,181,236,1)",
      "data": ["getColumn", 1],
      "pointPadding": 0.2,
      "pointPlacement": 0.0
    },
    {
      "type": "column",
      "name": "Prior Year Sales",
      "color": "rgba(67,67,72,0.7)",
      "data": ["getColumn", 2],
      "pointPadding": 0.4,
      "pointPlacement": 0.0
    },
    {
      "type": "line",
      "name": "Target Sales",
      "color": "rgba(0,0,0,0)",
      "data": ["getColumn", 3],
      "marker": {
            "lineWidth": 5,
            "lineColor":"red",
            "fillColor": "white"
        }
    }
  ]
  1. Choose APPLY CODE.

You should see the results as shown in the following screenshot.

Step 4: Change the marker to a triangle symbol

  1. Expand the Chart code section and modify the "series" array "marker" attribute using the following code:
     "marker": {
            "lineWidth": 3,
            "symbol": "triangle",
            "lineColor":"red",
            "fillColor": "white"
        }
  1. Choose APPLY CODE.

You should see the results as shown in the following screenshot.

Step 5: Add conditional formatting to the Current Year Sales column

  1. Expand the Chart code section and modify the "series" array "data" attribute for Current Year Sales series using the following code:
    {
      "type": "column",
      "name": "Current Year Sales",
      "color": "rgba(124,181,236,1)",
      "data": [
        "map",
        ["getColumn", 1, 2, 3],
        {
          "y": ["get", ["item"], 0],
          "color": [
            "case",
            [">=", ["get", ["item"], 0], ["get", ["item"], 2]],
            "rgba(168, 244, 179)",
            [">=", ["get", ["item"], 0], ["get", ["item"], 1]],
            "rgba(245,226,39,1)",
            "rgba(241,165,160,1)"
          ]
        }
      ],
      "pointPadding": 0.2,
      "pointPlacement": 0.0
    }

The preceding code block changes the color of the Current Year Sales column to "rgba(168, 244, 179)" (green) when Current Year Sales is greater than Target, to "rgba(245,226,39,1)" (yellow) when Current Year Sales is greater than Prior Year Sales, and to "rgba(241,165,160,1)" (pink) when Current Year Sales is less than Prior Year Sales and Current Year Sales is less than Target.

  1. Choose APPLY CODE.

You should see the results as shown in the following screenshot.

Additional examples

The following are some more examples of Highcharts visuals along with their code blocks for reference.

Packed bubble charts

Packed bubble charts are visualizations where the size and optionally the color of the bubbles are used to visualize the data. The positioning of the bubbles is not significant, but is optimized for compactness.

{
  "chart": {
    "type": "packedbubble"
  },
  "tooltip": {
    "useHTML": true,
    "pointFormat": "<b>{point.name}:</b> ${point.value:,.0f}"
  },
  "plotOptions": {
    "packedbubble": {
      "minSize": "20%",
      "maxSize": "130%",
      "zMin": 0,
      "zMax": 500000,
      "layoutAlgorithm": {
        "splitSeries": false,
        "gravitationalConstant": 0.02
      },
      "dataLabels": {
        "enabled": true,
        "format": "{point.name}",
        "filter": {
          "property": "y",
          "operator": ">",
          "value": 25000
        },
        "style": {
          "color": "black",
          "textOutline": "none",
          "fontWeight": "normal"
        }
      }
    }
  },
  "series": [
    "map",
    ["unique", ["getColumn", 0]],
    {
      "name": ["item"],
      "data": [
        "map",
        [
          "filter",
          ["getColumn", 0, 1, 2],
          ["==", ["get", ["item"], 0], ["item", 2]]
        ],
        {
          "name": ["get", ["item"], 1],
          "value": ["get", ["item"], 2]
        }
      ]
    }
  ]
}

Bullet charts

Bullet charts allow readers to quickly compare a single value to a target value. This particular demonstration incorporates plot bands to delineate distinct ranges along the axes, enhancing the chart’s interpretability. Due to their compact nature, bullet charts have gained significant popularity in dashboard design. They offer a space-efficient alternative to gauge charts, allowing for the presentation of key performance indicators (KPIs) in a concise manner.

{
  "chart": {
    "type": "bullet",
    "inverted": true,
    "marginLeft": 135,
    "marginTop": 40
  },
  "title": {
    "text": "Revenue Performance"
  },
  "xAxis": {
    "categories": [
      "<span class='hc-cat-title'>Revenue</span><br/>U.S. $ (1,000s)"
    ]
  },
  "yAxis": {
    "plotBands": [
      {
        "from": 0,
        "to": 15000,
        "color": "#666"
      },
      {
        "from": 15000,
        "to": 23000,
        "color": "#999"
      },
      {
        "from": 30000,
        "to": 9e9,
        "color": "#bbb"
      }
    ]
  },
  "tooltip": {
    "pointFormat": "<b>{point.y}</b> (Target: {point.target})"
  },
  "plotOptions": {
    "series": {
      "pointPadding": 0.25,
      "borderWidth": 0,
      "color": "#000",
      "targetOptions": {
        "width": "100%",
        "height": 20,
        "borderWidth": 2,
        "borderColor": "green",
        "borderRadius": 10,
        "color": "green"
      }
    }
  },
  "series": [
    {
      "data": [
        "map",
        ["getColumn", 0, 1, 2],
        {
          "y": ["get", ["item"], 1],
          "target": ["get", ["item"], 2]
        }
      ]
    }
  ],
  "legend": {
    "enabled": false
  },
  "credits": {
    "enabled": false
  },
  "exporting": {
    "enabled": false
  }
}

Highcharts visual QuickStart guide

For more examples and code samples of the Highcharts visual in QuickSight, visit QuickSight DemoCentral.

QuickSight expressions

The Highcharts visual accepts any valid JSON values, excluding functions, dates, and undefined values. It also supports standard arithmetic, string, and conditional operators. Additionally, QuickSight offers specific expressions to enhance functionality:

  • getColumn – This is the core expression that return values from specified column indexes. As seen in the following example, ["getColumn", 0] would get values for the first field (Name).
Name Age Income Tenure
John 42 123123 10
Samantha 32 492123 15
Auxie 25 85921 12

The input JSON is as follows:

{
  names: ["getColumn", 0], 
  ages: ["getColumn", 1]
}

The output JSON is as follows:

{
  names: ["John", "Samantha", "Auxie"],
  ages: [42, 32, 25]
}

You can also pass multiple columns at once, which returns an array of arrays.

The input JSON is as follows:

{
  values: ["getColumn", 0, 1]
}

The output JSON is as follows:

{
  values: [["John", 42], ["Samantha", 32], ["Auxie", 25]]
}
  • getColumnFromGroupBy – Similar to getColumn, the getColumnFromGroupBy expression returns values from the groupby field wells that are used in QuickSight. Either of these expressions can pass multiple indices to have an array of arrays returned, with each element corresponding to the field in the groupby field wells.
  • getColumnFromValue – Similar to getColumnFromGroupBy, this applies for the Value field.
  • formatValue – This applies QuickSight formatting to values. For example, the following expression formats the x-axis label with the format value that is specified in the first field of QuickSight field wells
 "xAxis": {
    "categories": ["getColumn", 0],
    "labels": {
       "formatter": ["formatValue", "value", 0]
    }
  },
  • getColorTheme – To get QuickSight’s current color palette use getColorTheme expression:
{
"color": ["getColorTheme"]
}

Limitations

As of this writing, the Highcharts visual has the following limitations:

  • Interactivity – No filter, navigation, or URL actions are supported (however, tooltips are possible using the Highcharts JSON)
  • External resources – Linking to GeoJSON and images is not supported
  • Color exp – Field colors aren’t available; default theme colors are used
  • Filtering – Ad-hoc filters are not supported

Conclusion

The Highcharts visual in QuickSight significantly enhances data visualization capabilities, offering you unparalleled flexibility and control. This powerful addition expands visualization options beyond built-in chart types, enables the creation of sophisticated and tailored visuals, streamlines dashboard creation within QuickSight, and reduces reliance on external tools. With the Highcharts visual, QuickSight users can now craft more impactful and insightful dashboards, improve data interpretation and communication, and transform complex data into compelling visual narratives. This feature empowers organizations to make better-informed decisions through enhanced data storytelling. We look forward to seeing how you use the Highcharts visual to unlock new insights and drive business value.


About the authors

Salim Khan is a Specialist Solutions Architect for Amazon QuickSight. Salim has over 16 years of experience implementing enterprise business intelligence (BI) solutions. Prior to AWS, Salim worked as a BI consultant catering to industry verticals like Automotive, Healthcare, Entertainment, Consumer, Publishing and Financial Services. He has delivered business intelligence, data warehousing, data integration and master data management solutions across enterprises.

Bhupinder Chadha is a senior product manager for Amazon QuickSight focused on visualization and front end experiences. He is passionate about BI, data visualization and low-code/no-code experiences. Prior to QuickSight he was the lead product manager for Inforiver, responsible for building a enterprise BI product from ground up. Bhupinder started his career in presales, followed by a small gig in consulting and then PM for xViz, an add on visualization product.

Arun Santhosh is a Principal Solutions Architect for Amazon QuickSight. Arun started his career at IBM as a developer and progressed on to be an Application Architect. Later, he worked as a Technical Architect at Cognizant. Business intelligence has been his core focus in these prior roles as well.