Site Design & Branding

Using APIs in custom HTML areas

You can customise your Content Catalyst site easily using custom HTML areas and the available GET API endpoints.

Read this article to understand how to:

  • Strengthen brand identity
  • Deliver a visually engaging experience for end-users
  • Create more upsell and cross-sell opportunities 

Custom HTML areas on the home page are in the left and right header, in the banner and in the homepage tabs:

Homepage (11)

Custom HTML areas on category landing pages are in the Marketing Block and Simple Marketing Block:

categorylanding

As with all API requests you can use the header to supply the authorisation token.  Content Catalyst provides the {{CurrentUser.AuthHeader}} variable for use in scripts in the custom HTML areas.  For example, using javascript and the fetch call you might do something like:

const myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("Authorization", "{{CurrentUser.AuthHeader}}");

fetch(API_url,{
method: "GET",
headers: myHeaders
});

This will authorise the currently logged-in user to access the specified API endpoint.

🔔 Note: the authorisation token may expire after 10 minutes.

Working example

In this example, we'll use a custom home page tab to present to the logged-in user a tiled grid view of reports in the specified category (in this example the "Featured" category).  Any images you want to reference should be made available via File Explorer

This code should be created in a Home page extra tab content preference as described here.  Use the </>source option:

home page tab content preference

The resulting homepage tabs will look something like this example homepage tabs screenshot:

 

Homepage tabs

 

<style type="text/css">.grid { 
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-gap: 20px;
align-items: stretch;
justify-items: center;
position: relative;
}

.grid img {
border: 1px solid #ccc;
box-shadow: 2px 2px 6px 0px rgba(0,0,0,0.3);
max-width: 100%;
margin-bottom: 15px;
}

.grid div {
position: relative;
}

.grid .top-right {
position: absolute;
top: 16px;
right: -12px;
color: rgb(230,230,230);
background-color: rgb(114,172,213);
border: none;
border-radius: 12px;
padding: 5px 10px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 14px;
}

.grid .title {
font-weight: bold;
}

a{
color: rgb(114,172,213);
}
</style>
<main class="grid">
<p>Please enable Javascript. This paragraph will be removed when adding items to the grid</p>
</main>
<script>
//point to the html we are modifying with the javascript
const main = document.querySelector('.grid');

// set up the request headers - the {{CurrentUser.AuthHeader}} variable
// allows us to authenticate the logged in user against the API
const myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("Authorization", "{{CurrentUser.AuthHeader}}");

// ckeditor doesn't like empty main's div's etc. Put some placeholder text in there
// and then remove it when we are building the grid
main.innerHTML = "";

// The fetch call is asynchronous, so define a function that include the await instruction
async function fetchJson(API_url) {
const response = await fetch(API_url,{
method: "GET",
headers: myHeaders
});
const json = await response.json();
return json;
}

// define the API endpoints to use for this example
// The most recently published 6 reports in the Featured category
const category = "Featured";
const fetchReports = (category) => fetchJson(`/api/v1/products?CategoryPaths=${category}&OrderBy=Published.desc&Skip=0&Take=6&IncludeUnlicensed=true&IncludePrivate=false&IncludeComingSoon=true&IncludeArchived=false&IncludeDisabled=false&MatchAllWords=false`)
// all the categories that a product is in
const fetchCategories = (productApiLink) => fetchJson(`${productApiLink}/categories?includeHidden=false`)
// basic metadata for a product
const fetchMetadata = (productApiLink) => fetchJson(`${productApiLink}?includeExtendedMetadata=false&includeToc=false`)

// fetch the list of reports in the specified category
fetchReports(category).then(reports => {
// get the number of reports returned
//const length = Object.keys(reports).length;
// get more information for the last 6 reports in the category
for (let i = 0; i < 6; i++) {
// create the elements for the grid. Each div is a grid element that contains
// an image (uploaded via the file explorer), an overlay of the subcategory it is in
// a paragraph of description and a link to the report.
let div = document.createElement('div');
div.id = 'd'+i;
let plink = document.createElement('p');
let link = document.createElement('a');
let img = document.createElement('img');
let poverlay = document.createElement('p');
let ptitle = document.createElement('p');
let p = document.createElement('p');

ptitle.textContent = reports.products[i].title;
ptitle.className = "title";
// fetch all the categories the product is in
fetchCategories(reports.products[i].apiLink).then(categories => {
// convert the categories array to a string, adding a comma at the end
// so each category-subcatgory substring has the same pattern
let categoriesstring = categories.toString() + ",";
// Find where the first category substring starts in the list
let start = categoriesstring.search(category);
// Find the end of the substring by finding the next comma
let end = categoriesstring.indexOf(",", start);
// Since categories and subcategories are separated by a - we can get
// the subcat substring by taking the bit after the -
subcat = categoriesstring.slice(start+category.length+1,end);
// create the image the referenced images in the File Explorer
// have the naming convention based on the subcategory names
img.src = `/Files/homeTabs/${subcat}.jpg`;
// create the element for the image overlay text to display the subcategory
poverlay.textContent = subcat;
poverlay.className = "top-right";

// create the link
link.textContent = "Read More"
link.href = `../reportaction/${reports.products[i].productCode}/Toc`
plink.appendChild(link);
})

// create the paragraph element for the description
let pdesc = document.createElement('p');
// fetch the metadata for the current report
fetchMetadata(reports.products[i].apiLink).then(metadata => {
// take first 20 words of description, stripping out any html tags
pdesc.textContent = metadata.description.replace(/(<([^>]+)>)/gi, "").split(/\s+/).slice(0,20).join(" ") + "...";
})

// putting it all together
div.appendChild(img);
div.appendChild(poverlay);
div.appendChild(ptitle);
div.appendChild(pdesc);
div.appendChild(plink);
main.appendChild(div);

}
});

</script>