Search and Replace: Getting Started with the Notion API SDK for JavaScript
Tags: javascript, notion, tutorial, api
Published: 2022-12-29 09:31:56

Notion is a powerful tool for creating and managing a variety of digital content, such as notes, articles, and databases. However, one feature that many users have requested for a long time is the ability to search and replace text within Notion documents and pages.

I have a lot of documents in my Notion databases and often need to search through all of the pages and replace specific words and phrases. 

For example, I have a table with instructions on how to work with remote repositories, and I want to replace all instances of **"GitHub"** with **"GitLab"** in every document:

![Notion database](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ttgxr4oikswzo94sghs6.png)

In this post, I'll show you how to create a simple workaround to search for text and replace it in multiple documents inside a Notion database. All you need is Node.js installed on your machine.

> Link to a GitHub repo with the full code: https://github.com/andreiparfenov/search-and-replace-notion-api

> Notion API Reference: https://developers.notion.com/reference/intro

This is a very simple workaround where I mostly tried to experiment with the Notion API. **Please note that I was only able to implement a solution for Notion text blocks or paragraphs.** My script will not work for headings, code snippets, etc. because different block types have different object properties in the Notion API. The code is also far from perfect, so feel free to leave your suggestions for improvement. Also, share about your experience working with the Notion API.

Here's a step-by-step instruction.

## Set up Notion

Assuming that you have an account on Notion, go to [the "My integrations" page](https://www.notion.so/my-integrations). Click the "New integration" button. Create an internal integration with the ability to read, update, and insert content:

![Create a Notion integration](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lmogghs9248x5nt0nun0.png)

Go to the database you want to work with, press "Settings" (three dots), and then click "Add connections". Choose the newly created integration.

## Set up the Node.js app

Notion has a JavaScript client for the API. We'll create a folder for the new Node.js project and initialize `package.json` inside:

```
mkdir notion-search-and-replace
npm init
```
Now that we have the `package.json` file, let's install a package with the Notion SDK:

```
npm install @notionhq/client
```

Create a Node.js file (I created `app.js`) in the project folder and initialize the Notion client:

```javascript
const { Client } = require("@notionhq/client");

const notion = new Client({
  auth: process.env.NOTION_TOKEN,
});
```

`NOTION_TOKEN` is your internal integration token from Notion. If you share your code with others, make sure that it's kept in `.env` as well.

Next, specify the value that the script will search for and what it should be replaced with. I want to replace all occurrences of **"GitHub"** with **"GitLab"** in my text:

```javascript
const searchValue = "GitHub";
const newValue = "GitLab";
```

Create an entry point function:

```javascript
(async () => {
  const db = await notion.databases.query({
    database_id: process.env.NOTION_API_DATABASE,
  });

  for (const page of db.results) {
    // we'll access the page's blocks here and update them
  }
})();
```
In this function, we access the database by its ID and create a loop to iterate over the pages (the `results` property) inside the database.

When we access each page from the database, we'll need to access the page's blocks. Let's do it in a separate function:

```javascript
async function retrieveBlocks(pageId) {
  const page = await notion.blocks.children.list({
    block_id: pageId,
  });

  return page.results;
}
```
On Notion, a page is also a block. That's why in the code above we access the `children` property of `blocks`.

We'll need to go one more level down and access the text inside each block. Let's add the following function:

```javascript
async function findAndReplace(blocks) {
  for (const block of blocks) {
    if (!block.paragraph) continue;
    const textItems = block.paragraph.rich_text;
    const newTextItems = textItems.map((item) => {
      const selectedText = item.text.content;
      const newText = selectedText.includes(searchValue)
        ? selectedText.replaceAll(searchValue, newValue)
        : selectedText;
      item.text.content = newText;
      return item;
    });
    // we'll update the corresponding block here
  }
}
```
In this function, we use the `paragraph.rich_text` property, which is an array of objects. Yes, the text content is actually an array where elements are split by their formatting style. It may sound complicated, but here's an example:

I **love** `GitHub`.

If this is a Notion paragraph, it will have four elements in the `rich_text` array:

1. "I" - non-formatted
2. "love" - bold
3. "GitHub" - code
4. "." - non-formatted

Read more about `rich-text` in [the Notion API's docs](https://developers.notion.com/reference/rich-text).

Then we use `map()` to replace every needed instance.

Finally, let's update the entire block and insert the new text items:

```javascript
async function updateBlock(block, newTextItems) {
  const selectedBlock = await notion.blocks.update({
    block_id: block.id,
    paragraph: {
      rich_text: newTextItems,
    },
  });
}
```
Update the `findAndReplace()` function by calling `updateBlock()` at the very end of the `for...of` loop:

```javascript
async function findAndReplace(blocks) {
  for (const block of blocks) {
    // all the previous code
    await updateBlock(block, newTextItems);
  }
}
```
Also, update the entry point function:

```javascript
(async () => {
  const db = await notion.databases.query({
    database_id: process.env.NOTION_API_DATABASE,
  });

  for (const page of db.results) {
    // call functions retrieveBlocks and findAndReplace here
    const blocks = await retrieveBlocks(page.id);
    findAndReplace(blocks);
  }
})();
```

Run the code with the following command:

```
node app.js
```

The script will replace all instances of **"GitHub"** in all the documents inside the database:

![Page before running the script](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qa60nz2jsq599kq3jnuy.png)
![Page after running the screen](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hdzc0eoyptaxs4byqh5u.png)

I hope you find this useful. Share how you use the Notion API to automate your work. 🤖