Skip to content

Advanced Dynamic Content

In this section we'll cover how to implement dynamic content in your Apps without requiring that data to be stored in fields on your Jira Issues or Projects.

The primary use-case we'll focus on here is wanting to display some data from an external system (e.g. your CRM) inside an App you've built for your Atlassian product.

We're not going to go through a full step-by-step walkthrough here because there is a thousand different ways you could implement this functionality, but we'll go over the high-level workflow, and give you some suggestions on ways to implement it.

Heads Up:

The topics covered in this section are going to be a little bit more technically advanced.

We recommend you have some experience with basic coding concepts, especially around APIs and JSON, before diving into this section.

Core Workflow

The first thing you need to do when implementing this functionality is reverse the order you would normally think about this kind of solution.

The way an App or front-end widget would normally work is that it would make a request to an API to get the data it needs, and then display that data in the product.

This is nice and simple, but it has a range of issues that make it not ideal for the kind of use-case that we're dealing with here:

  • Security: You don't want to expose your internal tool's API to the public internet (especially if that tool is behind a firewall),
    • Instead, you really want those internal systems to be in control of data sharing, and be the one's initiating the sharing process. For example, by pushing data OUT of your internal systems when it changes, rather than having an external system PULL it in.
  • Performance & Load: If you have a lot of users, and they're all making requests to your internal systems every time they open a Jira issue, you're going to put a lot of load on those systems.
    • Instead, you want to be able to cache data, and only update it when it changes, rather than having to re-fetch it every time a user loads the page.

App Maker is built to solve these problems by allowing you to PUSH data into your Apps, rather than having your Apps PULL data from your internal systems.

Automated UI Updates

You'll have noticed that the way you create and update Apps using App Maker is by making API calls to the UI Update endpoint.

This is a very deliberate design decision, as it makes it possible for your App's content to not just be updated manually by a human, but also by other automations or systems via API.

This workflow is achievable by configuring another system to fire a Webhook whenever a change occurs that you want to be reflected in your App, and then using the data from that webhook to update the content of your App via the JSON sent to the UI Update API.

Automated Component Update

It's important to note that this workflow requires some kind of tool to sit between the system sending the webhook data and your App Maker UI Update API, in order to translate the data coming from the external system into the JSON structure that App Maker expects.

App Maker supports other Advanced Dynamic Content techniques that do not require this intermediate step, which we'll cover in the Custom Data and Webhook Transforms sections.

Example Workflow:

  • The simplest way to achieve this using tools already available to you would be to use a Jira Automation workflow with a Webhook Trigger and a Web Request action.
  • You can configure your internal system to send the updated data to the Jira Automation workflow as via a webhook, then have the Jira Automation workflow translate the parts of that update you care about into the JSON structure that App Maker expects to update the UI, then send that JSON to the UI Update API.
  • One of the advantages of using Jira Automation like this is that you can leverage all the existing integrations and triggers supported by Jira Automation to get the data you need any time it updates, and use that data to update your Apps inside your Atlassian product.

Note:

A fully worked example tutorial for this process is coming soon!


TIP

If you are comfortable writing some code yourself, you could also write a small tool using something like Cloudflare Workers or Netlify Functions that listens for the Webhook from your internal system, translates the data into the JSON structure that App Maker expects, and then sends that JSON to the UI Update API.

However, this is a much more complex solution and misses out on all the integrations and triggers available with Jira Automation, so we recommend using the Jira Automation option wherever it can meet your needs.

Custom Data

Custom Data allows you to send and store arbitrary data in the context of your Apps, and then use that data in your Apps using the templating tools covered in Basic Dynamic Content.

Custom Data works similar to the UI Update API, but will allow you to send arbitrary data to a URL provided by App Maker and store that data in the context of your Apps.

This allows you to significantly simplify your Apps using dynamic content, as you can now use a single standardised set of UI "Templates", and then just update the data that's displayed in those templates using Custom Context Data.

This will make it easier to build Apps that display data from external systems, as your intermediate "translation" step will only need to translate the raw data and store it in App Maker, rather than having to template it into the full Component JSON structure that App Maker expects.

Example Workflow:

  • We're going to extend the example from Basic Dynamic Content, but we're going to tweak it a bit to provide a more realistic use-case.
  • The use-case we're going to cover is displaying a live "System Status" widget in your Jira Issue Context Panel, that shows the current status of your internal systems.
    • For the purpose of this example, you will be playing the part of your system-status monitoring system (e.g StatusPage), and you'll be pushing the current status of your systems into Custom Data stored in App Maker.

Creating the System Status UI Widget

  • First, in your API client, update the value of the top level fields and "componentData" section to the object below:
    • This will give us a nice "System Status" widget that we can populate data in to.
json
{
  "resourceType": "site",
  "module": "jira:issueContext",
  "title": "system-status-widget",
  "action": "set",
  "componentData": {
    "type": "StackedInformationGroup",
    "title": "System Status",
    "children": [
      ...
    ]
  }
}

