Wordpress to Builder media Migration Script

Hi all,

We are currently working on migrating our blog from wordpress to builder.io. I wanted to share a process that helped me migrate all media images from wordpress over to builder.io.

I first downloaded the ghost export plugin within wordpress. Then downloaded the WP Imp Exp plugin in wordpress to help download the categories. The ghost export plugin I downloaded was used to download my baseJSON file (which included all of the content I will eventually upload to builder.io) The WP Imp Exp helped me get a csv of all blog posts and their categories. I wrote a script that matched each JSON object with the csv id and appended the category onto the JSON file.

I used Builder.io’s Upload API to upload the media. However, wordpress url links aren’t able to upload directly to the API, so I had to write a script that would: * code at bottom of post

  1. download each link to my cp
  2. upload each link to builder.io using builder.io’s Upload API
  3. Take the new url in builder and update the JSON object with the new URL. This ensures when I upload the JSON object, each upload will have the url within my eventual blog data model to reference the correct URL.

I will post a new post detailing how I upload all of the content of the blog posts. But first started with the media so I can get the JSON object.

High level I accomplished:

  1. Uploading all media to builder
  2. Updating my eventual JSON import file into builder to have the new updated media links for each blog post.

Please reach out with any questions and I hope this helps someone.

/ NEW downloads
import fetch from 'node-fetch';
import fs from 'fs/promises';
import path from 'path';
import axios from 'axios';

// Function to download image from the URL

async function downloadImage(imageURL, objectId, __dirname) {
    try {
        if (!imageURL) {
            console.log(`Skipping download for object with ID ${objectId} as featureImage is null.`);
      const response = await axios({
        url: imageURL,
        method: 'GET',
        responseType: 'stream'
      const fileName = `${objectId}.jpg`; // Save images with the format "objectID.jpg"
      const downloadPath = path.join(__dirname, '..', '..', 'blogImages', fileName);

      await fs.writeFile(downloadPath, response.data, 'binary');

      return downloadPath;
    } catch (error) {
      throw new Error('Failed to download image: ' + error.message);

  // Function to upload image to the API
async function uploadImage(downloadPath, objectId) {
    try {
        var bitmap = await fs.readFile(downloadPath); // Read file as binary data
        var requestOptions = {
            method: 'POST',
            headers: {
                'Authorization': 'Bearer **enter own private key**',
                'Content-Type': 'image/jpeg', // Specify the correct content type
            body: bitmap,
            redirect: 'follow',

        const response = await fetch(`https://builder.io/api/v1/upload?name=${objectId}.jpg&folder=**enter folder's id**`, requestOptions);
        const data = await response.json();

        return data.url;
    } catch (error) {
        throw new Error('Failed to upload image: ' + error.message);

// Main function to initiate the process
async function processImages() {
    try {
        // Get the current file directory path
        const __filename = new URL(import.meta.url).pathname;
        // console.log(__filename);
        const __dirname = path.dirname(__filename);
        // console.log(__dirname);

        // Read JSON data from the local file named 'testingData.json'
        const jsonFilePath = path.join(__dirname, 'testingData.json');
        // console.log(jsonFilePath);
        let jsonData = JSON.parse(await fs.readFile(jsonFilePath, 'utf8'));

        // Update feature Image URLs
        jsonData = jsonData.map(post => {
            if (post.featureImage) {
                post.featureImage = post.featureImage.replace('/content/images/wordpress/', '/insights/wp-content/uploads/');
                post.featureImage = `https://www.crexi.com${post.featureImage}`;
            return post;

        for (const post of jsonData) {
        if (!post.featureImage) {
            console.log(`Skipping object with ID ${post.id} as featureImage is null.`);
      try {
        const objectId = post.id.toString(); // Assuming 'id' is the property in each object containing the object's ID
        const imageURL = post.featureImage; // Assuming 'featureImage' is the property in each object containing the image URL
        const downloadPath = await downloadImage(imageURL, objectId, __dirname);
        const newImageUrl = await uploadImage(downloadPath, objectId);
        // Add the new property 'builderFeatureImage' to the object with the uploaded image URL
        post.builderFeatureImage = newImageUrl;
        console.log(`Image uploaded successfully for Object ID ${objectId}: ${newImageUrl}`);
        // Optionally, delete the downloaded image after upload
        // fs.unlinkSync(downloadPath);
      } catch (error) {
        console.error('Error processing image:', error);

    //Write the modified JSON data back to the file
    await fs.writeFile(jsonFilePath, JSON.stringify(jsonData,null, 2));
    console.log('JSON file updated. :)')
    // Print the modified JSON data with 'builderFeatureImage' property
    // console.log(JSON.stringify(jsonData, null, 2));
} catch (error) {
    console.error('Error reading JSON file:', error);
  // Call the main function to start the process
1 Like

This is good and undoubtedly a valuable contribution to our community. We greatly appreciate it. Thank you, @cedson!