Exploit the Usage Reports API to Find Underused Accounts
Investing in Microsoft 365 Copilot licenses is an expensive decision. Choosing to pay $360 for an annual user license can represent a major increase in Microsoft 365 payments, so it’s important that the people who receive Copilot licenses use them to increase personal productivity. Previously, I’ve discussed some of the questions you might ask to decide which accounts should get Copilot licenses. I’ve also explained how to extract Graph usage data to analyze how people use Microsoft 365 as a further guide to license allocation.
The experience in some tenants is that users are often fascinated by their first Copilot interactions as they explore meeting and email thread summarization and other features. Enthusiasm remains high for the initial period but can tail off after a few weeks if people don’t discover a sweet spot where Copilot helps them in their jobs. Sometimes it just takes a little time and support before people discover how to use AI effectively instead of a gee-whiz tool.
In other situations, people never find a way for Copilot to work for them. It could be because of the job they do, the data they handle, or the way that they work. It could be that they only use Copilot in limited situations, such as only using BizChat. For instance, I hardly ever use Copilot to generate text because I reckon that I can do a better job. I don’t use it in Excel because I haven’t yet found a worksheet task that I need assistance with, and I don’t use Copilot in PowerPoint because I only create a few presentations annually.
Scanning for Copilot Activity Individually and Across the Tenant
It’s good to know if people are using expensive software and how they use that software. Previously, we’ve explored how to analyze Copilot interactions based on compliance records stored in user mailboxes and the Graph allInteractionHistory API. Copilot activity data can also be gleaned from Microsoft 365 audit records. A great deal of insight can be derived using these methods, but they focus on the interactions of individual users rather than casting a net to find inactive accounts.
Instead, when the need exists to scan for inactive Copilot accounts on a tenant-wide or for selected groups (like a country or department), usage report data is the right source to consult. This is the same usage data found in the reports section of the Microsoft 365 admin center and it’s been available through the Graph usage reports API since September 2024.
Usage data available through the Graph API is always a few days behind real time, but it’s sufficient to understand the applications people use Copilot with, even if the getMicrosoft365CopilotUsageUserDetail API doesn’t reveal how many individual interactions took place between a user and an app. Instead, you get a date for the last interaction between users and Copilot in seven Microsoft 365 apps. An individual user record looks like this:
Name Value ---- ----- wordCopilotLastActivityDate 2024-12-23 copilotActivityUserDetailsByPeriod {System.Collections.Hashtable} microsoftTeamsCopilotLastActivityDate 2024-12-19 reportRefreshDate 2024-12-30 displayName Tony Redmond oneNoteCopilotLastActivityDate copilotChatLastActivityDate 2024-12-19 lastActivityDate 2024-12-23 powerPointCopilotLastActivityDate 2024-09-22 outlookCopilotLastActivityDate 2024-11-28 excelCopilotLastActivityDate 2024-09-05 loopCopilotLastActivityDate 2024-09-11 userPrincipalName Tony.Redmond@office365itpros.com
Creating a Script to Find Underused Microsoft 365 Copilot Licenses
Knowing what data is available about Copilot usage, it’s possible to write a PowerShell script to detect and report accounts that aren’t using assigned Microsoft 365 Copilot licenses. The version of the code that I came up with goes through the following steps:
- Signs into the Microsoft Graph PowerShell SDK. The following permissions are needed: User.ReadWrite.All (to read and update license information for accounts), Reports.Read.All (read usage data), and ReportSettings.ReadWrite.All (to update the tenant setting for usage data obfuscation, if set).
- Runs the Get-MgUser cmdlet to find the set of accounts assigned a Microsoft 365 Copilot license (SKU identifier 639dec6b-bb19-468b-871c-c5c441c4b0cb).
- Updates the tenant setting for usage data obfuscation to allow full access to data. If the usage data doesn’t contain user principal names, it can’t be linked to a user account.
- Fetch the Copilot user detail data for the last 90 days by running a request with the getMicrosoft365CopilotUsageUserDetail API.
- For each licensed Copilot user, get their usage data and last successful sign-in date.
- Check if the user accessed each of the seven Copilot-enabled applications and record details of when the access occurred.
- Add the total number of days since the user accessed Copilot across the seven applications. Divide the total number of days by the number of active apps to compute a score. The lower the score, the higher the Copilot activity for the user.
- Generate a report showing the scores for each user (Figure 1).
- Filter the set of users whose score is greater than the threshold defined in the script. I used 30 as the threshold. It could be higher or lower. Remember, we’re just exploring principles here.
- Report the set of underused accounts that either exceed the threshold or have a zero score (they have a Copilot license but have never used it).
The Next Step – Removing Copilot Licenses
After identifying the accounts that don’t seem to make good use of their Microsoft 365 Copilot licenses, the next logical step is to remove those licenses so that they can be reassigned to more deserving accounts. Microsoft 365 supports direct license assignments, where administrators update user accounts to assign licenses, and group-based licensing, where licenses are assigned to members of a group.
To remove the Microsoft 365 Copilot licenses from user accounts, the script runs either the Remove-MgGroupMemberDirectoryObjectByRef cmdlet to remove accounts from membership of the groups used for group-based assignments or the Set-MgUserLicense cmdlet to remove directly-assigned licenses. Figure 2 shows how the script presents the administrator with the option to remove licenses.
Although scripting makes it simple to remove licenses from many users, it would be wise to inform the affected users before making any licensing changes. Data is a great basis for coming to a decision but sometimes it doesn’t tell the full story. For example, a user might not have been able to use Microsoft 365 Copilot because they were ill or on an extended vacation. The right decision might be to remove and reassign the Copilot license until the user is back at work. On the other hand, Office politics might mean that it is more politically expedient to allow the user to keep the license.
Improvements Always Possible
You can download the script I created to find and remove underused licenses from GitHub. Some obvious improvements could be made to the code. For instance, before removing a license from an account, you could fetch audit records for that account to figure out if the account is using Copilot heavily for a single app, like Word or Teams. It could be that the user is focused on a single app and uses Copilot to be more effective in that app. The summary data doesn’t tell you this because it only reports the last date that Copilot was used in an app, so removing the Copilot license in this case might be the wrong thing to do.
Another improvement could be made to the scoring system to emphasize Copilot usage in apps that are more important to the tenant. For example, you might not care about using Copilot in Loop but consider that Copilot in Chat (BizChat) is critical.
The techniques explained here aren’t specific to Copilot. The usage reports API includes data for Outlook (Exchange Online), SharePoint Online, OneDrive for Business, Teams, and Viva Engage (Yammer). You could analyze the data for users assigned high-end licenses like Microsoft 365 E5 and find if any accounts could use a lower license instead.
License management is a basic task for any Microsoft 365 tenant. Knowing who’s got and who’s using expensive licenses is an important step to controlling licensing costs (and the licensing report script might help here too). Happy coding!