How to export the complete activities log of your Storyblok space

Contents

In this article you will learn how to use the Mangement API of Storyblok to download your Activities log as .csv utilizing node.js.

Set-up a node.js project

Navigate into a folder you’re okay with creating a new Node project.

mkdir pull-logs

Start a new node project using the command below

node init

Set-up & install dependencies

Next you can exchange the content of the package.json with the following one:

{
  "name": "pull-logs",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "axios": "^0.21.1",
    "axios-concurrency": "^1.0.4",
    "flat": "^5.0.2",
    "json2csv": "^5.0.6"
  }
}

This will add the dependencies axios, axios-concurrency, flat, and json2csv which allows us to easily access the Management API, flatten the JSON we receive from the activities endpoint and convert JSON to csv so we can than write it as a file.

Install the dependencies so we can start creating the actual script itself.

npm install

Creating the Node Script

Create a index.js with the following content. The comments will guide you through the whole implementation. You will need your personal access token to exchange the STORYBLOK_MANAGEMENT_TOKEN placeholder and your space id to replace STORYBLOK_SPACE_ID.

const axios = require('axios')
const { ConcurrencyManager } = require("axios-concurrency")
const flatten = require('flat')
const fs = require('fs')
const { parse } = require('json2csv')

// Initialize axios with the Management API endpoint and your Space ID
// In the same step we will also add the Personal Access Token so we authenticated with the current user.
// CAUTION: DO NOT COMMIT YOUR PERSONAL ACCESS TOKEN - THIS ALLOWS CRUD OPERATIONS
let api = axios.create({
    baseURL: `https://app.storyblok.com/v1/spaces/STORYBLOK_SPACE_ID`,
    headers: { 'authorization': 'STORYBLOK_MANAGEMENT_TOKEN' }
})

// Set-up MAX_CONCURRENT_REQUESTS to apply to the rate limits
const manager = ConcurrencyManager(api, MAX_CONCURRENT_REQUESTS = 3)

// How many activities should be requested at once (no need to increase it)
const per_page = 100

// Perform a HEAD request to get the total number of activities from the Response Headers
api.head(`/activities/?created_at_gte=&created_at_lte=&per_page=${per_page}&page=1`).then((res) => {

    // Total number of activities from response header
    const total = res.headers.total
    // calculate the maximum amount of pages
    const maxPage = Math.ceil(total / per_page)

    // prepare all requests that needs to be sent in total to request all activities
    let contentRequests = []
    for (let page = 1; page <= maxPage; page++) {
        contentRequests.push(api.get(`/activities/?created_at_gte=&created_at_lte=&per_page=${per_page}&page=${page}`))
    }

    // Execute all requests that we've prepared before using axios.all and axios.spread
    // Thanks to axios-concurrency it will send maximum of 3 requests per second!
    axios.all(contentRequests).then(axios.spread((...responses) => {

        // To output the JSON as CSV we will have to flatten the JSON structure
        // for this we will loop through all responses and use `flat` and their flatten method
        let flatData = []
        responses.forEach((response) => {
            let data = response.data

            // flatten JSON response and add to array.
            data.activities.forEach(activity => {
                flatData.push(flatten(activity))
            })
        })

        // Get all fields of one object so we can define the header of the CSV
        const fields = Object.keys(flatData[0])
        const opts = { fields }

        // parse the whole flatData into a CSV format
        const csv = parse(flatData, opts)

        // and finally let's write it out into a file
        fs.writeFileSync('log-' + Date.now() + '.csv', csv)

    })).catch(e => { console.log(e) })
})

After adding the above content you can execute it using node index.js which will write out a log-timestamp.csv in your current directory.

Summary

With just a few lines of code you can not only access the whole activities log and easily run custom filters on it using Excel, archive it, export it for an audit or any other case you might want to access your logs of your Storyblok space.