Sanity Mutations: Data Manipulation Made Easy
Tags: sanity, nextjs, react, blog
Published: 2024-06-03 08:30:01

Let’s start by getting acquainted with [Sanity](https://www.sanity.io/). It’s not just another content management system; it’s a versatile platform that empowers developers to shape and control their digital content effortlessly. Beyond being a content management platform, it’s a dynamic tool that allows developers to effortlessly shape and manage their digital content. In this blog post, we’re embarking on a journey to explore how you can seamlessly interact with Sanity’s data through its API, thereby unlocking endless possibilities for dynamic content management.

### Navigating the World of Sanity Mutations

For developers, the quest for efficient data management tools is never-ending. Enter the [Sanity Mutations API](https://www.sanity.io/docs/http-mutations), a transformative force in the realm of content manipulation. This blog post serves as your trusted guide to unlocking the full potential of Sanity's mutation capabilities. We'll navigate each step together, ensuring that by the end, you'll be proficiently harnessing the [Sanity Mutations API](https://www.sanity.io/docs/http-mutations) to sculpt and reshape your data with precision.

### What Are Sanity Mutations?

In the realm of content management and data manipulation, Sanity Mutations serve as a powerful mechanism that enables developers to create, modify, and delete documents directly through the Sanity API. These mutations are the core building blocks for orchestrating changes to your data within the Sanity platform. Whether you need to create entirely new documents, update existing ones, or remove specific entries, Sanity Mutations provide the tools to achieve these tasks programmatically. What sets Sanity Mutations apart is their transactional nature, ensuring that a sequence of mutations is executed atomically. This means that if one mutation in the sequence fails, none of the mutations will take effect, ensuring data consistency and reliability. Understanding and harnessing Sanity Mutations is fundamental for developers seeking fine-grained control over their content within the Sanity ecosystem.

Let's explore the core mutation types:

> 1. **Create**: Add a new document to Sanity by providing its type and attributes.

> 2. **CreateOrReplace**: Create or replace a document. It updates content if it exists, or creates a new one if not.

> 3. **CreateIfNotExists**: creates a new document, but will silently fail if the document already exists. It is otherwise identical to create.

> 4. **Delete**: Remove a document by specifying its ID. Even if it doesn't exist, it's considered a success.

> 5. **Patch**: Update an existing document with operations like "set," "unset," and more. Fails if the document doesn't exist.

These mutations offer essential tools for adding, modifying, and deleting data in Sanity programmatically, providing precise control over your content.

### Why We Need the Sanity Mutations API and Its Significance:
In modern web and application development, the need for efficient data manipulation and content management is paramount. This is where the Sanity Mutations API comes into play as a vital tool for developers. Without it, manual data entry and content updates would be the norm, leading to time-consuming processes prone to errors. The Sanity Mutations API automates these tasks, enabling developers to seamlessly create, modify, or delete documents through code. This automation is crucial for content-rich websites, e-commerce platforms, and other digital ventures. Moreover, the API's utility extends beyond data manipulation—it empowers developers to implement dynamic features and responsive content updates in real time. For instance, it facilitates instant product availability updates in e-commerce platforms and ensures timely publishing and content edits in blogs and news websites. Beyond these benefits, developers can use the API to create intricate workflows, automate content migrations, and seamlessly integrate Sanity with other services. In essence, the Sanity Mutations API streamlines content management, enhances user experiences, and enables the development of dynamic, data-driven applications across various industries and use cases, making it an indispensable asset for modern, responsive digital experiences.


### Expanding on Sanity Mutations: A Practical Guide to Tracking Blog Post Views
Now that we've covered the fundamentals of Sanity Mutations, including what they are and the various types of mutations along with their use cases, let's roll up our sleeves and dive into the hands-on process of implementing a view tracking system for your blog posts.

> Note: This tutorial assumes that your blog is built using Next.js version 13.4 and styled with Tailwind CSS. If you're using a different framework or styling library, the code examples may need to be adapted accordingly. However, the fundamental concepts of implementing view tracking with Sanity Mutations remain applicable regardless of your technology stack.

#### Step 0: Add the 'viewCount' Field to Your Post Schema
Before we dive into the implementation of view tracking using Sanity Mutations, it's essential to ensure that your blog post schema includes a 'viewCount' field. This field will store and track the number of views for each blog post.


To add the 'viewCount' field to your Sanity Studio schema, follow these steps:

1. **Open your Sanity Studio project.**
2. **Navigate to the schema definition for your blog posts. This is typically found in the "schemas" directory of your Sanity folder.**
3. **Inside the schema definition for your blog posts, add the following code to define the 'viewCount' field**:

```
import { defineField, defineType } from "sanity";

export default defineType({
  name: "post",
  title: "Post",
  type: "document",
  fields: [
    //...other fields.
    defineField({
      name: "viewsCount",
      title: "Views Count",
      type: "number",
      hidden: true,
      initialValue: 1,
    })
  ],

  //preview code
});

```
  
### Step 1: Configure Environment Variables
To get started with implementing view tracking using Sanity Mutations, you'll need to configure your environment variables. These variables include the

> NEXT_PUBLIC_SANITY_PROJECT_ID,

> NEXT_PUBLIC_SANITY_DATASET,

> NEXT_PUBLIC_SANITY_API_TOKEN.

These values are essential for authenticating and interacting with the Sanity API.

Here's how to set up these environment variables:

**1. Project ID**: Obtain your Sanity project ID from Sanity Studio. Follow these steps:

- Open your Sanity Studio project.
- In the Sanity Studio, navigate to the "Settings" section.
- In the "API" tab, you will find your project ID. Copy this ID.


![ProjectId location in Sanity project dashboard](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u1fd4vwjf1vmuwssszwo.jpg)


**2. Dataset:** Similarly, find your dataset name within the Sanity Studio:

- In the Sanity Studio, navigate to the "Settings" section.
- In the "API" tab, you will find your dataset name. Copy this name.
- it's default is "production"

**3. API Token**: To secure your API requests, you'll need an API token. Create one in the Sanity Studio:
- In the Sanity Studio, navigate to the "Settings" section.
- In the "API" tab, click on "Tokens."
- Generate a new token, making sure to grant it the necessary permissions for mutations.


![API token location in Sanity project dashboard](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tuad86x5twmf5bwdhu5r.jpg)

**4.** Now that you have the required values, create or update your .env.local file in your Next.js project directory. Add the following lines, replacing YOUR_PROJECT_ID, YOUR_DATASET, and YOUR_API_TOKEN with the values you obtained in the previous steps:

```
NEXT_PUBLIC_SANITY_PROJECT_ID=YOUR_PROJECT_ID
NEXT_PUBLIC_SANITY_DATASET=YOUR_DATASET || "production"
NEXT_PUBLIC_SANITY_API_TOKEN=YOUR_API_TOKEN

```

### Step 2: Create the Component for Handling Post Views Count
In this step, we'll create a React component called HandlePageViewCount that takes a post object as a prop. This component plays a pivotal role in our view tracking system. It's responsible for the crucial task of incrementing the view count of a blog post using Sanity Mutations. Additionally, it takes care of formatting the view count for a user-friendly display. Let's delve into the details of how this component accomplishes these tasks.

#### Step 2.1: Define a function to increment post views count

```
const incrementPostViews = useCallback(
  (postId: string) => {
    // Code for updating the viewsCount field will go here
  },
  [post]
);

```

In this step, we define a function **incrementPostViews **using the **useCallback **hook. This function will be responsible for updating the **viewsCount **field of a blog post.

#### Step 2.2: Define a mutation to update the view count

```
const mutations = [
  {
    patch: {
      id: postId,
      set: {
        viewsCount: post.viewsCount ? post.viewsCount + 1 : 2, // Ensure post is defined
      },
    },
  },
];

```

Here, we create a mutation object that uses the '**patch**' mutation type. It specifies which document to update (identified by its **id**) and what changes to make. In this case, we increment the **viewsCount **field by 1. We also provide a fallback value of 2 if the **viewsCount **is not defined to ensure it starts from a minimum value.

#### Step 2.3: Send a mutation request to Sanity API

```
fetch(
  `https://${process.env.NEXT_PUBLIC_SANITY_PROJECT_ID}.api.sanity.io/v2021-06-07/data/mutate/${process.env.NEXT_PUBLIC_SANITY_DATASET}`,
  {
    method: "post",
    headers: {
      "Content-type": "application/json",
      Authorization: `Bearer ${process.env.NEXT_PUBLIC_SANITY_API_TOKEN}`,
    },
    body: JSON.stringify({ mutations }),
  }
)
  .then((response) => response.json())
  .then((result) => console.log(result))
  .catch((error) => console.error(error));

```

This part of the code sends a **POST **request to the Sanity API to execute the mutation we defined earlier. It includes the mutation array in the request body and uses the provided environment variables (**NEXT_PUBLIC_SANITY_PROJECT_ID**, **NEXT_PUBLIC_SANITY_DATASET**, and **NEXT_PUBLIC_SANITY_API_TOKEN**) for authentication and endpoint configuration.

#### Step 2.4: Trigger the incrementPostViews function on component mount

```
useEffect(() => {
  incrementPostViews(post?._id);
}, [incrementPostViews, post?._id]);

```

The **useEffect** hook ensures that the **incrementPostViews **function is called when the component is mounted. It passes the **post?._id** as a dependency to track which blog post's view count should be incremented.


**Step 2.5 to 2.7:** These steps involve formatting the view count and rendering it in your component, which are essential but don't directly relate to the mutation process.


Now that we've thoroughly examined each part of the HandlePostViewCount component and its role in view tracking, let's present the complete code. This code encapsulates all the functionality we've discussed, from incrementing post views to formatting the count for display. Feel free to integrate this component into your project to enhance user engagement with view tracking.

```
"use client";

import { Post } from "@/typings";
import { useCallback, useEffect } from "react";

type Props = {
  post: Post;
};

function HandlePageViewCount({ post }: Props) {
  const incrementPostViews = useCallback(
    (postId: string) => {
      const mutations = [
        {
          patch: {
            id: postId,
            set: {
              viewsCount: post.viewsCount ? post.viewsCount + 1 : 2, // Ensure post is defined
            },
          },
        },
      ];

      fetch(
        `https://${process.env.NEXT_PUBLIC_SANITY_PROJECT_ID}.api.sanity.io/v2021-06-07/data/mutate/${process.env.NEXT_PUBLIC_SANITY_DATASET}`,
        {
          method: "post",
          headers: {
            "Content-type": "application/json",
            Authorization: `Bearer ${process.env.NEXT_PUBLIC_SANITY_API_TOKEN}`,
          },
          body: JSON.stringify({ mutations }),
        },
      )
        .then((response) => response.json())
        .then((result) => console.log(result))
        .catch((error) => console.error(error));
    },
    [post],
  );

  useEffect(() => {
    incrementPostViews(post?._id);
  }, [incrementPostViews, post?._id]);

  const formatViewsCountFunc = () => {
    const viewsCount = post?.viewsCount || 1;
    if (viewsCount < 1000) {
      return viewsCount.toString();
    } else if (viewsCount < 1000000) {
      return (viewsCount / 1000).toFixed(2) + "K";
    } else {
      return (viewsCount / 1000000).toFixed(2) + "M";
    }
  };

  let formatViewsCount = formatViewsCountFunc();

  return (
    <div className="text-sm text-gray-400 lg:text-base">
      {formatViewsCount} {formatViewsCount > "1" ? "views" : "view"}
    </div>
  );
}

export default HandlePageViewCount;

```

### Step 3: Implementing Post View Tracking
Now that we've successfully created the HandlePageViewCount component to handle post view tracking, it's time to implement it within your Post component. This step will guide you through the process of integrating the view tracking functionality into your blog posts.

```
//...Other imports
import HandlePageViewCount from "@/components/blog-Components/HandlePageViewCount";

type Props = {
  params: { slug: string };
};

export default async function Post({ params: { slug } }: Props) {
  const post = await fetchPost(slug);

  return (
    <div>
    <HandlePageViewCount post={post} />
    // ...Other code to render...
    </div>
  );
}
```

By adding the HandlePageViewCount component to your Post component, you're enabling the tracking of post views for each blog post.

1. **Enhance User Engagement:** With view tracking in place, your readers can now see how popular a post is, fostering a sense of community and encouraging more interactions.
2. **Monitor Post Performance:** This feature enables you to gather valuable insights into your content's performance and helps you tailor your content strategy based on reader engagement.

That’s it for our journey into the world of Sanity Mutations API. We’ve seen how it empowers developers to shape their digital content and even build a view tracking system for blog posts. This not only enhances user engagement but also provides valuable insights into content performance. Remember, the power to create, update, or delete documents in Sanity is now at your fingertips.


We hope you have enjoyed this tutorial and learned something new. If you want to learn more about Sanity and its features, check out the [official documentation](https://www.sanity.io/docs/http-mutations) and the community resources. You can also join the [Sanity Slack channel](https://slack.sanity.io/) to connect with other developers and get support.

Thanks for joining us on this adventure, and as always, happy coding!