Digital Workplace, Intranets

Make Adaptive Cards for a SharePoint intranet (Updated Sep '22)

Newsletter robot
Enjoying the read?

Don't miss our next article

Adaptive Cards are a standardized "recipe" for writing a Card in Microsoft Teams or other Microsoft products. However, oddly SharePoint does not directly let you embed Adaptive Cards from within their UI.

In this tutorial, I will show you two ways to easily can define an Adaptive Card that looks great, displays the data you connect it to, and how you can embed it into your SharePoint Intranet.

"Quick" way: Display a Card with static or async content

If you just want to spruce up your SharePoint page with a nice Adaptive Card, or you have an Adaptive Card that gets updated only infrequently (quarterly list of events, monthly changing lunch menu, etc.) than this could be the best option for you.

Step 1: Make your Adaptive Card based off of a template

No matter what you're trying to design, you can probably start by grabbing one of these templates and pull them into the Adaptive Card designer.

The actual Adaptive Card Designer is split into three main areas that we will look at:

  1. The yellow area is a list of card elements that you can drag and drop into your template where all you see currently is Empty Container.

  2. In the turquoise area we have the Card Payload Editor which shows anything you add to your Adaptive Card. It is the "recipe" for your Card, formatted in JSON, which structurally describes your card's layout and content.

  3. Lastly, in the purple area, we have the Sample Data Editor where you will see what data this template uses to display the content. This sample data is embedded (or "bound") into the Adaptive Card payload and you can see this process by switching into Preview Mode.

Step 2: Embed the Adaptive Card into SharePoint

Once you're happy with your Adaptive Card, add this free Adaptive Card web part to your SharePoint and then select the web part on the page you want to insert your Adaptive Card.

Then just copy-and-paste your Card Payload and Sample Data into the respective fields in the configuration, and you're done.

"Correct" extended way: Instead of static data, switch to a live source

This is a tiny bit more involved. Anytime you want to show users their current holiday allowance, the current list of requests, the current online meeting for the day, then the quick way won't work for you. Basically what you're missing is a connection to an API from an outside app (say Salesforce, ServiceNow, etc.) that then gets projected into your Adaptive Card every time the user visits your page. That's what this approach takes cares of:

Step 1: Adaptive Card design

You can either stay with whatever design your created for the "quick" way, or you can make an Adaptive Card from scratch.

Add an empty Adaptive Card

As another example, let's say we're making a simple list that shows us the contacts from our Hubspot list. We would like the end result to look similar to this:

Example mockup of an Adaptive Card design for Digital AssistantTo build this card we start designing the first row (or entry) of our list. We have a name, company name, as well as a direct email button. Clicking on the list entry should open our contact in a new tab.

So to start we need to drag into our Card a column, images, and text blocks that match the layout of our mockup.

Notice, how the Card Payload Editor changes as you drag each card element into your framework.

It's a little finicky, but once you added in your text columns, button (ActionSet), texts and icons your card preview should look something like this:

Preview of an example Adaptive Card built with the Adaptive Card designer, based on the mockup

Here's the code shown in the payload editor:

{
"type": "AdaptiveCard",
"body": [
{
"type": "Container",
"bleed": true,
"items": [
{
"type": "ColumnSet",
"$data": "${$root.contacts}",
"columns": [
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "${properties.firstname.value} ${properties.lastname.value}",
"size": "Medium",
"weight": "Bolder"
},
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"width": "20px",
"items": [
{
"type": "Image",
"url": "<your-icon-url>",
"size": "Stretch"
}
],
"spacing": "None"
},
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "${properties.company.value}",
"fontType": "Default",
"size": "Small",
"weight": "Bolder"
}
],
"spacing": "Small",
"verticalContentAlignment": "Center"
}
],
"spacing": "None"
}
]
},
{
"type": "Column",
"width": "auto",
"items": [
{
"type": "ActionSet",
"actions": [
{
"type": "Action.OpenUrl",
"title": "Message",
"style": "positive",
"iconUrl": "<your-icon-url>",
"url": "${profile-url}?interaction=email"
}
]
}
],
"verticalContentAlignment": "Center"
}
],
"selectAction": {
"type": "Action.OpenUrl",
"url": "${profile-url}?"
},
"separator": true
}
],
"spacing": "None",
"backgroundImage": {},
"separator": true
},
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"width": "17px",
"items": [
{
"type": "Image",
"url": "https://logo.clearbit.com/hubspot.com",
"size": "Stretch"
}
],
"spacing": "None"
},
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "Open Hubspot app"
}
],
"backgroundImage": {
"verticalAlignment": "Center"
},
"spacing": "Small"
}
],
"separator": true,
"selectAction": {
"type": "Action.OpenUrl",
"url": "https://app.hubspot.com/"
}
}
],
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.2"
}

Step 2: Data binding with the target app

