How to read users insights

What are Insights?

In Microsoft Graph API, Insights refers to a set of APIs that provide intelligent, personalized information derived from user activity and relationships within Microsoft 365. Insights are relationships calculated using advanced analytics and machine learning techniques

There are three main types of insights.

Trending insights are document that are trending around the user, meaning files that are being accessed or edited frequently by people in their network. This helps users discover relevant content they might not be aware of.

Use the /v1.0/users/{user_id}/insights/trending endpoint to retrieve trending insights for a specific user.

The response contains reference properties of the trending document, properties that you can use to visualize the document and value indicating how much the document is currently trending around the user.

Used Insights

Used insights are documents that the user has recently viewed or edited. It's useful for building "recently used" lists or dashboards.

Use the /v1.0/users/{user_id}/insights/used endpoint to retrieve used insights for a specific user.

The response contains reference properties of the trending document, properties that you can use to visualize the document and information about the last time the user interacted with the document, such as when it was last viewed or edited.

Shared Insights

Shared insights are documents that others have shared with the user, which helps users quickly find content that is relevant to them without having to search through emails or chats.

Use the /v1.0/users/{user_id}/insights/shared endpoint to retrieve shared insights for a specific user.

The response contains reference properties of the shared document, properties that you can use to visualize the document and information about the user who shared the document and the way how it was shared.

Filtering Insights

The common properties across all three types of insights are resourceReference and resourceVisualization. The resourceReference contains the URL and type of the referenced item.

Much more interesting is the resourceVisualization property, which contains additional information about the document, such as:

  • containerType: where the document is located. Possible values are OneDriveBusiness, Site, Mail, DropBox, Box, and GDrive
  • type: the media type of the document. Possible values are PowerPoint, Word, Excel, Pdf, OneNote, OneNotePage, InfoPath, Visio, Publisher, Project, Access, Mail, Csv, Archive, Xps, Audio, Video, Image, Web, Text, Xml, Story, ExternalContent, Folder, Spsite, and Other

You can filter insights based on these properties like

$filter=resourceVisualization/type eq '{type}'
$filter=resourceVisualization/containerType eq '{containerType}'

You can filter multiple type or containerType values by using the or operator. The in operator is not supported for filtering.

$filter=resourceVisualization/type eq 'Word' or resourceVisualization/type eq 'Excel'

For Trending Insights, you can filter by the value indicating how much the document is currently trending around the user.

$filter=weight ge 0.5
$filter=weight ge 0.1 and weight le 0.3

For Shared Insights, you can also filter by the user who shared the document using the sharedBy property.

$filter=lastShared/sharedBy/id eq '{user_id}'
$filter=lastShared/sharedBy/address eq '{user_mail}'

For Used Insights, you can filter by the last time the user interacted with the document using the lastUsed property.

$filter=lastUsed/lastAccessedDateTime ge 2025-08-01T00:00:00Z and lastUsed/lastAccessedDateTime le 2025-08-31T00:00:00Z
$filter=lastUsed/lastModifiedDateTime ge 2025-07-01T00:00:00Z and lastUsed/lastModifiedDateTime le 2025-07-31T00:00:00Z

You can retrieve the related resource by using the resource property. The resource can be driveItem, fileAttachment, or site.

GET /v1.0/users/{user_id}/insights/trending/{insight_id}/resource
GET /v1.0/users/{user_id}/insights/used/{insight_id}/resource
GET /v1.0/users/{user_id}/insights/shared/{insight_id}/resource

Permissions

According the documentation, all insights endpoints require Sites.Read.All. Only delegated permissions are supported. Insights can be read only for the signed-in user.

Read insights via Microsoft Graph .NET SDK

How to read insights using the Microsoft Graph .NET SDK? The following code snippets demonstrate how to read trending, used, and shared insights for a specific user.

Let's start by creating the InsightService class that will encapsulate the logic for reading insights. The class will have the CreateCommonFilter method to create a common filter for media types and container types, and methods to read trending, used, and shared insights.

