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. ⚽