Table of Contents
Use SDK Cmdlets to Add Properties to the Microsoft 365 User Profile Card
The Microsoft 365 profile card displays information about users. The information show in a profile card comes from the user’s Entra ID account. By default, Microsoft 365 limits the properties shown by the profile card to the set that they consider to be most important. Organizations can customize the Contact tab of the profile card to reveal some of the properties that are not shown by default. However, not every property of an Entra ID user account is available for the profile card. Some, like the employee hire date, are not supported.
In 2020, I wrote about how to customize the profile card. At that time, the profile card API was in beta. The production Graph endpoint now supports the profile card API, and it’s also supported by cmdlets in the Microsoft Graph PowerShell SDK. I used version 2.9 of the SDK for this article.
The Microsoft documentation for customizing the profile card is a little outdated. At the time of writing, it uses V1.0 of the SDK and is based on the beta API. Because the API is now in production, it follows that the latest SDK cmdlets use that API. In any case, the instructions contained in the documentation are a reasonable guide.
Customized User Profile Card Available to All
The most important point about customizing the profile card is that any change is exposed to all users. You cannot customize the profile card for a subset of the user population such as a targeted administrative unit. This fact creates difficulties in multinational organizations where local privacy regulations might prevent the display of certain information held in user account properties.
As already mentioned, only certain user account properties are available for customization. Basically, you can add six standard Entra ID properties to the user profile card:
- UserPrincipalName.
- Fax.
- StreetAddress.
- PostalCode.
- StateOrProvince.
- Alias.
Of course, including these properties in the profile card is useless unless information is populated in the directory for all user accounts. That often doesn’t happen.
The the fifteen custom attributes inherited from Exchange Server (different to the custom security attributes that can be defined for Entra ID) are also supported. Many organizations use these attributes to store information about users such as personnel numbers, cost centers, employee type, employee job codes, seniority level, and even the date of last promotion. Dynamic distribution lists and dynamic Microsoft 365 groups.
Add an Attribute to the Profile Card
To add one of the six standard or fifteen custom attributes to the profile card, construct a payload in a PowerShell hash table. The table contains the property name and its display name (annotation). Then run the New-MgAdminPeopleProfileCardProperty cmdlet passing the hash table as the body parameter (the same as passing a request body to a Graph request). This command adds CustomAttribute15 and tells Microsoft 365 that the user profile card should refer to the property as the “Employee Type.”
Connect-MgGraph -Scopes "PeopleSettings.ReadWrite.All" -NoWelcome
$AddPropertyDetails = @{
directoryPropertyName = "CustomAttribute15"
annotations = @(
@{ displayName = "Employee Type" }
)
}
$AddPropertyDetails
Name Value
---- -----
directoryPropertyName CustomAttribute15
annotations {Employee Type}
New-MgAdminPeopleProfileCardProperty -BodyParameter $AddPropertyDetails
Id DirectoryPropertyName
-- ---------------------
CustomAttribute15
It takes at least 24 hours before the profile card picks up customized properties. When they do, they appear on the Contact tab of the profile card. Figure 1 shows three custom properties for cost center, preferred drink (a historic part of the Active Directory schema), and employee type. If a custom properties doesn’t contain any information for a user, it won’t appear on the profile card.