private string CreateCommonFilter(List<MediaTypes> mediaTypes, List<ContainerTypes> containerTypes)
{
    var filters = new List<string>();
    if (mediaTypes.Count > 0)
    {
        var mediaTypeFilter = string.Join(" or ", mediaTypes.Select(mt => $"resourceVisualization/type eq '{mt}'"));
        filters.Add($"({mediaTypeFilter})");
    }
    if (containerTypes.Count > 0)
    {
        var containerTypeFilter = string.Join(" or ", containerTypes.Select(ct => $"resourceVisualization/containerType eq '{ct}'"));
        filters.Add($"({containerTypeFilter})");
    }
    return string.Join(" and ", filters);
}

public async Task<List<Trending>> GetTrendingInsightAsync(GraphServiceClient graphClient, string userId,
        List<MediaTypes> mediaTypes, List<ContainerTypes> containerTypes, double? minWeight, double? maxWeight)
{
}

public async Task<List<UsedInsight>> GetUsedInsightsAsync(GraphServiceClient graphClient, string userId,
        List<MediaTypes> mediaTypes, List<ContainerTypes> containerTypes, DateTime? minLastAccessed, DateTime? maxLastAccessed,
        DateTime? minLastModified, DateTime? maxLastModified)
{
}

public async Task<List<SharedInsight>> GetSharedInsightAsync(GraphServiceClient graphClient, string userId,
        List<MediaTypes> mediaTypes, List<ContainerTypes> containerTypes, string sharedById, string sharedByAddress)
{
}

As you can see, the CreateCommonFilter method constructs a filter string based on the provided media types and container types. The GetTrendingInsightAsync, GetSharedInsightAsync, and GetUsedInsightsAsync methods will use this filter to retrieve insights from the Microsoft Graph API. All methods accept parameter for the graph client and user id.

The enums MediaTypes and ContainerTypes are defined as follows:

public enum ContainerTypes
{
    None,
    OneDriveBusiness,
    Site,
    Mail,
    DropBox,
    Box,
    GDrive
}

public enum MediaTypes
{
    None,
    PowerPoint,
    Word,
    Excel,
    Pdf,
    OneNote,
    OneNotePage,
    InfoPath,
    Visio,
    Publisher,
    Project,
    Access,
    Mail,
    Csv,
    Archive,
    Xps,
    Audio,
    Video,
    Image,
    Web,
    Text,
    Xml,
    Story,
    ExternalContent,
    Folder,
    Spsite,
    Other
}

The GetTrendingInsightAsync accepts parameters for media types, container types, and optional weight filters. It constructs the filter string and retrieves trending insights for the specified user.

public async Task<List<Trending>> GetTrendingInsightAsync(GraphServiceClient graphClient, string userId,
        List<MediaTypes> mediaTypes, List<ContainerTypes> containerTypes, double? minWeight, double? maxWeight)
{
    var trending = await graphClient.Users[userId].Insights.Trending.GetAsync(rc =>
    {
        var allFilters = new List<string>();
        var filter = CreateCommonFilter(mediaTypes, containerTypes);
        if (!string.IsNullOrEmpty(filter))
        {
            allFilters.Add(filter);
        }
        if (minWeight.HasValue)
        {
            var weightFilter = $"weight ge {minWeight.Value}";
            allFilters.Add(weightFilter);
        }
        if (maxWeight.HasValue)
        {
            var maxWeightFilter = $"weight le {maxWeight.Value}";
            allFilters.Add(maxWeightFilter);
        }

        filter = string.Join(" and ", allFilters);
        if (!string.IsNullOrEmpty(filter))
        {
            rc.QueryParameters.Filter = filter;
        }
    });

    var trendingItems = new List<Trending>();
    var pageIterator = PageIterator<Trending, TrendingCollectionResponse>.CreatePageIterator(graphClient, trending, x =>
    {
        trendingItems.Add(x);
        return true;
    });

    await pageIterator.IterateAsync();

    foreach (var item in trendingItems)
    {
        var entity = await graphClient.Users[userId].Insights.Trending[item.Id].Resource.GetAsync(rc=>
        {
            rc.Headers.Add("accept", "application/json;odata.metadata=full");
        });
        item.Resource = entity;
    }

    return trendingItems;
}

