How to Feature a Blog Post in BigCommerce using GraphQL | Arctic Leaf
In particular, this post will guide you through the process of featuring a blog post (or multiple posts), so that it will appear at the top of your blog page, even though it may not necessarily be the newest.
Note: for the purpose of this guide, we will be developing using the Stencil CLI on a store with Cornerstone 6.15. The same concepts should apply to any Stencil theme, but the file paths may differ slightly. Because this guide requires editing JavaScript and adding new files, having the Stencil CLI installed on your machine is a requirement.
Step By Step Guidance
1: Feature the post.
In the admin panel of your store, navigate to Storefront → Blog. Find the post you wish to feature and click on the title to go into the editor. Simply add “featured” as a tag on this post. You can tag as many posts as you like.
2: Edit the blog.html file.
The first step will be to set up our HTML. This is a fairly straightforward step, simply requiring the addition of a single HTML tag to our blog.html template file. Navigate to templates/pages/blog.html and add the following line of code just above the loop for the blog posts ({{#each blog.posts}}): <div class="featured-posts" data-featured-posts></div>.
Note that you can place this code anywhere you like within the blog.html file. This is where the blog posts will be injected with JavaScript. While data attributes are not the only way to find an element in which to inject our code, it is good practice to use them over class- or id-selectors with JavaScript.
3: Install GraphQL if your theme does not yet have it
To install GraphQL and a GraphQL client, run npm i @apollo/client graphql
. Then, ensure the following line is somewhere in your layout/base.html file: `{{~inject 'storefrontAPIToken' settings.storefront_api.token}}`.
4: Define the route for the Blog’s JS file.
In app.js, we want to declare a file to load on the blog page. We do this by changing `blog: noop,`
to `blog: () => import('./theme/blog'),`
. Note: if you are running stencil when you make this change, the code will error out as the blog.js file does not exist just yet!
5: Create the Blog’s JS file.
Create a new file at the path assets/js/theme/blog.js. The code for this file will be:
```
import PageManager from './page-manager';
import getBlogPosts from './common/get-blog-post';
export default class Blog extends PageManager {
constructor(context) {
super(context);
this.context = context;
}
onReady() {
getBlogPosts(this.context.storefrontAPIToken);
}
}
```
6: Add the get-blog-post.js file
Add file at the following location: assets/js/theme/common/get-blog-post.js
Here are the contents of the file:
import { ApolloClient, gql, InMemoryCache } from '@apollo/client/core';
/**
* Get the one-time purchase option for a product.
*
* @param {string} token - The store's access token.
*
* @returns {Promise<object|undefined>} The one-time purchase option.
*/
export default async (token) => {
const client = new ApolloClient({
cache: new InMemoryCache(),
headers: { Authorization: `Bearer ${token}` },
uri: '/graphql',
});
const query = gql`query GetBlogPosts {
site {
content {
blog {
description
posts(first: 50) {
edges {
node {
name
plainTextSummary
tags
author
publishedDate {
utc
}
thumbnailImage {
altText
url(width: 200)
}
path
}
}
}
}
}
}
}`;
try {
const data = await client.query({ query });
if (!data || !data.data || !data.data.site || !data.data.site.content || !data.data.site.content.blog || !data.data.site.content.blog.posts || !data.data.site.content.blog.posts.edges) {
return;
}
const featuredPosts = data.data.site.content.blog.posts.edges.filter(({ node }) => node.tags.includes('featured'));
let html = '';
featuredPosts.forEach(post => {
const pnode = post.node;
const postImage = pnode.thumbnailImage ? `
<div class="blog-post-figure">
<figure class="blog-thumbnail">
<a href="${pnode.path}">
<img src="${pnode.thumbnailImage.url}" alt="${pnode.thumbnailImage.altText}">
</a>
</figure>
</div>
` : '<div class="blog-post-figure"></div>';
const postTags = pnode.tags.map(tag => `<li class="tag"><a href="/blogs/news/tag/${tag}">#${tag}</a></li>`).join('');
const formatter = new Intl.DateTimeFormat('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric',
});
html += `
<article class="blog featured-post">
${postImage}
<div class="blog-post-body">
<header class="blog-header">
<h2 class="blog-title">
<a href="${pnode.path}">${pnode.name}</a>
</h2>
<p class="blog-date">${pnode.author ? `Posted by ${pnode.author} on` : ''} ${formatter.format(new Date(pnode.publishedDate.utc))}</p>
</header>
<div class="blog-post">
${pnode.plainTextSummary} … <a href="${pnode.path}" aria-label="${pnode.name} Read More">Read More</a>
</div>
<ul class="tags">
${postTags}
</ul>
</div>
</article>
`;
});
document.querySelector('[data-featured-posts]').innerHTML = html;
} catch (error) {
return Promise.reject(error);
}
};
7: Customize.
Now the fun part! The code up to this point will simply make another post that looks almost the same as all the others, but this is our chance to change that. You can target the “featured-posts” class in your CSS to separate this section from the rest. You can also alter the HTML of the post itself to your liking. In the html variable, feel free to move elements around, add extra classes, style these elements, place the featured posts into a carousel. The possibilities are endless!
Wrapping it all up
While the BigCommerce built-in blog is not nearly as robust as platforms built specifically for blogging (IE. Wordpress), the pros of utilizing it can sometimes outweigh the cons. You can definitely extend the functionality of the built-in blog to meet many possible client needs. While this post touched on one specific item, this same methodology can certainly be used to extend additional areas. Feel free to leave a comment to discuss how you used it!
If at any point you get stuck during these steps, remember that we are only adding 2 files and modifying 5 others. Here is a screenshot of the changes: