{ Akbar NoorMohamed }

Using GraphQL with Contentful CMS

Mar 02, 2025
     #learning  
4 minutes

In the earlier blog post, we explored how to use Contentful with a basic JS/REST integration. Now, let’s take a quick look into using GraphQL with Contentful, which provides more efficiency and flexibility when fetching content.

GraphQL simplifies managing and querying content efficiently. It provides the flexibility of fetching only the data you need, instead of dealing with unnecessary payloads, GraphQL is the perfect solution when working with Contentful.

Getting Started with GraphQL in Contentful

First, we need to set Contentful space and define a content model. I created a simple Blog Post model with fields like title, body, author, publishedDate, slug, and tags. After adding some dummy content, I was ready to query it using GraphQL.

To interact with Contentful’s GraphQL API, we require:

  • A Contentful space ID
  • A Content delivery API key
  • The GraphQL endpoint: https://graphql.contentful.com/content/v1/spaces/{SPACE_ID}

Querying Content with GraphQL

Here’s a simple JS example that fetches blog posts: https://github.com/Akbarsait/akbarsaitblogposts/blob/main/code-snippets/contentful-graphql-example.js

const spaceId = 'your_space_id';
const accessToken = 'your_access_token';
const query = `{
  blogPostCollection {
    items {
      title
      slug
      body
      author
      publishedDate
      tags
    }
  }
}`;

fetch(`https://graphql.contentful.com/content/v1/spaces/${spaceId}`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    Authorization: `Bearer ${accessToken}`,
  },
  body: JSON.stringify({ query }),
})
  .then((response) => response.json())
  .then((data) => console.log(data.data.blogPostCollection.items))
  .catch((error) => console.error("Error fetching GraphQL data:", error));

This query fetches all blog posts along with their title, slug, body, author, published date, and tags. What I love about GraphQL is that you can easily modify the query to retrieve only the fields you need—no extra data cluttering the response.

Displaying Content on a Web Page

To make things more practical, let’s display the fetched blog posts inside an HTML page: https://github.com/Akbarsait/akbarsaitblogposts/blob/main/code-snippets/contentful-graphql-example.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Blog Posts</title>
</head>
<body>
    <h1>My Blog</h1>
    <div id="blog-container"></div>

    <script>
        const spaceId = 'your_space_id';
        const accessToken = 'your_access_token';
        const query = `{
            blogPostCollection {
                items {
                    title
                    slug
                    body
                    author
                    publishedDate
                    tags
                }
            }
        }`;

        fetch(`https://graphql.contentful.com/content/v1/spaces/${spaceId}`, {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
                Authorization: `Bearer ${accessToken}`,
            },
            body: JSON.stringify({ query }),
        })
        .then((response) => response.json())
        .then((data) => {
            const blogContainer = document.getElementById("blog-container");
            data.data.blogPostCollection.items.forEach(post => {
                const postElement = document.createElement("div");
                postElement.innerHTML = `
                    <h2>${post.title}</h2>
                    <p><strong>Author:</strong> ${post.author}</p>
                    <p><strong>Published Date:</strong> ${post.publishedDate}</p>
                    <p><strong>Tags:</strong> ${post.tags.join(", ")}</p>
                    <p>${post.body}</p>
                    <p><strong>Slug:</strong> ${post.slug}</p>
                `;
                blogContainer.appendChild(postElement);
            });
        })
        .catch(error => console.error('Error fetching content:', error));
    </script>
</body>
</html>

Let’s fetch data with some scenario based examples.

To fetch only the blog posts marked as “featured”, we can modify your query like this:

const query = `{
  blogPostCollection(where: { featured: true }) {
    items {
      title
      author
      publishedDate
    }
  }
}`;

To fetch blog posts based on a specific category, use:

const query = `{
  blogPostCollection(where: { category: "Technology" }) {
    items {
      title
      slug
      category
    }
  }
}`;

Fetching Blog Posts by Tags

To fetch blog posts that contain a specific tag:

const query = `{
  blogPostCollection(where: { tags_contains: "GraphQL" }) {
    items {
      title
      tags
    }
  }
}`;

Fetching Blog Posts Between Two Dates

To get blog posts published between two dates:

const query = `{
  blogPostCollection(where: { publishedDate_gte: "2023-01-01", publishedDate_lte: "2023-12-31" }) {
    items {
      title
      publishedDate
    }
  }
}`;

Why Use GraphQL with Contentful?

  • Efficient queries: Get only the data you need, reducing API response sizes.
  • Easier frontend integration: Fetch structured content without multiple API calls.
  • More flexibility: Modify queries easily without backend changes.

So far, my experience with GraphQL and Contentful has been fantastic. It streamlines data fetching and makes content management way more efficient. If you’re working on a content-driven app or website, I’d highly recommend giving it a shot!

Let me know if you try this out or run into any issues! 🚀

Title Photo by Akbar Noormohamed on Unsplash