Reading trending insights it's really straightforward. The most complicated part is constructing the filter based on the parameters.

The method uses the PageIterator to retrieve all trending items. For each trending item, it retrieves the related resource using the Resource property.

When retrieving the resource, I'm adding the accept: application/json;odata.metadata=full header to get the full metadata of the resource. By default, the Microsoft Graph API returns null for the @odata.type property and the SDK is not able to deserialize the resource to the correct type. By adding the accept header, it ensures that the full metadata is returned, allowing the SDK to deserialize the resource correctly.

Read used insights via .NET SDK

The GetUsedInsightsAsync method retrieves used insights for the specified user. It accepts parameters for media types, container types, and optional date filters for last accessed and last modified dates.

public async Task<List<UsedInsight>> GetUsedInsightsAsync(GraphServiceClient graphClient, string userId,
        List<MediaTypes> mediaTypes, List<ContainerTypes> containerTypes, DateTime? minLastAccessed, DateTime? maxLastAccessed,
        DateTime? minLastModified, DateTime? maxLastModified)
{
    var used = await graphClient.Users[userId].Insights.Used.GetAsync(rc =>
    {
        var allFilters = new List<string>();
        var filter = CreateCommonFilter(mediaTypes, containerTypes);
        if (!string.IsNullOrEmpty(filter))
        {
            allFilters.Add(filter);
        }

        if (minLastAccessed.HasValue)
        {
            var lastAccessedFilter = $"lastUsed/lastAccessedDateTime ge {minLastAccessed.Value.ToString("o")}";
            allFilters.Add(lastAccessedFilter);
        }
        if (maxLastAccessed.HasValue)
        {
            var maxLastAccessedFilter = $"lastUsed/lastAccessedDateTime le {maxLastAccessed.Value.ToString("o")}";
            allFilters.Add(maxLastAccessedFilter);
        }

        if (minLastModified.HasValue)
        {
            var lastModifiedFilter = $"lastUsed/lastModifiedDateTime ge {minLastModified.Value.ToString("o")}";
            allFilters.Add(lastModifiedFilter);
        }
        if (maxLastModified.HasValue)
        {
            var maxLastModifiedFilter = $"lastUsed/lastModifiedDateTime le {maxLastModified.Value.ToString("o")}";
            allFilters.Add(maxLastModifiedFilter);
        }

        filter = string.Join(" and ", allFilters);

        if (!string.IsNullOrEmpty(filter))
        {
            rc.QueryParameters.Filter = filter;
        }
    });

    var usedItems = new List<UsedInsight>();

    var pageIterator = PageIterator<UsedInsight, UsedInsightCollectionResponse>.CreatePageIterator(graphClient, used, x =>
    {
        usedItems.Add(x);
        return true;
    });

    await pageIterator.IterateAsync();

    foreach (var item in usedItems)
    {
        var entity = await graphClient.Users[userId].Insights.Used[item.Id].Resource.GetAsync(rc =>
        {
            rc.Headers.Add("accept", "application/json;odata.metadata=full");
        });
        item.Resource = entity;
    }

    return usedItems;
}

Reading used insights is similar to reading trending insights. The most complicated part is again constructing the filter based on the parameters.

The PageIterator is used to retrieve all used items and related resource is retrieved for each used insight.

Read shared insights via .NET SDK

The GetSharedInsightAsync method retrieves shared insights for the specified user. It accepts parameters for media types, container types, and optional filters for the user who shared the document.

