Plotly Dash App
So far we have created a free, user-friendly data store and connected to it through the Google Python API.
Part 1 – Design and ETL Process using Google and code.gs
Next, we will use the data to build our dashboard for the field marketing team to track their activities and progress toward a bonus.

Build the Plotly Dash app
Dash is an open source tool from Plotly to allow data scientists and other front-end-ignorant folks like myself the opportunity to put together an interactive web app to show off their Plotly charts with just a few lines of python.
The docs on Plotly Dash are fantastic and get right to the point with great examples.
Dash Basics
Open a terminal and create a new environment for our project.
conda create -n <yourEnvironmentName>
conda activate <yourEnvironmentName>
conda install plotly dash pandas numpy flask
And from Part 1, we will need the Google API libraries:
conda install -c conda-forge google-api-python-client google-auth-httplib2 google-auth-oauthlib
Start a new project folder and create a file named app.py
. We’re ready to build our Dash app.
- [line 5] Start Flask
- [line 7–8] Create a Dash object with the server you just created
- [line 10–20] Use the layout method to add the components and styles to that Dash object.
- [line 23] Run server
That’s it. With those 4 core pieces, you now have a working app.
The core of Dash is that all of the visual components of the app are Python classes. There are specific libraries to import for the types of components you might use, such as the HTML library for the basic HTML items such as div and image, the user friendly Dash Core Components library, with classes for pre-built dropdowns, lists, buttons, graphs(!), and many other typical web components, and finally the Dash Data Table library to display and manipulate a large table of data on the page.
Run python app.py
from the working directory in your terminal.

