In any organization, gathering feedback from customers and employees is essential to improve products and services, as well as to enhance the overall experience. However, obtaining that feedback can be a challenging task, especially when you need to reach out to a large number of people.
Fortunately, with the rise of digital communication tools and collaborative apps, it's becoming easier than ever to gather feedback efficiently and in a timely manner. Among these apps, Microsoft Teams stands out as one of the most popular and versatile options, providing a unified platform for team communication and collaboration.
In this post, we'll explore how you can leverage Microsoft Teams to gather feedback from your customers or employees via surveys sent as Adaptive Cards, using ServiceNow as the source of information. Specifically, we'll discuss how to set up an automated process that sends Adaptive Cards to Microsoft Teams after a ticket is closed on ServiceNow, making it easy for respondents to provide feedback directly from Teams. By doing so, you'll not only save time and effort but also increase the response rate and improve the quality of the feedback you receive.
ServiceNow provides a free development environment called the Now Platform (https://developer.servicenow.com/dev.do), which enables developers to quickly build, test, and deploy applications to improve workflows and productivity within their organizations. With a free account on the Now Platform, you can start building powerful applications that leverage ServiceNow's advanced capabilities for workflow management, incident management, and service requests. Whether you're an experienced developer or just getting started, the Now Platform offers a flexible and easy-to-use environment for creating custom solutions tailored to your organization's unique needs.
Go to the Microsoft Teams website (https://www.microsoft.com/en-us/microsoft-teams/group-chat-software) and click on the "Sign up for free" button.
Enter your email address and click on "Next". If you already have a Microsoft account, you can sign in with that account.
Create a new password and click on "Sign up".
Follow the prompts to complete the setup process, such as entering your name and company information.
Once your account is set up, you can download the Microsoft Teams app on your desktop or mobile device and start collaborating with your team.
With a free Microsoft Teams account, you can chat with colleagues, make voice and video calls, share files, and collaborate on projects from anywhere. Plus, with its seamless integration with other Microsoft products, such as Office 365 and SharePoint, Microsoft Teams can help streamline your organization's workflows and improve productivity.
Microsoft provides a free Power Automate environment (https://powerautomate.microsoft.com/en-us/#home-signup), which enables users to automate workflows across multiple applications and services. With Power Automate, you can create automated processes, such as approvals, notifications, and data synchronization, to save time and increase efficiency. Whether you're a business user or a developer, the Power Automate environment provides an intuitive and easy-to-use interface for creating and managing workflows. Plus, with its seamless integration with other Microsoft products, such as Teams and SharePoint, Power Automate can help streamline your organization's workflows and improve collaboration.
To automate the process of sending Adaptive Cards to Microsoft Teams after a ServiceNow ticket is closed, you can use either Power Automate or Azure Logic Apps. With these tools, you can create a flow that retrieves the necessary information from ServiceNow and then prepares and sends the Adaptive Card to Teams.
In this post, I am demonstrating how to use Power Automate to automate the process of sending Adaptive Cards to Microsoft Teams after closing a ServiceNow ticket. However, the process is similar if you decide to use Azure Logic Apps instead, so feel free to choose the tool that best suits your needs and preferences.
It's worth noting that this solution utilizes Microsoft 365 seeded licenses and standard connectors, which makes it a cost-effective option for organizations looking to streamline their feedback process. Power Automate and Azure Logic Apps provide a range of pre-built connectors and templates that allow you to easily connect different apps and automate workflows, without the need for extensive coding or development work.
By leveraging these tools, you can reduce manual effort and errors, improve collaboration and communication across teams, and gain valuable insights into the needs and preferences of your users. And with the use of seeded licenses and standard connectors, you can achieve all of this at a minimal cost, making it an ideal option for small and medium-sized businesses.
Open a web browser and go to the Power Automate portal.
Sign into Power Automate using your Microsoft account or organizational account.
Once you're signed in, you should see the Power Automate portal dashboard. On the left-hand menu, click on "Create" to create a new flow.
Choose a template from the available options or start from scratch by selecting "Instant - from blank".
HTTP triggers are a powerful feature in Power Automate that allows us to create custom APIs and automate processes with external systems. By creating a custom HTTP trigger, we can make the approval process more flexible and scalable, and enable other systems to interact with Microsoft Teams Approvals without having to go through ServiceNow.
To set up the "When a HTTP request is received" trigger, we need to define the input parameters that will be sent via a rule from ServiceNow (we will create this rule later).
{
"type": "object",
"properties": {
"number": {
"type": "string"
},
"short_description": {
"type": "string"
},
"description": {
"type": "string"
},
"resolved_by_name": {
"type": "string"
},
"resolved_by_email": {
"type": "string"
},
"state": {
"type": "string"
},
"closed_at": {
"type": "string"
},
"opened_by_name": {
"type": "string"
},
"opened_by_email": {
"type": "string"
},
"closed_by_name": {
"type": "string"
},
"closed_by_email": {
"type": "string"
},
"opened_at": {
"type": "string"
},
"resolved_at": {
"type": "string"
}
}
}
The next step is sending the adaptive card to Teams.
Select Chat with Flow bot for the Post in type field.
Copy and paste the following JSON code into the message field to create the Adaptive Card:
{
"type": "AdaptiveCard",
"body": [
{
"type": "ColumnSet",
"horizontalAlignment": "Center",
"columns": [
{
"type": "Column",
"items": [
{
"type": "TextBlock",
"text": "@{triggerBody()?['number']}",
"wrap": true,
"horizontalAlignment": "Left",
"weight": "Bolder",
"size": "Large"
},
{
"type": "TextBlock",
"spacing": "None",
"text": "@{triggerBody()?['short_description']}",
"wrap": true,
"size": "Large",
"horizontalAlignment": "Left"
},
{
"type": "TextBlock",
"text": "@{triggerBody()?['description']}",
"wrap": true,
"spacing": "Medium",
"horizontalAlignment": "Left"
}
],
"width": "stretch"
}
],
"width": 1
},
{
"type": "ColumnSet",
"horizontalAlignment": "Center",
"columns": [
{
"type": "Column",
"items": [
{
"type": "ColumnSet",
"horizontalAlignment": "Center",
"columns": [
{
"type": "Column",
"items": [
{
"type": "Image",
"url": "https://adaptivecards.io/content/LocationGreen_A.png",
"altText": "Location A"
}
],
"width": "auto"
},
{
"type": "Column",
"items": [
{
"type": "TextBlock",
"text": "**Opened at**",
"wrap": true
},
{
"type": "TextBlock",
"spacing": "None",
"text": "@{formatDateTime(triggerBody()?['opened_at'], 'yyyy-MM-dd')}",
"wrap": true,
"horizontalAlignment": "Center"
}
],
"width": "auto"
}
]
}
],
"width": 1
},
{
"type": "Column",
"spacing": "Large",
"separator": true,
"items": [
{
"type": "ColumnSet",
"horizontalAlignment": "Center",
"columns": [
{
"type": "Column",
"items": [
{
"type": "Image",
"url": "https://messagecardplayground.azurewebsites.net/assets/LocationBlue_B.png",
"altText": "Location B"
}
],
"width": "auto"
},
{
"type": "Column",
"items": [
{
"type": "TextBlock",
"text": "**Resolved at**",
"wrap": true
},
{
"type": "TextBlock",
"spacing": "None",
"text": "@{formatDateTime(triggerBody()?['resolved_at'], 'yyyy-MM-dd')}",
"wrap": true,
"horizontalAlignment": "Center"
}
],
"width": "auto"
}
]
}
],
"width": 1
},
{
"type": "Column",
"spacing": "Large",
"separator": true,
"items": [
{
"type": "ColumnSet",
"horizontalAlignment": "Center",
"columns": [
{
"type": "Column",
"items": [
{
"type": "Image",
"url": "https://messagecardplayground.azurewebsites.net/assets/LocationRed_C.png",
"altText": "Location C"
}
],
"width": "auto"
},
{
"type": "Column",
"items": [
{
"type": "TextBlock",
"text": "**Closed at**",
"wrap": true
},
{
"type": "TextBlock",
"spacing": "None",
"text": "@{formatDateTime(triggerBody()?['closed_at'], 'yyyy-MM-dd')}",
"wrap": true
}
],
"width": "auto"
}
]
}
],
"width": 1
}
],
"spacing": "Medium"
},
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"items": [
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"items": [
{
"type": "Image",
"horizontalAlignment": "Left",
"url": "https://messagecardplayground.azurewebsites.net/assets/clock.png",
"altText": "Calendar conflict",
"width": "15px",
"height": "15px"
}
],
"width": "auto"
},
{
"type": "Column",
"spacing": "None",
"items": [
{
"type": "TextBlock",
"text": "@{formatDateTime(triggerBody()?['opened_at'], 'HH:MM')}",
"wrap": true,
"spacing": "None",
"horizontalAlignment": "Center"
}
],
"width": "stretch"
}
]
}
],
"width": "80px",
"verticalContentAlignment": "Center"
},
{
"type": "Column",
"backgroundImage": {
"url": "https://messagecardplayground.azurewebsites.net/assets/SmallVerticalLineGray.png",
"fillMode": "RepeatVertically",
"horizontalAlignment": "Center"
},
"items": [
{
"type": "Image",
"horizontalAlignment": "Center",
"url": "https://adaptivecards.io/content/LocationGreen_A.png",
"altText": "Opened by"
}
],
"width": "auto",
"spacing": "None"
},
{
"type": "Column",
"items": [
{
"type": "TextBlock",
"text": "**@{triggerBody()?['opened_by_name']}**",
"wrap": true
},
{
"type": "ColumnSet",
"spacing": "None",
"columns": [
{
"type": "Column",
"items": [
{
"type": "TextBlock",
"text": "@{triggerBody()?['opened_by_email']}",
"wrap": true,
"spacing": "None"
}
],
"width": "stretch"
}
]
}
],
"width": 40
}
],
"separator": true,
"spacing": "Medium"
},
{
"type": "ColumnSet",
"spacing": "None",
"columns": [
{
"type": "Column",
"items": [
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"items": [
{
"type": "Image",
"horizontalAlignment": "Left",
"url": "https://messagecardplayground.azurewebsites.net/assets/clock.png",
"altText": "Calendar conflict",
"width": "15px",
"height": "15px"
}
],
"width": "auto"
},
{
"type": "Column",
"spacing": "None",
"items": [
{
"type": "TextBlock",
"text": "@{formatDateTime(triggerBody()?['resolved_at'], 'HH:MM')}",
"wrap": true,
"spacing": "None",
"horizontalAlignment": "Center"
}
],
"width": "stretch"
}
]
}
],
"width": "80px",
"verticalContentAlignment": "Center"
},
{
"type": "Column",
"backgroundImage": {
"url": "https://messagecardplayground.azurewebsites.net/assets/SmallVerticalLineGray.png",
"fillMode": "RepeatVertically",
"horizontalAlignment": "Center"
},
"items": [
{
"type": "Image",
"horizontalAlignment": "Center",
"url": "https://messagecardplayground.azurewebsites.net/assets/LocationBlue_B.png",
"altText": "Location B: Flight"
}
],
"width": "auto",
"spacing": "None"
},
{
"type": "Column",
"items": [
{
"type": "TextBlock",
"text": "**@{triggerBody()?['resolved_by_name']}**",
"wrap": true
},
{
"type": "ColumnSet",
"spacing": "None",
"columns": [
{
"type": "Column",
"items": [
{
"type": "TextBlock",
"text": "@{triggerBody()?['resolved_by_email']}",
"wrap": true
}
],
"width": "stretch"
}
]
}
],
"width": 40
}
]
},
{
"type": "ColumnSet",
"spacing": "None",
"columns": [
{
"type": "Column",
"items": [
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"items": [
{
"type": "Image",
"horizontalAlignment": "Left",
"url": "https://messagecardplayground.azurewebsites.net/assets/clock.png",
"altText": "Calendar conflict",
"width": "15px",
"height": "15px"
}
],
"width": "auto"
},
{
"type": "Column",
"spacing": "None",
"items": [
{
"type": "TextBlock",
"text": "@{formatDateTime(triggerBody()?['closed_at'], 'HH:MM')}",
"wrap": true,
"spacing": "None",
"horizontalAlignment": "Center"
}
],
"width": "stretch"
}
]
}
],
"width": "80px",
"verticalContentAlignment": "Center"
},
{
"type": "Column",
"backgroundImage": {
"url": "https://messagecardplayground.azurewebsites.net/assets/SmallVerticalLineGray.png",
"fillMode": "RepeatVertically",
"horizontalAlignment": "Center"
},
"items": [
{
"type": "Image",
"horizontalAlignment": "Center",
"url": "https://messagecardplayground.azurewebsites.net/assets/LocationRed_C.png",
"altText": "Location B: Flight"
}
],
"width": "auto",
"spacing": "None"
},
{
"type": "Column",
"items": [
{
"type": "TextBlock",
"text": "**@{triggerBody()?['closed_by_name']}**",
"wrap": true
},
{
"type": "ColumnSet",
"spacing": "None",
"columns": [
{
"type": "Column",
"items": [
{
"type": "TextBlock",
"text": "@{triggerBody()?['closed_by_email']}",
"wrap": true
}
],
"width": "stretch"
}
]
}
],
"width": 40
}
]
},
{
"type": "TextBlock",
"text": "Rate your experience!",
"weight": "Bolder",
"color": "Accent",
"size": "Medium",
"spacing": "Medium"
},
{
"type": "TextBlock",
"text": "Please rate your experience! Your feedback is very appreciated and will help improve your experience in the future. ",
"wrap": true
},
{
"type": "Input.Text",
"placeholder": "Add a comment",
"isMultiline": true,
"id": "comment"
},
{
"type": "Input.ChoiceSet",
"choices": [
{
"title": "Terrible",
"value": "Terrible"
},
{
"title": "Poor",
"value": "Poor"
},
{
"title": "Fair",
"value": "Fair"
},
{
"title": "Good",
"value": "Good"
},
{
"title": "Excellent",
"value": "Excellent"
}
],
"placeholder": "Placeholder text",
"isRequired": true,
"id": "rating"
},
{
"type": "ActionSet",
"actions": [
{
"type": "Action.Submit",
"title": "Submit"
}
]
}
],
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.4",
"msTeams": {
"width": "full"
}
}
The above Adaptive Card was generated using the Adaptive Cards Designer tool (https://adaptivecards.io/designer), which allows you to create visually appealing and functional cards without the need for coding. The card was designed using the following sample data JSON.
"number": "INC0000060",
"short_description": "Unable to connect to email",
"description": "I am unable to connect to the email server. It appears to be down.",
"resolved_by_name": "user 1",
"resolved_by_email": "user@sample.com",
"state": "",
"closed_at": "2016-12-14 02:46:44",
"opened_by_name": "user 2",
"opened_by_email": "user2@sample.com",
"opened_at": "2016-12-12 15:19:57",
"resolved_at":"2016-12-13 21:43:14",
"closed_by_name": "user 3",
"closed_by_email": "user3@sample.com"
}
{
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"comment": {
"type": "string"
},
"rating": {
"type": "string"
}
}
}
}
}
Next, you'll want to save the survey results returned from Microsoft Teams in a SharePoint List for further analysis and processing. To do so, follow the steps outlined below.
If you're interested in taking the feedback process to the next level, you might want to check out the post How to track the user experience of your Bot with Azure, Power BI and Microsoft Teams, that was written by Alexis Kinzelin (Cloud Solution Architect at Microsoft). In this post, Alexis shows you how to create a Power BI dashboard from the data stored on the SharePoint List, allowing you to easily visualize and analyze the feedback data and gain valuable insights into the performance and user experience of your Bot.
By integrating Power BI with Azure and Microsoft Teams, you can create a seamless end-to-end feedback process that allows you to collect, analyze, and act on feedback from your users in a timely and efficient manner. So be sure to check out our post and take your feedback process to the next level!
In the search box, type "SharePoint" and select the Create item action.
Select the appropriate SharePoint Site, List, and Folder where you want to create the new item.
Note that when you save your trigger, you will be given a URL that you can use to invoke the trigger from external systems.
Business Rules are server-side logic that execute when database records are queried, updated, inserted, or deleted. For more details, please check the Service Now Business Rules documentation.
To configure a ServiceNow Business Rule that triggers a request to Microsoft Power Automate when an incident is closed, follow the steps outlined below:
Give the business rule a name and description that accurately describes its purpose. For example, Incident Closed Survey.
Choose the table to which the business rule applies. This can be done by selecting the table from the drop-down menu in the "Applies to" field. For example, Incident [incident].
Specify the conditions that must be met for the business rule to run. This is done by adding conditions to the "When to run" section of the business rule. For example, you could specify that the rule should run after a new record is created or updated.
Add a filter condition to consider only closed tickets (state is closed).
It's important to note that creating a business rule in ServiceNow requires some knowledge of JavaScript and the ServiceNow platform. If you're not familiar with these concepts, it may be helpful to seek assistance from a ServiceNow administrator or developer.
Add the following code:
(function executeRule(current, previous /*null when async*/) {
gs.info("Incident Survey rule is running");
var snowURL = "https://dev78230.service-now.com/";
var number = current.getValue("number");
var shortDescription = current.getValue("short_description");
var description = current.getValue("description");
var stateId = current.getValue("state");
var openedAt = current.getValue("opened_at");
var resolvedAt = current.getValue("resolved_at");
var closedAt = current.getValue("closed_at");
var statusDescription;
var openedById = current.getValue("caller_id");
var openedByName;
var openedByEmail;
var resolvedById = current.getValue("resolved_by");
var resolvedByName;
var resolvedByEmail;
var closedById = current.getValue("closed_by");
var closedByName;
var closedByEmail;
//this isnt the best practice. Consider change it to oauth2 authentication
var user = 'admin';
var password = 'CHANGE HERE';
//GET THE NAME OF WHO RESOLVED THE CASE
var resolvedByRequest = new sn_ws.RESTMessageV2();
resolvedByRequest.setBasicAuth(user,password);
resolvedByRequest.setRequestHeader("Accept","application/json");
resolvedByRequest.setRequestHeader('Content-Type','application/json');
resolvedByRequest.setEndpoint(snowURL + "api/now/table/sys_user?sysparm_query=sys_idIN"+ resolvedById +"&sysparm_fields=sys_id,name,email");
resolvedByRequest.setHttpMethod("GET");
var resolvedByResponse = resolvedByRequest.execute();
var resolvedByBody = resolvedByResponse.getBody();
var resolvedByJson = new JSONParser().parse(resolvedByBody);
resolvedByName = resolvedByJson.result[0].name;
resolvedByEmail = resolvedByJson.result[0].email;
gs.info("Incident Survey: name: " + resolvedByName + ", email: " + resolvedByEmail);
//GET THE NAME OF WHO OPENED THE CASE
var openedByRequest = new sn_ws.RESTMessageV2();
openedByRequest.setBasicAuth(user,password);
openedByRequest.setRequestHeader("Accept","application/json");
openedByRequest.setRequestHeader('Content-Type','application/json');
openedByRequest.setEndpoint(snowURL + "api/now/table/sys_user?sysparm_query=sys_idIN"+ openedById +"&sysparm_fields=sys_id,name,email");
openedByRequest.setHttpMethod("GET");
var openedByResponse = openedByRequest.execute();
var openedByBody = openedByResponse.getBody();
var openedByJson = new JSONParser().parse(openedByBody);
openedByName = openedByJson.result[0].name;
openedByEmail = openedByJson.result[0].email;
//GET THE NAME OF WHO CLOSED THE CASE
var closedByRequest = new sn_ws.RESTMessageV2();
closedByRequest.setBasicAuth(user,password);
closedByRequest.setRequestHeader("Accept","application/json");
closedByRequest.setRequestHeader('Content-Type','application/json');
closedByRequest.setEndpoint(snowURL + "api/now/table/sys_user?sysparm_query=sys_idIN"+ closedById +"&sysparm_fields=sys_id,name,email");
closedByRequest.setHttpMethod("GET");
var closedByResponse = closedByRequest.execute();
var closedByBody = closedByResponse.getBody();
var closedByJson = new JSONParser().parse(closedByBody);
closedByName = closedByJson.result[0].name;
closedByEmail = closedByJson.result[0].email;
//CALL POWER AUTOMATE TO SEND TO TEAMS APPROVALS
try {
var body = {
"number": number,
"short_description": shortDescription,
"description": description,
"resolved_by_name": resolvedByName,
"resolved_by_email": resolvedByEmail,
"state": stateId,
"closed_at": closedAt,
"opened_by_name": openedByName,
"opened_by_email": openedByEmail,
"closed_by_name": closedByName,
"closed_by_email": closedByEmail,
"opened_at": openedAt,
"resolved_at": resolvedAt
};
var r = new sn_ws.RESTMessageV2();
// Change the following URL by the one you have created as HTTP trigger on Power Automate
r.setEndpoint("https://prod-96.westus.logic.azure.com:443/workflows/ee1cfb87108044f5affdeab515871234/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=xndVM5q0vLUdIK0GG6mrPb1-_5pjaqfE2oKj0RHHtJI");
r.setHttpMethod("POST");
r.setRequestBody(JSON.stringify(body));
r.setRequestHeader("Accept","application/json");
r.setRequestHeader('Content-Type','application/json');
var response = r.execute();
var httpStatus = response.getStatusCode();
} catch (ex) {
var message = ex.message;
gs.error("Error message: " + message);
}
gs.info("Webhook target HTTP status response: " + httpStatus);
})(current, previous);
The next step is to close an incident and verify if the notification is sent to Power Automate, and subsequently to Teams. This will allow you to ensure that the integration is working correctly and that the survey feedback process is functioning as expected.
This allows you to easily collect and analyze feedback from your users, and track any changes or trends over time.
In this post, we've explored how to use Microsoft Teams and ServiceNow to collect and analyze user feedback using Adaptive Cards and SharePoint Lists. By integrating these tools, you can streamline the feedback process, improve collaboration across teams, and gain valuable insights into the needs and preferences of your users.
We've covered the steps involved in setting up the integration, from creating the Adaptive Card survey to configuring the Power Automate flow and SharePoint List. By following these steps, you can easily implement the feedback process in your organization and start collecting valuable insights from your users.
We hope you found this post useful and informative. If you have any feedback or suggestions on how to improve this integration, please share them in the comments below. We look forward to hearing from you!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.