Dynamically changing app icons
Zendesk apps in the nav bar and top bar locations display a related app icon. In this tutorial, you'll create a top bar app that dynamically updates its icon based on a changing integer. The integer represents a count of unread messages from a third-party API.
To change the icon, the app runs a background instance. This background instance accesses the app's top bar instance using the client.instance() method. This lets the app change the icon even when the top bar app is closed.
Note: Dynamic app icons are not supported in the ticket editor location because the iconSymbol
API used to create them is not supported in that location.
What you'll need
To complete this tutorial, you'll need the following:
-
A Zendesk account with the Zendesk Suite Growth plan or above, or the Support Professional plan or above. To get a free account for testing, see Getting a trial or sponsored account for development.
-
The Zendesk Command Line Interface (ZCLI). To install or upgrade ZCLI, see Installing and updating ZCLI.
ZCLI replaces the Zendesk Apps Tools (ZAT), which are in maintenance mode. To use ZAT instead, see Installing and using ZAT.
-
Familiarity with the Zendesk Apps framework (ZAF). Before you start, complete the Building your first Support app tutorial.
Creating the app files
First, create basic starter files for an app named Message Counter.
-
In your shell, navigate to the folder where you want to store the app. Example:
cd projects
-
In the folder, run:
zcli apps:new
-
At the prompts, enter the following values:
- Directory name: msg_counter
- Author's name: Your name
- Author's email: Your email address
- Author's website: Leave blank and press Enter.
- App name: Message Counter
ZCLI creates app starter files in the Message Counter folder.
Setting the app locations
Next, update the app to run in the top bar and background locations.
-
In the msg_counter folder, open manifest.json in your text editor.
-
Replace the
location
property with the following:...
"location": {
"support": {
"top_bar": {
"url": "assets/iframe.html"
},
"background": "assets/iframe.html"
}
},
...
-
Save manifest.json.
Adding the top bar icon
Top bar apps require an SVG app icon named icon_top_bar.svg. To add the app icon, right-click the following image link and save it to your computer as icon_top_bar.svg. Place the image in the msg_counter/assets folder.
How app icon changes work
The above icon_top_bar.svg file includes multiple icons as <symbol>
tags.
Each <symbol>
tag has a unique id
attribute.
<svg xmlns="http://www.w3.org/2000/svg">
<symbol id="default" viewBox="0 0 990 990" ...>
...
</symbol>
<symbol id="count-1" viewBox="0 0 990 990" ...>
...
</symbol>
...
</svg>
When a top bar app starts, it uses the symbol with the "default" id. To change the icon, you can use the top bar instance's ZAF client to set the iconSymbol property.
client.set("iconSymbol", "count-1")
Dynamically setting the top bar icon
Update your app to dynamically change its icon based on data.
For this tutorial, you'll use a JavaScript function to generate a random integer between 0–10 (inclusive). The integer represents a count of unread messages. In a production app, you could update the function to get similar data from a third-party API using the client.request() method.
-
In the app's assets folder, open iframe.html. Replace the
<script>
tag containingZAFClient.init()
with the following:<script type="text/javascript" src="main.js"></script>
-
In the assets folder, create a main.js file. Paste the following into the file:
const client = ZAFClient.init();
const POLL_INTERVAL_IN_MILLIS = 2000;
async function updateIconCount(delayInMillis) {
const count = await getCount();
if (count > 9) {
setTopBarIcon("count-9plus");
} else if (count === 0) {
setTopBarIcon("default");
} else {
setTopBarIcon(`count-${count}`);
}
await new Promise((resolve) => setTimeout(resolve, delayInMillis));
await updateIconCount(delayInMillis);
}
// In prod, update this function to call a
// third-party API using ZAF's client.request() method
async function getCount() {
// Returns a random integer between 0-10 (inclusive)
return Math.floor(Math.random() * 11);
}
async function setTopBarIcon(symbol) {
const topBar = await getTopBarInstance();
topBar.set("iconSymbol", symbol);
}
async function getTopBarInstance() {
const instancesData = await client.get("instances");
const instances = Object.values(instancesData.instances);
const topBar = instances.find((e) => e.location === "top_bar");
return client.instance(topBar.instanceGuid);
}
client.on("app.registered", (appData) => {
const location = appData.context.location;
if (location === "background") {
updateIconCount(POLL_INTERVAL_IN_MILLIS);
}
});
Most of the code only runs in the app's background instance. When the background instance loads, it generates a message count.
The background instance then uses the
client.instance()
method to access the top bar instance's ZAF client. The background instance uses this client to set theiconSymbol
property. This changes the icon to one that corresponds to the message count.Every two seconds, the background instance generates a new message count and updates the icon.
-
Save iframe.html and main.js.
Running the app locally
Run the app locally to ensure it changes the top bar icon every two seconds.
-
In your shell, navigate to the msg_counter folder. Example:
cd projects/msg_counter
-
Start a local ZCLI web server.
zcli apps:server
Note: To stop the server, press Ctrl+C.
-
In your browser's private or incognito window, sign in to Zendesk Support and go to the Agent Workspace. Append
?zcli_apps=true
to the URL. Example:https://{subdomain}.zendesk.com/agent/dashboard?zcli_apps=true
-
The top bar displays the app icon. The app automatically changes the icon every two seconds.
Next steps
Congratulations! You've created an app that dynamically updates its icon. As a next step, consider the following tasks:
- Change the app's
getCount()
function to call a third-party API using the client.request() method - Update the top bar app to display useful information from the API
- Add error handling for the app's async calls
- Upload and install the app as a private app in your Support instance