Building a directory feed sounds like “export a SharePoint list.” In practice, the hard part is deciding whether two records describe the same person when names, email addresses, and job titles keep changing.
The problem: names and email addresses are not permanent identifiers
“Jordan Lee” can become “Jordan Smith.” An employee can receive a new email alias. Two people can share the same name. If the integration matches on display name or email, updates can become duplicate people.
Before:
Jordan Lee | jlee@example.edu | Web Specialist
After:
Jordan Smith | jsmith@example.edu | Senior Web Specialist
The higher-ed workaround: use Banner ID as the anchor
Banner can be difficult to integrate with, but the Banner ID is exactly the kind of stable external identifier a directory needs. Microsoft 365 can supply current account information while SharePoint supplies manually maintained office and service data.
$employee = [
'bannerId' => '@00123456',
'firstName' => 'Jordan',
'lastName' => 'Smith',
'email' => 'jsmith@example.edu',
'title' => 'Senior Web Specialist',
'active' => true
];
The quirk: people and offices are not the same record type
A service such as “Financial Aid” needs a page URL, public phone number, and description, but it does not have a Banner ID or Microsoft 365 account. Mixing services into employee rows creates fake identities and confusing search results.
<directory>
<employee>
<bannerId>@00123456</bannerId>
<name>Jordan Smith</name>
<email>jsmith@example.edu</email>
</employee>
<service>
<name>Financial Aid</name>
<url>https://www.example.edu/financial-aid</url>
</service>
</directory>
The solution: merge, validate, then publish
I merge the sources by stable identifier, reject missing Banner IDs for employee records, normalize email domains and URLs, check for duplicate IDs, and verify the record count before replacing the public feed. The XML is the easy part. Identity and validation are what make the feed dependable.
