In today’s fast-paced digital environment, having a powerful search capability within your content management system (CMS) is critical. Combining Storyblok and BatteryIncluded offers a robust solution for building a customized and AI-powered search experience. In this article, we’ll walk you through how to seamlessly index your Storyblok content into BatteryIncluded using Node.js, with just a few lines of code.
Setting Up a Node.js Project
Before we dive into the implementation, make sure that **Node.js** is installed on your machine. Once you’re ready, open a terminal and create a new directory for your project:
mkdir storyblok-to-batteryincluded && cd storyblok-to-batteryincluded
Next, initialize a new Node.js project:
npm init
Installation of Required Packages
You’ll need two main packages for this project: `storyblok-js-client` to interact with the Storyblok API, and `axios` to help with HTTP requests. Install them using the following commands:
Install Storyblok Universal JS client SDK to load data from Storyblok
npm install storyblok-js-client
Install axios so we can use axios.all to load all entries from Storyblok
npm install axios
Configuration
Now, let’s create a new file called **`index.js`**. This is where all the indexing magic will happen. The following code will guide you through the entire process:
const StoryblokClient = require(’storyblok-js-client‘);
const axios = require(‚axios‘);
const STORYBLOK_CONTENT_DELIVERY_API_KEY = ‚YOUR_STORYBLOK_API_KEY‘;
const BI_API_KEY = ‚YOUR_BI_API_KEY‘; // private integration key
const BI_COLLECTION = ‚customer.yourcollection.demo‘;
const storyblok = new StoryblokClient({ accessToken: STORYBLOK_CONTENT_DELIVERY_API_KEY });
const options = {
starts_with: ‚articles/‘, // adjust as per your folder structure
per_page: 100, // max 100 entries per page
page: 1,
version: ‚draft‘ // switch to ‚published‘ when ready
};
// Retrieve total number of pages from Storyblok
storyblok.get(‚cdn/stories/‘, options).then(async (res) => {
const total = res.headers.total;
const maxPage = Math.ceil(total / options.per_page);
let contentRequests = [];
for (let page = 1; page <= maxPage; page++) {
contentRequests.push(storyblok.get(‚cdn/stories/‘, { …options, page }));
}
// Fetch all entries from Storyblok
Promise.all(contentRequests)
.then(async (responses) => {
let records = responses.map(response => response.data.stories).flat();
// Use Storyblok UUID as objectID
records.forEach(record => {
record.id = record.uuid;
});
// Convert to NDJSON format
let data = records.map(record => JSON.stringify(record)).join(‚\n‘);
// Send the records to the BatteryIncluded API
axios.post(`https://api.batteryincluded.io/api/v1/collections/${BI_COLLECTION}/documents/import`, data, {
headers: {
‚Content-Type‘: ‚application/x-ndjson‘,
‚X-BI-API-KEY‘: BI_API_KEY
}
})
.then(response => console.log(‚Data indexed:‘, response.data))
.catch(err => console.error(‚Error posting data to BI:‘, err));
})
.catch(err => console.error(‚Error fetching articles:‘, err));
})
.catch(err => console.log(‚Error fetching stories:‘, err));
Running the Indexer
Once you’ve added the above code and updated the configuration with your own API keys, you’re ready to index your content. Run the following command to start indexing:
node index.js
This will send all your Storyblok content to BatteryIncluded and make it searchable through their high-performance API.
Advanced Features: Filtering Content in Storyblok
Instead of solely relying on BatteryIncluded for filtering, you can take advantage of Storyblok’s Content Delivery API with its `filter_query` feature to retrieve specific data directly from Storyblok. Here’s an example of how to get all products with a price greater than 100:
storyblok.get(‚cdn/stories/‘, {
starts_with: ‚products/‘,
filter_query: {
price: {
gt_int: 100
}
}
})
.then(response => console.log(response))
.catch(error => console.log(error));
This is a powerful feature that can eliminate the need for additional indexing when filtering through Storyblok directly.
Summary
With just a few lines of code, you can seamlessly index your Storyblok content into BatteryIncluded. Whether you’re building a simple search interface or an advanced AI-powered search system, the combination of **Storyblok** and **BatteryIncluded** offers flexibility and performance.
How to Integrate BatteryIncluded with Your Headless CMS
If your project requires more advanced search functionalities, BatteryIncluded is the way to go. It provides customizable search experiences, optimized for AI-driven performance. You can manipulate your data structure, index Storyblok objects as they are, or even crawl live pages.
In most cases, you’ll want to use Storyblok’s **webhooks** to trigger the indexing script automatically upon content updates, ensuring that your search index is always up-to-date.
Triggering the Indexing Script with Webhooks
You can configure Storyblok’s webhooks to trigger your indexing function whenever content is updated. This way, you’ll only reindex the changed content, minimizing API calls and reducing server costs.
Alternatively, you can also create manual triggers in Storyblok’s interface using the **Task Manager**, which can be useful when performing bulk updates or the initial indexing of your content.
Conclusion
Combining Storyblok with BatteryIncluded allows you to build powerful search interfaces tailored to your needs. Whether you choose to index content directly, manipulate it, or crawl live pages, this guide offers flexible options to suit different use cases. By leveraging Storyblok’s webhooks, you can keep your index fresh and relevant with minimal effort.
Happy coding!