We now have a Card that shows a single lead, but we want the Designer to repeat this list item for each contact in our data. This is called "looping" or "iterating". And to start this process we first need to fill in some sample data into our design. (For now some sample data will suffice, but further down we'll set up a live feed as well.)

You will have to do your own research and start digging for an API endpoint documentation from the application you get your data from. In the case of Hubspot it would be the Lists endpoint. For our Card we want to get a sample readout of my own Hubspot account, so we will use a tool like Postman which can request this from the Hubspot API.

Once you have your sample data, paste it into the Sample Data Editor section.

Editor's tip:
If Postman isn't your thing, or you simply can't get easy access to the API, you could also use the sample response shown on the API docs website, although these are sometimes shortened for brevity.

Now we can bind to this data in our ColumnSet. We do this simply by adding the following code to line 10: "$data": "${$root.contacts}",

Example payload editor/sample data editor panes showing how data binding works

This tells the designer to show such a ColumnSet for each entry in the "contacts" array of our sample data JSON.

You know this worked successfully, when you click on Preview Mode and the entries suddenly multiply by however many items are in your API sample. If it didn't work, check out the docs for templating and see if you can debug your Card payload.

Finally, now we can bind the actual data from the sample response we copied to our design.

First we navigate to the the element where we want to show the name and we enter ${properties.firstname.value} ${properties.firstname.value}:

This tells the Card designer to look for the correct entry in the JSON by navigating through the "tree" and delving deeper into every branch denoted with a . in the binding command.

In our example the API's root is already set to the contacts array (defined in line 10), so to get to the first name of each contact the Card Designer needs to:

  • Go to the properties array

  • Within there, find the firstname object

  • Read out the value nested within

We follow the same logic for the last name, and the company name below that.

If everything worked, your Card should now show each contact separately.

Just for completeness' sake, you can find the finished Card payload code below:

{
"type": "AdaptiveCard",
"body": [
{
"type": "Container",
"bleed": true,
"items": [
{
"type": "ColumnSet",
"$data": "${$root.contacts}",
"columns": [
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "${properties.firstname.value} ${properties.lastname.value}",
"size": "Medium",
"weight": "Bolder"
},
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"width": "20px",
"items": [
{
"type": "Image",
"url": "<your-icon-url>",
"size": "Stretch"
}
],
"spacing": "None"
},
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "${properties.company.value}",
"fontType": "Default",
"size": "Small",
"weight": "Bolder"
}
],
"spacing": "Small",
"verticalContentAlignment": "Center"
}
],
"spacing": "None"
}
]
},
{
"type": "Column",
"width": "auto",
"items": [
{
"type": "ActionSet",
"actions": [
{
"type": "Action.OpenUrl",
"title": "Message",
"style": "positive",
"iconUrl": "<your-icon-url>",
"url": "${profile-url}?interaction=email"
}
]
}
],
"verticalContentAlignment": "Center"
}
],
"selectAction": {
"type": "Action.OpenUrl",
"url": "${profile-url}?"
},
"separator": true
}
],
"spacing": "None",
"backgroundImage": {},
"separator": true
},
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"width": "17px",
"items": [
{
"type": "Image",
"url": "https://logo.clearbit.com/hubspot.com",
"size": "Stretch"
}
],
"spacing": "None"
},
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "Open Hubspot app"
}
],
"backgroundImage": {
"verticalAlignment": "Center"
},
"spacing": "Small"
}
],
"separator": true,
"selectAction": {
"type": "Action.OpenUrl",
"url": "https://app.hubspot.com/"
}
}
],
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.2"
}

Step 3: Replace sample data with real data

Cool, so we've got the Card working using our sample obtained from the API. How do we get a live feed set up?

Just go over to the App Directory page and look for the application you're trying to connect to. In this case for Hubspot just hit Install now which will redirect you to link the Digital Assistant (so the Adaptive Card) with your Hubspot account.

Some apps (including Hubspot) have also got built-in Cards that get installed as part of the authorization process. But you can just ignore these and return back to the Adaptive Card design you still have open.

Editor's tip:
If your project uses an app not listed in that Directory you can also use a free Postman template that lets you connect with any API.

Back in the Designer hit Save and then refresh the Designer. Now you can click on Connect to data source and select Hubspot from your dropdown list.

Once you save that, you may be prompted to carry out the account linking.

Having selected this Connector, it will now replace the content in the Sample Data Editor section that we put in manually, with live data coming from your Connector.

To double check if all the data-binding is still valid, please toggle to the Preview Mode one more time and fix anything that may not be working as intended.

Seeing the finished Card toggling between Preview and Edit mode

Completed example Adaptive Card for Digital Assistant showing lead data from HubspotAnd that's it. You're Card is ready to roll. 👍😎

Step 4: Embed the Card into SharePoint

The last step is to add our Card to an existing SharePoint site. We need to install a free companion Webpart in SharePoint for this.

Adding the Digital Assistant SharePoint webpart to a SharePoint modern team siteOnce it is installed, you should be able to add it to your SharePoint site.

Configuring the Digital Assistant SharePoint webpartThe Webpart will simply require the Card URL to work, which you can get from the Share dialog in the Adaptive Card Designer.

That's it. Your Card is working, if you need make slight layout changes just go back to your Card Designer and make the changes you want, and they'll be live as soon as you hit Save (the link won't need to be changed).

~~~

Did you find this tutorial useful? Anything not clear? Let me know in the comments below.

Author portrait

Article by Henry Amm

I’m the Senior Director for the Digital Assistant Platform. Prevously gained 6 years of experience as an Intranet consultant. Fluent in German.

Make your Assistant Build your free AI-powered Digital Workplace platform in minutes, with our free forever plan. Digital Assistant logo Yes please
Author portrait

Article by: Henry Amm

I’m the Senior Director for the Digital Assistant Platform. Prevously gained 6 years of experience as an Intranet consultant. Fluent in German.

Join the discussion

Avatar placeholder
This field is required.
This field is required.
This field is required.

0 responses

Be the first to leave a comment!