If there are no errors you should see the above. This means your computer is now running the app. Open a browser and go to http://127.0.0.1:8050/ (or whatever the response is for you above). You’ll see the app running and displaying the <h2>
message from your layout. Also notice the blue circle that will appear in your browser in the lower right. This will be handy for debugging and following callbacks in the future.
Callbacks
Another very important step in understanding how our app will function is the callback. After we start Flask, create a Dash object, and design the layout our app can respond to changes such as selecting a value in a dropdown, clicking a button or sorting a table.
The basic structure of a callback in Dash looks like this:
@ app.callback(
Output(component_id='graph', component_property='figure'),
[Input(component_id='dropdown', component_property='value')]
)
def build_graph(selection):
The first arguement in our function is the first item in the
list of Inputs above. Name it as you like
Do something here with the input.
In this case it is the values from the dropdown.
return the property needed for the output
(in this case it is a plotly figure object)
Dash will now listen for any changes in our component named "dropdown". It will run the function connected to the callback when something has changed. Then return the output of the function to the component listed. Thus, updating the page with our selection.
Fast Forward
Plotly has incredible docs for it’s Dash app and visualization library. So, I’ll let you find the particular tools you would like to use and move ahead to discuss how we will connect our Google Sheet to be used in the Dashboard.
Our Build
First we need to add our two functions to get Google Data from Part 1 to our app.py
script. This will fetch the data from our Google Sheet and convert it into a Pandas DataFrame.
The Layout
Next we will build the layout of our Dash App. The idea of Dash is that it is a tool for folks who know very little about front-end development, React, or Javacript. There are two points I will highlight below for other beginners like myself.
- Dash Bootstrap Components
Bootstrap is popular CSS framework for responsive sites viewed on mobile and other screens.
In building my first few Dash Apps, I struggled to make adjustments to the layout. Simple tasks such as centering a piece of text or adding margins was difficult and rarely had the results I wanted.
Dash Bootstrap Components is third party library to incorporate bootstrap CSS into dash. The documentation is wonderful and I learned much of how the layout works from their visuals. Take a look:
https://dash-bootstrap-components.opensource.faculty.ai
The library adds Python classes for Containers, Rows and Columns to the layout of the page. Using this structure with your components will allow for the site to respond much better to other screens. For me the Python classes made it simple to adjust sizing and justification
Install Dash Bootstrap Components in your environment:
conda install -c condo-forge dash-bootstrap-components
2. Data Tables
Data Tables are a component of Dash for viewing, editing, and exploring large datasets. The tables allow for our app users to filter, sort and select data that can be directly inputed into our visualizations.
They are incredibly powerful, but finicky. Building tables, columns and headers is straight foward, but understanding how each style setting interacts with others can take some time to understand and cause unexpected layouts.
I had trouble with the fixed row headers matching the cells below, as well as certain CSS settings cutting off the left and right most pixels of the data.
First tip, is to understand the order of priority for all of the style settings:
- styledataconditional
- style_data
- stylefilterconditional
- style_filter
- styleheaderconditional
- style_header
- stylecellconditional
- style_cell
This means adjusting a setting like minWidth=60
to "style_data", will override any overlapping setting of maxWidth=50
in "style_cell".
The next tip I have when using a Dash Data Table is to build a separate file for all the style settings. In many examples and tutorials I found online, each column of data is added using a for loop, even some of the conditionally formatted columns and data. While it’s not the most efficient, using a separate file and building each column manually allowed me to debug, test, and adjust data quickly and easily. So, while learning to build Dash Apps with tables, it’s a good idea to be explicit. You can test and learn how to change data formats, colors, and columns widths. Here is the example I used with this dashboard:
Notice in the third list "bonus_data_cond", I can set a conditional style to check if our employees have exceed their bonus goals. The script then sets the background color accordingly.
I import all of these variables in our main script, app.py
, and assign them in the table layout above like so: style_cell_conditional=bonus_cell_cond
The Callbacks
Next we will add callbacks for each visualization and interactive component. We’re going to build:
- Responsive summary statistics
- An interactive map
- A data table with corresponding bar chart responding to data selections.
A Special Data Callback
We’ll start with something interesting that I did not find in many tutorials. While testing the app, commonly the data would not refresh when loading the page. Additionally, I found several sources which mention a best practice of creating a callback which stores the data to an html.Div()
as a string instead of letting the python script just store the data in a Pandas DataFrame as a global variable that each function could use. For this data store html.Div()
we will set style={'display':'none'}
But why?
This does a few things for us. First, it forces the page to update the data on each load. Secondly, each visual component will be built using the data stored in this hidden component. The API call and some of the more computationally expensive data transformation will happen just once. Changes to the visualizations happen quicker as the data is already clean an only needs to be filtered. Finally, I read this practice has a slightly security beenfit if the data is not intended to be seen or read.
So, during our first page load this function will be run by the hidden html.Div()
. The primary data transformation will happen here, dates converted and numbers stored as integers. Then 2 responsive Callbacks will use this clean data to filter for their purposes. All data is stored in string format inside a .Div()
component instead of in memory on the server. Fortunatly, this project will never work with very large data sets. If that is your scenario you should find a alternative that keeps the memory usage low.
I’m actually going to set up two of these data gathering Callbacks. The reason is to allow the Dashboard to independently set a time frame between the main map and the employee bonus table.
The Map Building Callback
Here we dive into some of Plotly‘s core visualization strengths. We input the data from our hidden data component and convert it from a string back to a Pandas DF for some manipulation before we return a scatterGeo figure to be rendered in the app layout above.
The Data Table Callback
Most of the tedious work setting up a Dash Data Table is done in the layout and styling, here we use Pandas to do some aggregations on each field marketing employee and return a data in string format to be read by the dash_table.DataTable() component in the layout.
The Bar Charts Callback
This is one of my favorite parts of many dashboard projects. Data Tables offer the flexibility of selecting rows, highlight, deleting, filtering. All of those adjustments to the table can be sent as input to resulting visualizations (or better… Machine Learning predictions!)
Why is this my favorite part? Because I like to give Dashboards as much flexibility as possible. The user may want to know the answer to a very specific question, "How many widgets were sold in the eastern region in April?" A good dashboard design gives the user that flexibility and Dash Data Tables do that inherently.
Here we will take input from selected rows in the above table and build 4 bar charts.
Important to highlight here that callbacks can not only take multiple inputs, but Outputs can also be set as a list and sent to multiple components.
The Summary Stats Callback
Nice and simple, this callback reports the clear metrics given the time frame set in our initial Date Picker component. Most business users want rapid cognition. This reports the key numbers, with lots of room.
Put It All Together
All the pieces above combined into one Dash App.
The Github repository below contains the core pieces above along with a few bonus maps, additional filters and a few images.
Conclusion
This was the big step that requires a lot of tedious trial and error in design, but is the place you can make your project stand out and add a lot of value to the users.
Part 3— Deploy to Heroku
[coming soon]