Custom Data Templating

  • Next, we need to update the UI Component to allow us to template Custom Data stored in App Maker - for the example we're going to be showing the status of the Website and API services.
  • Update the first "FieldValue" under "children" to the value below.
    • We're telling the UI to access some data stored under the site.system-status context here, which we'll be creating in the next step.
json
{
  "type": "FieldValue",
  "key": "Website",
  "value": "{{customData.site.system-status.website}}"
}
  • Now update the second FieldValue to the value below:
json
{
  "type": "FieldValue",
  "key": "API",
  "value": "{{customData.site.system-status.api}}"
}

Final UI Component JSON

  • Your final JSON should look something like this:
  • Hit "Send" to update the UI Component in App Maker, if you open up Jira you'll see the widget is created, but nothing is populated into the fields because we haven't set the Custom Data yet.
json
{
  "resourceType": "site",
  "module": "jira:issueContext",
  "title": "system-status-widget",
  "action": "set",
  "componentData": {
    "type": "StackedInformationGroup",
    "title": "System Status",
    "children": [
      {
        "type": "FieldValue",
        "key": "Website",
        "value": "{{customData.site.system-status.website}}"
      },
      {
        "type": "FieldValue",
        "key": "API",
        "value": "{{customData.site.system-status.api}}"
      }
    ]
  }
}

Empty System Status Widget


Updating the System Status Custom Data

  • Now we need to update the Custom Data in App Maker to store the current status of our systems.
  • In Jira, head back to the App Admin page by clicking on the cog icon in the top-right of the screen, then selecting "Apps", and then "App Maker".
  • On the "App Maker" tab, you'll see a field labelled "Update Custom Data URL", copy that URL and save it for later.
  • Head back to your API client and create a new POST request, with the URL you just copied.
  • The top level of the request object will look very similar to the UI Update API:
    • There is an "action": field, which should be set to "set".
    • A "resourceType": field, which should be set to "site".
    • And a "title": field, which should be set to "system-status".

TIP

Notice that the values for the "resourceType" and "title" fields match the first two values under customData from our UI Component JSON (customData.site.system-status)?

  • This is how you tell App Maker where to store/find the data you're sending in the Custom Data API.
  • We'll go into more detail on all the different ways of storing data in the following sections.
json
{
  "action": "set",
  "resourceType": "site",
  "title": "system-status",
  ...
}
  • Now, create another field labelled "customData" and set its values as per the object below:
json
{
  "action": "set",
  "resourceType": "site",
  "title": "system-status",
  "customData": {
    "website": "Online",
    "api": "Offline"
  }
}
  • Hit "Send" to update the Custom Data in App Maker, and then head back to Jira and refresh the page.
  • You should now see your "System Status" widget displaying the values you set via the Custom Data API.

System Status Widget Offline

  • Now go back to your API client, update the "api": value to "Online", and hit "Send" again, then refresh the page in Jira.
    • You should see that your widget has already updated, and the "API" status is now showing as "Online".

System Status Widget Online

Custom Data In-Depth

  • Just like for UI Updates - setting the "action": to "set" will update the Custom Data and setting it to "delete" will remove the Custom Data.
  • Custom Data can be stored and scoped at different levels within your Jira site.
    • You can scope data to the "site", "project", or "issue" level, and you can store multiple pieces of data at each level by using different "title": values.
      • Within a given "resourceType": each piece of data must be stored under a unique "title":.
      • Note that "project" and "issue" scoped data also needs a "resourceKey": field to set which resource the data is scoped to.
      • The "title": property only needs to be unique within the context of a specific "project" or "issue".
    • When a UI Component is displayed and the Custom Data templated into it, App Maker will automatically inject the correct data based on the "project" or "issue" context the UI Component is being displayed in.
      • For example, Custom Data stored with a "resourceType": of "project" and a "resourceKey": of "ABC" will only be available to a UI Component displayed in the context of a Jira Project with the key "ABC".

Scoped Data Example

TIP

Note that even though the UI Component has a "resourceType" of "site" it will still be able to access Custom Data stored at the "project" and "issue" levels, as long as the UI Component is being displayed in the context of the correct Jira project/issue.

This allows you to use a single "Site-level" UI Component and dynamically template different data into it based on the Project or Issue it's being rendered inside of.

json
// Custom Data
{
  "action": "set",
  "resourceType": "project",
  "resourceKey": "ABC",
  "title": "project-system-status",
  "customData": {
    "message": "I will only be accessible by UI components in the context of project ABC",
  }
}
json
// UI Component
{
  "resourceType": "site",
  "module": "jira:issueContext",
  "title": "system-status-widget",
  "action": "set",
  "componentData": {
    "type": "StackedInformationGroup",
    "title": "Test Info Group",
    "children": [
      {
        "type": "FieldValue",
        "key": "Message",
        "value": "{{customData.project.project-system-status.message}}"
      }
    ]
  }
}