Dynamic Content Pages utilising Page Composer API

Interacts API is very versatile and can be harnessed in many different ways to solve many different use cases.

Have you ever wanted a page on your intranet to be automatically updated (synced) with content generated from an external system? Well, you're in luck! We are going to be using Interacts Page Composer API to create a cronjob-like sync to publish dynamic data to Interact. This could be used to create an array of dynamic content use cases - see the list below for some common use-cases.

Common Use Cases

  • Leaderboards
  • Progress Updates
  • Employee recognition
  • Automatic analysis and forecasts publishing
  • KPI's
  • Graphs, charts, and metrics
  • Sales progress
  • Project burndowns and recurring updates
  • Data dumps from external systems wrapped in HTML

Tutorial

We're going to provide you with the boilerplate code in .NET Framework/Core C# (Restsharp) required to achieve the sync. Of course, this can be converted to any language or system capable of pushing content to REST API Endpoints.

Application Flow

  1. Get API Domain for your Interact instance.
  2. Authenticate using Basic Authentication flow.
  3. Create HTML content (manually or dynamically using another process)
  4. Push the generated content to Page Composer API

1. Finding API Domain

Interact provides a simple endpoint to get details about your intranet instance. We can find your API domain by going to https://your-intranet.interactgo.com/info this lists us the following details in JSON format:

  • API Domain (Required)
  • Auth mode
  • Tenant GUID (Required)
  • Name
  • Market API Path

The information we require is highlighted in bold, using this we can now begin authentication.

// Required for API
string apiDomain = "https://us-lb-api-01.interactgo.com/api";
string tenantGuid = "00000000-0000-0000-0000-000000000000";

2. API Authentication

When working with any Interact API you need to authenticate for most API calls. You can learn more about API authentication on our API documentation. We need to use the /token token endpoint in order to receive our Bearer token.

Interact uses an OAuth 2.0 password-bearer authentication mechanism to acquire an access_token which gives you access to perform actions using the API endpoints.

Once, we've got our token we can move on to content generation.

🚧

Authentication

The password-bearer authentication requires a username and password to authenticate. It may be tempting to use a personal account to do this but it may break the connection if the user ever becomes de-activated (eg. leaves the company). Interact recommends setting up a dedicated user account within Interact which will only be used for the API connectivity (akin to a service account.)

string token = ""; // Replace with the token from /token response

3. Dynamic Content Generation

Now for the most important part, the content generation which can be dynamically generated by an application, script, service or anything which is capable of creating HTML content. HTML content is the heart of Interact pages and therefore it is the key component of the dynamic page updates. Interacts page API currently only supports HTML.

In the example below (see line 50), we create a simple alert bar (div) that writes out the current date and time. This can be replaced with highly complex content including combinations of HTML, CSS and JavaScript. We have successfully embedded full React.js apps in these uploads.

<div class="alert alert-info">Last Sync: {DateTime.Now}</div>

Custom Widget Gallery showcasing some of our internal works/experiments is coming soon - feel free to reach out to see the art of possible.

4. Updating Content

Once our content has been generated we can now push it Interacts Page Composer API. We will be using the Page Composer PUT endpoint.

Boilerplate

Combing all the steps above we end up:

using System;
using Newtonsoft.Json;
using RestSharp;