To check the set of attributes added to the profile card with PowerShell, run the Get-MgAdminPeopleProfileCardProperty cmdlet. This output tells us that the profile card is configured to display three optional properties and three custom properties:
Get-MgAdminPeopleProfileCardProperty Id DirectoryPropertyName -- --------------------- userPrincipalName customAttribute12 StreetAddress Postalcode CustomAttribute9 CustomAttribute15
If you make a mistake, you can remove a property from the profile card by running the Remove-MgAdminPeopleProfileCardProperty cmdlet. For example, this command removes the Drink attribute (stored in CustomAttribute9) from the profile card:
Remove-MgAdminPeopleProfileCardProperty -ProfileCardPropertyId CustomAttribute9
Note that the profile card property id parameter is case sensitive. You must pass the property name as returned by the Get–MgAdminPeopleProfileCardProperty cmdlet.
Adding a Translated Label for a Custom Profile Card Property
The documentation makes a big thing about defining a language-specific value for a custom property. This is done using the Update-MgAdminPeopleProfileCardProperty cmdlet. This example shows how to add a French language label for CustomAtrribute15:
$LocalizationHash = @{}
$LocalizationHash.Add("languagetag","fr-FR")
$LocalizationHash.Add("displayName","Type d’employé")
$UpdatePropertyDetails = @{
annotations = @(
@{
displayName = "Cost Center"
localizations = @( $LocalizationHash )
}
)
}
Update-MgAdminPeopleProfileCardProperty -ProfileCardPropertyId 'customAttribute15' -BodyParameter $UpdatePropertyDetails
This command works, but it only works for a single language. If you want to have labels for multiple languages, you’ll be sadly disappointed because Update-MgAdminPeopleProfileCardProperty (and its Graph API counterpart) overwrite the language configuration each time.
You could argue that this is disappointing for multinational organizations that want to have fully-translated interfaces for all languages in use. Being restricted to a single language alternative is a strange approach to localization, especially for a company that does so much to deliver local language translations for user interfaces. The counterargument is that the properties chosen for display in the profile cards are likely to be well understood by anyone in an organization.
Work Still to Do
Not much has changed in customizing the profile card since 2020. The API is now production rather than beta and the Graph SDK supports the action, but that’s it. Coverage for multiple local language labels would be nice but that’s still elusive.
Support the work of the Office 365 for IT Pros team by subscribing to the Office 365 for IT Pros eBook. Your support pays for the time we need to track, analyze, and document the changing world of Microsoft 365 and Office 365.
Thanks for this post. This would be helpful to us to surface some attributes on the profile card.
I’m trying it and get an error when I try the final step. Any thoughts on what is causing this?
New-MgAdminPeopleProfileCardProperty : The ‘New-MgAdminPeopleProfileCardProperty’ command was found in the module ‘Microsoft.Graph.Identity.DirectoryManagement’, but the module could not be loaded. For more information, run
‘Import-Module Microsoft.Graph.Identity.DirectoryManagement’.
At C:\Users\tandy\Farmers Alliance\M365 Admin & Governance – PowerShellScripts\Update-User-Profile-Cards.ps1:24 char:1
+ New-MgAdminPeopleProfileCardProperty -BodyParameter $AddPropertyDetai …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (New-MgAdminPeopleProfileCardProperty:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CouldNotAutoloadMatchingModule
What version of the SDK are you using? The latest is V2.9 and that’s the one I use.
I believe I am at version 2.9.0. That’s what I see for the version when I use get-module for microsoft.graph.identity.directorymanagement. I did load az.accounts and connect and now I get a different error.
+ New-MgAdminPeopleProfileCardProperty -BodyParameter $AddPropertyDetai …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [New-MgAdminPeop…Property_Create], AggregateException
+ FullyQualifiedErrorId : System.AggregateException,Microsoft.Graph.PowerShell.Cmdlets.NewMgAdminPeopleProfileCardProperty_Create
Permissions? “PeopleSettings.ReadWrite.All”,”PeopleSettings.Read.All”
I’m a global admin and using Powershell with my admin credentials. At some point while working on this I got a “Permissions requested” pop up that said “This app would like to: read and write tenant-wide people settings, Read tenant-wide people settings, View users’basic profile, maintain access to data you have given it access to. I selected “Consent on behalf of your organization.” So I should have permissions.
Run (Get-MgContext).Scopes just to make sure. Being a global admin doesn’t mean that the process has permissions to update the people card settings.
Yes, the scope says: Scopes : {ChannelSettings.Read.All, Directory.Read.All, openid, PeopleSettings.Read.All…}
But in looking at versions of modules, I had both the 2.9.0 and an older version of the Microsoft.Graph.Authentication. I had to force uninstall that version and restart powershell, and now I’ve run the command without an error. So “fingers-crossed,” I might have updated the profile cards.
Thanks so much Tony for your quick responses and attention to detail. I appreciate it!
It´s sad not more attributes are supported, like employeeid.
Great article as always Tony!
I’m running into an issue with running the commands.
I’m running PS Graph SDK v2.11.1. I’ve tried in WPS (5.1) and PSC (7.4).
I’m a GA with a PIM’d role and have admin and user consent.
Scope was set to “Connect-MgGraph -Scopes “PeopleSettings.ReadWrite.All”,”PeopleSettings.Read.All” -NoWelcome”
Double checked with “(Get-MgContext).Scopes”and scopes are listed and presented, but I’m hitting a
Remove-MgAdminPeopleProfileCardProperty
Status: 403 (Forbidden)
UnknownError,Microsoft.Graph.PowerShell.Cmdlets.RemoveMgAdminPeopleProfileCardProperty_Delete
The documentation says that PeopleSettings.ReadWrite.All is all that’s needed as does the Graph documentation. Have you tried using a Graph request rather than the cmdlet (just in case).
Found the answer 👍. It was GA permission consent in one of our tenants that wasn’t in the correct state. Thanks for taking the time to reply.
When i run my $addpropertydetails command to view i see the following – my annotations isnt showing the correct name
PS C:\Users\martin.FCC> $AddPropertyDetails | fl
Name : annotations
Value : {System.Collections.Hashtable}
Name : directoryPropertyName
Value : CustomAttribute15
What is the object type for AddPropertyDetails?
$AddPropertyDetails.Gettype()
IsPublic IsSerial Name BaseType
——– ——– —- ——–
True True Hashtable System.Object
PS C:\Users\martin.FCC> $addpropertydetails.gettype()
IsPublic IsSerial Name BaseType
——– ——– —- ——–
True True Hashtable System.Object
This is the original code I used to set up my variable
$AddPropertyDetails = @{
directoryPropertyName = “CustomAttribute15”
annotations = @(
@{ displayName = “Employee Dot Type” }
)
}
I copied the command from the article. What version of PowerShell are you using? I use 7.4
Me again. It still hasn’t updated the contact card in Outlook app in Windows. How long should it normally take?
Teams/Outlook app on phone have updated
I don’t know. Outlook (classic) has its own method of caching information. I never really monitored how long it took.
I am using version 5.1. I am upgrading the version now to 7.4.
HI after upgrading to 7.4 i can now see the proper values
PS C:\Users\martin.FCC> Get-MgAdminPeopleProfileCardProperty
PS C:\Users\martin.FCC> $AddPropertyDetails = @{
>> directoryPropertyName = “CustomAttribute15”
>> annotations = @(
>> @{ displayName = “Dot Type(s)” }
>> )
>> }
PS C:\Users\martin.FCC> $AddPropertyDetails
Name Value
—- —–
directoryPropertyName CustomAttribute15
annotations {Dot Type(s)}
I have since done the following commands and my output doesnt show what your output says
PS C:\Users\martin.FCC> New-MgAdminPeopleProfileCardProperty -BodyParameter $AddPropertyDetails
Id DirectoryPropertyName
— ———————
CustomAttribute15
PS C:\Users\martin.FCC> Get-MgAdminPeopleProfileCardProperty
Id DirectoryPropertyName
— ———————
CustomAttribute15
PS C:\Users\martin.FCC>
Your output looks like I would expect. My output is different because I have configured several properties to appear on the profile card.
Hi Tony
I have just checked it and i can see the new info inside the contact card in Teams but it hasnt flowed through to the contact card in Outlook on Windows just yet. It has flowed through to Outlook on the web.
It takes time for changes to flow through to apps…
Do you know if it is possible to add in coloured dots into the custom attribute fields at all?
Nope.
Hi Tony
Is that a No it can’t be done or No you are not sure? 🙂 I dont think it can be done.
I don’t think it can be done either.
Is it possible to change the associated icons with the custom attributes?
Nope.
can anyone confirm if this is working for them on outlook classic latest version, 2412? I am not sure if it ever worked or when it stopped working, but confirmed it only appears in OWA/new outlook/teams.
I don’t believe that custom profile fields appear in Outlook classic (I am looking at version 2502). I see the optional properties, but not the custom properties. Everything shows up in OWA and the new Outlook.
Where is the data for a custom attribute set once one (say number 1 for example) is activated. Does it grab it form the Exchange Admin center setting or from the Entra User properties?
Custom attributes are properties of the Entra ID user account. They are also synchronized from Exchange Online mailbox custom properties.
Thank you. It is strange how this info is not overly obvious in KB’s. Some info discusses using the Exchange admin center and others the Entra user attributes. Thank you for the quick reply!
I can’t account for why people don’t cover the full picture…
Any idea if it is possible to have the custom attribute show up in the profile card as a clickable link?
Nope. That’s not possible.
Rats. Do you happen to know if any if the out of the box fields support hyperlinking by default?
If you add a custom attribute, can you search for values in that custom attribute? For example using your screenshot, find everyone who has an Employee Type of Temporary Contract?
Thank you!
Yes, the Get-MgUser cmdlet supports that kind of searching.