public async Task<List<SharedInsight>> GetSharedInsightAsync(GraphServiceClient graphClient, string userId,
        List<MediaTypes> mediaTypes, List<ContainerTypes> containerTypes, string sharedById, string sharedByAddress)
{
    var shared = await graphClient.Users[userId].Insights.Shared.GetAsync(rc =>
    {
        var filter = CreateCommonFilter(mediaTypes, containerTypes);
        var sharedByFilter = string.Empty;
        var sharedByIdFilter = string.Empty;
        var sharedByAddressFilter = string.Empty;
        if (!string.IsNullOrEmpty(sharedById))
        {
            sharedByIdFilter = $"lastShared/sharedBy/id eq '{sharedById}'";
        }
        if (!string.IsNullOrEmpty(sharedByAddress))
        {
            sharedByAddressFilter = $"lastShared/sharedBy/address eq '{sharedByAddress}'";
        }

        var allSharedFilters = new List<string> { sharedByIdFilter, sharedByAddressFilter };
        sharedByFilter = string.Join(" or ", allSharedFilters.Where(f => !string.IsNullOrEmpty(f)));

        var allFilters = new List<string> { filter, sharedByFilter };
        filter = string.Join(" and ", allFilters.Where(f => !string.IsNullOrEmpty(f)));
        if (!string.IsNullOrEmpty(filter))
        {
            rc.QueryParameters.Filter = filter;
        }
    });

    var sharedItems = new List<SharedInsight>();

    var pageIterator = PageIterator<SharedInsight, SharedInsightCollectionResponse>.CreatePageIterator(graphClient, shared, x =>
    {
        sharedItems.Add(x);
        return true;
    });

    await pageIterator.IterateAsync();

    foreach (var item in sharedItems)
    {
        var entity = await graphClient.Users[userId].Insights.Shared[item.Id].Resource.GetAsync(rc =>
        {
            rc.Headers.Add("accept", "application/json;odata.metadata=full");
        });
        item.Resource = entity;
    }

    return sharedItems;
}

Main program

Before calling the methods in the InsightService, you need to create an instance of the GraphServiceClient and authenticate it using your preferred authentication method (e.g., client credentials, delegated permissions).

Let's assume that you have already registered an app in the Entra ID and granted the necessary permissions to read insights.

Initialize the Graph client:

var userCredentials = new InteractiveBrowserCredential(new InteractiveBrowserCredentialOptions()
{
    ClientId = "<client_id>",
    TenantId = "<tenant_id>"
});
var graphClient = new GraphServiceClient(userCredentials);

Read insights:

var insightService = new InsightService();
var trending = await insightService.GetTrendingInsightAsync(graphClient, "user_id",
    [MediaTypes.Word, MediaTypes.Excel],
    [ContainerTypes.OneDriveBusiness, ContainerTypes.Site], 0.1, 0.7);

Console.WriteLine("Trending Items:");
foreach (var item in trending)
{
    PrintResourceInfo(item.Resource);
}

var used = await insightService.GetUsedInsightsAsync(graphClient, "user_id",
    [], [], DateTime.UtcNow.AddDays(-30), DateTime.UtcNow, DateTime.UtcNow.AddDays(-30), DateTime.UtcNow);

Console.WriteLine("Used Items:");
foreach (var item in used)
{
    PrintResourceInfo(item.Resource);
}

var shared = await insightService.GetSharedInsightAsync(graphClient, "user_id",
    [MediaTypes.Word, MediaTypes.Excel],
    [ContainerTypes.OneDriveBusiness, ContainerTypes.Site], string.Empty, string.Empty);

Console.WriteLine("Shared Items:");
foreach (var item in shared)
{
    PrintResourceInfo(item.Resource);
    Console.WriteLine($"Shared by: {item.LastShared?.SharedBy?.DisplayName} ({item.LastShared?.SharedBy?.Address})");
}

Where the PrintResourceInfo method is a utility method to print the resource information:

void PrintResourceInfo(Entity entity)
{
    if (entity is DriveItem driveItem)
    {
        Console.WriteLine($"Insight: {driveItem.Name} ({driveItem.WebUrl})");
    }
    else if (entity is Site site)
    {
        Console.WriteLine($"Insight: {site.DisplayName} ({site.Description})");
    }
    else if (entity is FileAttachment file)
    {
        Console.WriteLine($"Insight: {file.Name}");
    }
    else
    {
       Console.WriteLine($"Insight: {entity?.GetType().Name} - {entity?.Id}");
    }
}

Conclusion

In this blog post, I explored how to read insights from the Microsoft Graph API using the .NET SDK.

I covered the different types of insights—trending, used, and shared—and how to filter them based on media types, container types, and other properties.

Don't forget that insights can be read only for the signed-in user.

0
Buy Me a Coffee at ko-fi.com
An error has occurred. This application may no longer respond until reloaded. Reload x