WP JSON to Timeline JS

As part of some thoughts on building out a series of reflective views for student portfolio blogs, I thought seeing your WordPress posts in the TimelineJS view might be a useful way to look back over your progress.

I intend to wrap this into a custom spreadsheet template and/or a plugin1 but figured I’d sketch out how it works so far in case anyone was interested.

The WP Rest API makes it pretty easy to write the data via Google Script. I just want to cut out chunks of the data and put it in the right fields. The following script does that and writes it to a page named “wp.”

function getPosts() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName('wp');
//get the data from the feed and get the last 50 items in this case (set via the URL)
  var url = 'https://bionicteaching.com/wp-json/wp/v2/posts?_embed&per_page=50';
  var response = UrlFetchApp.fetch(url); // get feed
  var json = response.getContentText(); // 
  var data = JSON.parse(json);
  for (i = 0; i < data.length; i++){
    var ssData = [];    
    ssData.push(data[i].date.substring(0,4)); //post year   
    ssData.push(data[i].date.substring(5,7)); //post month   
    ssData.push(data[i].date.substring(8,10)); //post day   
    ssData.push(data[i].date.substring(11,19)); //post time 
    ssData.push(""); //filler for now for end date  info

    ssData.push(theUrl(data[i]) + data[i].title.rendered + '</a>'); //post title w link
    ssData.push(data[i].excerpt.rendered); //post excerpt
    ssData.push(featuredCheck(data[i])); //post feature image

//have a featured image? then get it . . . 
function featuredCheck (data) {
  try {data._embedded['wp:featuredmedia'][0].media_details.sizes.full.source_url;
       return data._embedded['wp:featuredmedia'][0].media_details.sizes.full.source_url;
  catch (err){
    return "";

//make things a bit neater by building the href via function
 function theUrl (data) {
   return '<a href="' + data.guid.rendered + '">'; //build the url 

1 Or maybe just a page where you throw in a blog URL and get a bunch of alternate view/data options.

Comments on this post

  1. Anne Kergroach said on January 3, 2018 at 11:04 am

    it’s exactly what i’m looking for since 3 weeks!
    how do think i must proceed to include and call this code?

    thank in advance

  2. Anne said on January 9, 2018 at 1:16 pm

    Hello and sorry to solicit you again ๐Ÿ˜€

    but once the script created does it link to the official spreadsheet of the timelinejs or to a new one? do you link the script to a cell?
    and how do you deploy it, to get the code of the source?

    Thank you

    • Tom Woodward said on January 9, 2018 at 3:59 pm

      Anne- This uses the WordPress site itself to create the data for the timeline. In this scenario there is no spreadsheet at all. To change the site feeding the timeline you can just change the site address in the URL to the blog you want to use (assuming it’s a modern WordPress site).

      If you give me a better idea about what you’re trying to do I might be able to make some suggestions.

      • Anne said on January 10, 2018 at 3:09 am

        Hello Tom, yes it’s for a recent wordpress site.
        I changed the path of line 6 to a wp page that I created via wp-json (I found that it worked) and inserted an iframe tag in the landing page to https: // cdn.knightlab.com/libs/timeline3/latest/embed/index.html? but I do not know which source to paste after url
        I guess it was when exporting the code that I missed something?!?

  3. Tom Woodward said on January 11, 2018 at 10:05 pm

    Oh man. I’m sorry I was confusing this with another thing I did later. You can see the new version here and it’s kind of easier. You just change the url where it says cogdogblog.com to whatever site you want to use.

    To answer your question, using the google sheets path, I’d put that script in the same sheet you’d normally use for your timeline JS. That script writes to a page named “wp” (line 3) so you’d need to create that. Then you can just use a sheets function to mirror it to the normal page.

    If you want to share the doc with me at bionicteaching@gmail.com, I can make it work.

  4. Jane SENEOR said on February 16, 2018 at 12:48 pm

    I’ve got custom post type and custom field (event date).
    How could I adapt your code to fit my needs?

    • Tom Woodward said on February 19, 2018 at 10:13 pm

      It depends. If the post type is available via the WP API then I think you’d just have to add that element to the URL.

      • Jane SENEOR said on February 20, 2018 at 7:31 am

        here’s the controller I used to feed my timeline :

        class JSON_API_Timeline_Controller {

        public function category_posts() {
        global $json_api;
        $json = array();

        // get attributes
        $category_id = $json_api->query->category_id;
        $post_type = $json_api->query->post_type;
        $amount = $json_api->query->amount;
        $main_post_id = $json_api->query->main_post_id;

        if(!$post_type) $post_type = ‘post’;
        if(!$amount) $amount = -1;

        $posts = get_posts(array(‘post_type’ => $post_type, ‘numberposts’ => $amount, ‘category’ => $category_id, ‘orderby’ => $eventdate, ‘order’ => ‘DESC’));

        if($main_post_id) $main_post = get_post($main_post_id);
        else {
        $main_post = $posts[0];

        if($main_post) {

        // setting first (main) post

        $json[‘timeline’] = array();

        $json[‘timeline’][‘headline’] = $main_post->post_title;
        $json[‘timeline’][‘type’] = ‘default’;
        $json[‘timeline’][‘startDate’] = date(‘Y,m,d’, strtotime($main_post->post_date));
        $json[‘timeline’][‘text’] = $main_post->post_excerpt;

        // example of media asset using the post thumbnail
        if(has_post_thumbnail($main_post->ID)) {

        $thumbnail_id = get_post_thumbnail_id($main_post->ID);
        $thumbnail_src = wp_get_attachment_image_src($thumbnail_id, ‘large’);
        $json[‘timeline’][‘asset’][‘media’] = $thumbnail_src[0];


        if($posts) {
        $json[‘timeline’][‘date’] = array();
        $i = 0;
        foreach($posts as $post) {

        $json[‘timeline’][‘date’][$i][‘startDate’] = date_i18n(‘Y,m,d’, strtotime(get_post_meta($post->ID, “_datepicker”, true)));
        $json[‘timeline’][‘date’][$i][‘endDate’] = date_i18n(‘Y,m,d’, strtotime(get_post_meta($post->ID, “_datepicker”, true)));
        if ( has_post_format( ‘aside’,$post->ID ) ) {
        $json[‘timeline’][‘date’][$i][‘headline’] = $post->post_title;
        $json[‘timeline’][‘date’][$i][‘text’] = ”.get_post_meta($post->ID, “event_lieu”, true).”.$post->post_content;
        } else {
        $json[‘timeline’][‘date’][$i][‘headline’] = ‘ID).'”>’.$post->post_title.’‘;
        $typelist = ”;
        if ($eventtypes = get_field(“type_de_event”, $post->ID)) {
        if(is_array($eventtypes)) {
        foreach ($eventtypes as $key => $eventtype) {
        $typelist .= $eventtype . ‘ | ‘;
        $typelist = substr($typelist, 0, -2);
        $typelist = ”.$typelist.”;
        $json[‘timeline’][‘date’][$i][‘text’] = ”.get_post_meta($post->ID, “event_lieu”, true).”.$post->post_excerpt.$typelist;

        // example of media asset using the post thumbnail
        if(has_post_thumbnail($post->ID)) {

        $thumbnail_id = get_post_thumbnail_id($post->ID);
        $thumbnail_src = wp_get_attachment_image_src($thumbnail_id, ‘large’);

        $json[‘timeline’][‘date’][$i][‘asset’][‘media’] = $thumbnail_src[0];}



        return $json;

        } else return ‘Posts not found’;

        } else return ‘Main post not found’;



        and i used that url which doesn’t work anymore :
        echo do_shortcode(“[timeline src=’http://conexion.cluster003.ovh.net/blog/api/timeline/category_posts/?category_id=4&hash_bookmark=true&start_zoom_adjust=3&main_post_id=1136′]”);

        Can you help me adjust your code to my needs?

Trackbacks and Pingbacks on this post

  1. WordPress Timeline JS Plugin – Bionic Teaching said on February 23, 2018 at 8:51 am

    […] A blog post on how that works is via Google Sheets is here. I also built another version using URL parameters and PHP but may not have written the blog post. […]