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:
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. Click the "New integration" button. Create an internal integration with the ability to read, update, and insert content:
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:
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:
const searchValue = "GitHub";
const newValue = "GitLab";
Create an entry point function:
(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:
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:
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:
- "I" - non-formatted
- "love" - bold
- "GitHub" - code
- "." - non-formatted
Read more about rich-text
in the Notion API's docs.
Then we use map()
to replace every needed instance.
Finally, let's update the entire block and insert the new text items:
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:
async function findAndReplace(blocks) {
for (const block of blocks) {
// all the previous code
await updateBlock(block, newTextItems);
}
}
Also, update the entry point function:
(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:
I hope you find this useful. Share how you use the Notion API to automate your work. 🤖
Top comments (0)