Creating and Publishing a Teams Directory

Avoiding Duplicated and Unwanted Teams

A reader reported that their Teams deployment had run into a roadblock. By default, teams are created as private. This suits the owners because they want to control access to their data, but it creates a problem when people don’t know that a team already exists for a project or other purpose. They then go ahead and create another team and the organization ends up with duplicate teams to serve the same purpose. The teams might have different members and titles, but they’re duplicates all the same.

The issue the reader had is the lack of a central Teams directory that users can browse to discover what teams exist, what they are being used for, and who’s responsible for the teams. A user can search for public teams and join them without hindrance but finding out about private teams is a different matter.

The challenge therefore is to create a Teams directory that’s accessible to all users where they can find out about teams in the tenant that they’d like to join and to make it easy for them to join a team they find.

Teams Deep Links and PowerShell

The approach I took was to write a PowerShell script to output a list of teams, their descriptions, some ownership information, and a deep link to each team. A deep link is a URL to navigate to a specific part of Teams. In this case, we want to navigate to a team chosen from the directory, so the link generated by the Get link to team option in the Teams client seemed like the right one to use.

The deep link to a team (as generated by a Teams client) looks like this:

https://teams.microsoft.com/l/team/19%3ad883bd88149a430f9c8b64231fc5f459%40thread.skype/conversations?groupId=83d28c15-f89c-435d-bba2-a328b476203d&tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47

The two important components are the tenant id, which tells Teams what Office 365 tenant the target team belongs to, and the group id for the underlying Office 365 group. Both are GUIDs. After doing some testing, it seems like all that’s necessary to generate a deep link for a target group is to insert the relevant group id.

Scripting a Teams Directory

The script (you can download a copy from GitHub) is simple.

  • Collect the set of teams in the tenant (some tenants might prefer to only include public teams in the list).
  • Get some information for each team (we need to use Get-UnifiedGroup to retrieve some information about the group).
  • Build a deep link for the team.
  • Write the information out to a table.
  • When finished processing all teams, write out a HTML report and a CSV file.

I created both the report and CSV file because I wasn’t sure what would be the best way for users to access the information.

Making the Directory Accessible to Users

Teams supports org-wide teams with automatic membership for small to medium tenants of up to 5,000 accounts. Larger tenants need to take care of membership management to the current limit of 10,000 members. In either case, a public team that’s generally open to all users seemed like a good location to host the directory.

I wanted users to be able to browse and search the directory. The static report (a HTML file) didn’t work so well because there’s no easy way to load this into Teams and have it display properly. I tried to paste the file into the Teams Wiki, which wasn’t successful, and OneNote, which was (Figure 1). All the links are clickable, including the Mailto: links for team owners.

Teams Directory OneNote
Figure 1: The Teams directory in OneNote (image credit: Tony Redmond)

The only problem is that every member in a team has the rights to edit content, so the possibility exists that someone will change a link or other important piece of data.

Hyperlinks, Excel, and PDFs

My script generates a CSV file too, so I could use that. Before uploading it to Teams, I edited the file to adjust its formatting and saved it as an Excel spreadsheet, which I then loaded into the SharePoint folder for the General channel. Once a spreadsheet is in SharePoint, you can create a channel tab pointing to the file. Access is easy, but once again you run into the problem that people can edit information in the spreadsheet. And we have a further issue in that the links in the spreadsheet are plaintext hyperlinks and need to be activated before people can click them to go a team.

You can manually update a hyperlink to make it active, but that’s only feasible when a small number of links are to be processed. A directory could include hundreds or thousands of teams, so that’s not a viable option. Fortunately, an Excel macro can transform plaintext hyperlinks into active.

With all the hyperlinks activated and a little extra formatting to make the data look nicer, we can save the spreadsheet as a PDF file. After uploading the PDF to SharePoint, we can create a channel tab for the PDF. Users can browse and search for teams, but they can’t change the data (Figure 2).

Teams Directory PDF
Figure 2: Viewing the PDF file with the Teams directory (image credit: Tony Redmond)

When a user clicks a hyperlink to a public team, the link opens the Teams web client and they can join the team without further delay. The link works for private teams too, but the user can only request to join the team. All requests are routed to team owners for their approval.

Other Approaches

Other possibilities exist to disseminate and refine the information in the Teams directory. For example, you could populate a SharePoint list with information about Teams (this approach seems interesting. Or you could create a HTML page that makes the deep links more approachable with a href labeled something like “Click to Join the team” and host that page on a web server that’s linked to a tab.

You might not want all private teams in the directory so you could filter and include only teams that meet some criteria (like those with a specific classification). All the other private teams would remain hidden from non-member eyes. In any case, the tools described here are flexible enough to filter out specific teams and generate outputs in several formats. It’s all just a matter of some PowerShell code (and maybe some manual fix-up afterwards).