StatsBomb x Qlik Sense – Part 2: Dashboard Design

In StatsBomb x Qlik Sense – Part 1: Data Preparation, we created a data model using JSON files from StatsBomb’s GitHub repository. Now, we will design a dashboard using just five native Qlik Sense objects – layout container, map, button, text, and line (yes, line).

Before we start, let’s set up a few things. Go to Fields, right-click on the ID field, choose Field settings, and select Always one selected value to ensure only one player remains selected at any time. Another important step is outside the app, in the Administration settings, under Content Security Policy. There you need to add img.uefa.com as Origin so that the images can be displayed in Qlik Sense Cloud.

Sheet background

To start, set up the background. I used a simple off-white and charcoal blue image as a sheet background under Sheet properties > Styling > Background image. You could also use a single background color, an option located just above. Additionally, set a custom sheet size in Sheet properties > Sheet size. I went with 1920×950.

Layout container

Add a layout container and resize it to cover the entire sheet. To display the player’s pictures on the dashboard, navigate to the properties panel:

Appearance > Presentation > Styling > Background image > URL
=URL

In the Presentation section, set up the grid size. More rows and columns give finer control over object placement within the container. As all objects will be in this layout container, it’s worth checking out Using the Layout Container in Qlik Sense.

Buttons

The dashboard features three main buttons to control the fields added to the data model – Heat_Map, Shot_Map, and Pass_Map. In addition, there are two navigation buttons to switch between football players.

Main buttons

Let’s focus on the heat map button, which performs three actions:

Actions and navigation
Action: Clear selections in field
Field: Shot_Map

Action: Clear selections in field
Field: Pass_Map

Action: Toggle field selection
Field: Heat_Map
Value: Yes

For the button’s image, go to Appearance > Presentation > Styling > General > Background image and choose one from the Media library. Set it to Always fit. Then adjust the following settings:

Appearance > General
Show titles: Off
Show label: Off

Appearance > Icon
Show icon: Off

Appearance > Presentation > Styling > Chart > Background options > Color > By expression
=ARGB(0,248,248,248)

The shooting and passing buttons follow the same setup. Make sure to assign actions that reset selections from the other buttons.

It is a good practice to signal when a button has no data to show, e.g. a player has not taken a shot. To do this, you can overlay a non-interactive gray button that executes no actions. Set a show condition for this button in the layout container properties panel. Here is the show condition for the gray shooting button:

Content > Button > Show condition
=COUNT({<Shot_Map={'Yes'}, Heat_Map=, Pass_Map=>}Event_ID)=0

Apply the same logic to disable the passing and heat map buttons, though a blank heat map is unlikely unless the player substituted the corner flag.

Navigation buttons

With the main button actions set, let’s add navigation controls to switch between players. The two arrow buttons control the ID field that we created in the Pictures table. Each executes only one action, e.g. the left arrow button is configured as follows:

Actions and navigation
Action: Select values in a field
Field: ID
Value: =IF(NUM(ID)=NUM(MIN({1}ID)), NUM(MAX({1}ID)), NUM(ID)-1)

The expression checks if the current player ID is equal to the minimum ID value across the entire dataset. This enables seamless navigation by looping to the maximum ID when the minimum is reached. The right arrow is configured similarly, except it checks if the maximum ID is reached. In terms of styling, the navigation buttons follow the settings of the main buttons, but instead of a background image, each uses an icon under Appearance > Icon.

Text

I used the text object from the dashboard bundle since it offers better formatting options than the standard one. To match the inactive buttons, an additional text object with gray font overlays the main text, using the same show conditions as the gray buttons.

To display player names, a simple text object with the following expression does the job:

=Player_Name

The legend under the football pitch is composed of text objects with show conditions placed on top of each other. The condition e.g. for the heat map legend is as follows:

=GETSELECTEDCOUNT(Heat_Map)=1

Line

A vertical line placed next to each main button subtly highlights the active button selection, while keeping the interface clean and uncluttered. The show conditions are the same as the ones used for the legend.

Map

Let’s dive into the most exciting part – mapping player actions on the field. We will use the map object to display a football field and plot our StatsBomb data. Start by adding a map to the layout container and adjust the settings:

Map settings
Base map: None
Projection: User defined (degrees)
Auto-zoom: Off

Appearance > General
Show titles: Off

Appearance > Legend
Show legend: Off

Appearance > Presentation
Navigation: Off
Scale bar: Off
Limit zoom levels: 3x zoom - 3x zoom
Limit pan navigation: Custom

With these settings ready, we are all set to add four layers – a background layer for the football field, a density layer for the heat map, a line layer for the passes, and a point layer for the shots, making it easy to get a full view of player activity.

Background layer

Add a background layer. Under Data > Format choose Image and set URL to a pitch image, preferably SVG like this one, since these can be easily color-adjusted to match your dashboard’s style. Do not forget to enable the image’s URL under under Administration > Content Security Policy. Continue to set the image position. For the one linked above, the proper values would be as follows:

Top (latitude): 125
Left (longitude): -2.6
Bottom (latitude): -2.6
Right (longitude): 83

Density layer

The heat map shows where players have been most active on the pitch. Add a density layer and apply the following settings:

Data > Dimensions > Density
Field: Event_ID

Location
Latitude and longitude fields: On
Latitude: Location_X
Longitude: Location_Y

Options > Layer display
Calculation condition: =GETSELECTEDCOUNT(Heat_Map, 1)

Line layer

We will show passes here, with forward passes in green and backward in red for a quick visual split. Add a line layer and proceed with applying the settings below.

Data > Dimensions > Line
Field: Event_ID

Location > Start point
Latitude and longitude fields: On
Latitude: Location_X
Longitude: Location_Y

Location > End point
Latitude and longitude fields: On
Latitude: Pass_End_Location_X
Longitude: Pass_End_Location_Y

Width & Style
Arrow: Forward
Arrow position: 100

Colors
=IF(Pass_End_Location_X > Location_X, '#33D1C4', '#FF5A5F')

Options > Layer display
Calculation condition: =GETSELECTEDCOUNT(Pass_Map, 1)

Point layer

The point layer marks shooting locations, with goals highlighted in green.

Data > Dimensions > Point
Field: Event_ID

Location
Latitude and longitude fields: On
Latitude: Location_X
Longitude: Location_Y

Colors
Colors: By expression
Expression: =IF(Shot_Outcome_Name = 'Goal', '#33D1C4', '#FFE896')

Options > Layer display
Calculation condition: =GETSELECTEDCOUNT(Shot_Map, 1)

Conclusion

We have now transformed raw StatsBomb data into a dynamic, interactive dashboard in Qlik Sense. By setting up the data model, designing responsive navigation buttons, and layering the map with insightful visual elements, we have made it easy to explore player movements, passing patterns, and shot locations in-depth. Creating this dashboard has been a blast and I am already eyeing ways to take it further. Football data just has so much to offer. ⚽