namespace PageComposerSync
{
    static class Program
    {
        static void Main()
        {
            // Required for API
            string apiDomain = "https://us-lb-api-01.interactgo.com/api";
            string tenantGuid = "00000000-0000-0000-0000-000000000000";
            string token = ""; // Replace with the token from /token response
            
            // Destination Page ID for syncing
            int pageId = 2000;
             
            // Create RestClient
            var restClient = new RestClient(apiDomain);

            // Create Page Update Request
            var request = new RestRequest($"/page/{pageId}/composer", Method.PUT);
            request.AddHeader("X-Tenant", tenantGuid);
            request.AddHeader("Authorization", $"Bearer {token}");
            request.AddHeader("Content-Type", "application/json");

            // Add request content - Page Composer PUT Schema (https://developer.interact-intranet.com/reference#pageidcomposer-1)
            var requestContent = new PageUpdateRequest();

            /// Transition
            requestContent.Transition = new Transition
            {
                State = "published",
                Message = DateTime.Now.ToString()
            };

            /// Page details - Tip: Use the Page Composer GET Endpoint to find all required meta information
            requestContent.Page = new Page()
            {
                ContentType = "html",
                TopSectionIds = new List<int>() { 3141 }, // Required
                AuthorId = 2, // Required
                PublishAsId = null,
                AssetId = 1999, // Required
                Title = "Sync Page", // Required
                Summary = $"Sync Page Summary", // Required
                Content = new Content()
                {
                    Html = $@"<div class=""alert alert-info"">Last Sync: {DateTime.Now}</div>" // Dynamic content here
                },
                CategoryIds = new List<int>() { 3145 }, // Required
                Features = new Features
                {
                    DefaultToFullWidth = false,
                    AllowComments = false,
                    IsKeyPage = false,
                    Recommends = new Recommends
                    {
                        MaxContentAge = null,
                        Show = false
                    }
                },
                PubStartDate = DateTime.Today, // Required
                PubEndDate = DateTime.Today.AddDays(7), // Required
                ReviewDate = DateTime.Today.AddDays(7), // Required
                TagIds = new List<object>() { },
                Keywords = new List<object>() { }
            };

            // Convert our page to JSON payload
            request.AddJsonBody(requestContent);

            // Execute the request
            var response = restClient.Execute(request);
            // response.Content ->
            /*
                {
                    "ContentId": 1234,
                    "VersionId": 1235,
                    "Acknowledged": true
                }
            */ 
        }
    }

    public class Transition
    {
        public string State { get; set; }
        public string Message { get; set; }
    }

    public class Content
    {
        public string Html { get; set; }
    }

    public class Recommends
    {
        public bool Show { get; set; }
        public object MaxContentAge { get; set; }
    }

    public class Features
    {
        public bool DefaultToFullWidth { get; set; }
        public bool AllowComments { get; set; }
        public bool IsKeyPage { get; set; }
        public Recommends Recommends { get; set; }
    }

    public class Page
    {
        public string ContentType { get; set; }
        public List<int> TopSectionIds { get; set; }
        public int AuthorId { get; set; }
        public object PublishAsId { get; set; }
        public int AssetId { get; set; }
        public string Title { get; set; }
        public string Summary { get; set; }
        public Content Content { get; set; }
        public List<int> CategoryIds { get; set; }
        public Features Features { get; set; }
        public DateTime PubStartDate { get; set; }
        public DateTime PubEndDate { get; set; }
        public DateTime ReviewDate { get; set; }
        public List<object> TagIds { get; set; }
        public List<object> Keywords { get; set; }
    }

    public class PageUpdateRequest
    {
        public Transition Transition { get; set; }
        public Page Page { get; set; }
    }
}

This was built with .NET Core 3.1, Restsharp 106.10.1 and Newtonsoft.JSON 12.0.3.

Styling and CSS

Styling and CSS can be included inline with style tags.

<style>
  h1 {color:red;}
  p {color:blue;}
</style>
<h1>Hello World!</h1>
<p>This is my dynamic content</p>

It can be included as inline styles.

<table>
  <tr style="font-weight: bold">
    <th>Row</th>
    <th>Name</th>
  </tr>
</table>

Recommended: Or it can be included in the Custom CSS settings in Interact to store the presentation and styling layer globally. You can classes on your HTML elements to reference the globally declared styles in the Custom CSS in the HTML.

eg.

Custom CSS

.table {
  background-color: transparent;
  margin: 0.5em;
}

.header-row {
  font-weight: bold;
  color: darkgrey;
}

HTML Upload

<table class="table">
  <tr class="header-row">
    <th>Row</th>
    <th>Name</th>
  </tr>
</table>

Automation

You can extend the boilerplate to fit requirements and build or use cronjobs for scheduling on a schedule that suits your data requirements. Your page will be updated dynamically and visible within your Intranet.