Using Google Visualization with wkhtmltopdf

Published on March 17, 2014 by

The wkhtmltopdf tool, which converts HTML markup to a PDF document, is quite powerful compared to most other solutions that I have come across. It uses the WebKit rendering engine, which powers many Mac OS X applications such as Safari – and previously Google Chrome. If you have attempted to make wkhtmltopdf work with the Google Visualization API, you quickly noticed that it is unfortunately not as easy as one might think. While the wkhtmltopdf tool does execute JavaScript, rendering graphs (or visualizations) with Google Visualization API does not work out of the box. This article shows you how to easily get it working.

After searching and searching, and trying many different things, I finally got it to work by improvising and hacking away. I am using the Linux 64-bit binary version 0.12.0 available at wkhtmltopdf downloads page on an Ubuntu server. Please note that this article does not cover how to install wkhtmltopdf.

First, you need to use the javascript-delay argument, which allows you to delay the execution of JavaScript code for a given number of milliseconds. In my code, I have set it to 1000, and so far I have not had any problems. You could probably set it lower if you need the PDF to be rendered quickly.

That is the only argument you have to change. Below follows my template file used for generating the charts.


<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <script type="text/javascript" src="https://www.google.com/jsapi"></script>

        <script type="text/javascript">
            function init() {
                google.load("visualization", "1.1", { packages:["corechart"], callback: 'drawCharts' });
            }

            function drawCharts() {
                drawAccountImpressions('chart-account-impressions');
            }
            
            function drawAccountImpressions(containerId) {
            	var data = google.visualization.arrayToDataTable([
                    ['Day', 'This month', 'Last month'],
                    ['01', 1000, 400],
                    ['05', 800, 700],
                    ['09', 1000, 700],
                    ['13', 1000, 400],
                    ['17', 660, 550],
                    ['21', 660, 500],
                    ['23', 750, 700],
                    ['27', 800, 900]
                ]);

                var options = {
                    width: 700,
                    height: 400,
                    hAxis: { title: 'Day',  titleTextStyle: { color: '#333' } },
                    vAxis: { minValue: 0 },
                    curveType: 'function',
                    chartArea: {
                        top: 30,
                        left: 50,
                        height: '70%',
                        width: '100%'
                    },
                    legend: 'bottom'
                };

                var chart = new google.visualization.LineChart(document.getElementById(containerId));
                chart.draw(data, options);
            }
        </script>
    </head>
    
    <body onload="init()">
    	<div id="chart-account-impressions"></div>
    </body>
</html>

There are few things to notice here. First of all, notice the onload attribute on the body tag. This is what triggers our chain of JavaScript function calls. In the init function, I am loading the Google Visualization API as one typically would, except that I am passing in the name of a function, which will be used as a callback when the API is loaded. I found this to be necessary in order for Google Visualization to work with wkhtmltopdf.

When the library is ready, the drawCharts function is invoked. This is simply a function that I made because for my own use case, I need to draw several different charts. So all this function does is call other functions that each draw a chart. You could just as well draw your chart directly in the drawCharts function if you prefer; in other words, you are free to choose how to go about it.

The drawAccountImpressions function is just an example of how to create a line chart. There is nothing in this function that is special for wkhtmltopdf, so you can use the code examples from the Google Visualization API.

All there is left to do is to invoke wkhtmltopdf to generate your PDF, be it on the command line or through a wrapper library such as Snappy for PHP.

I hope this article has helped you save you the hours of searching and experimenting that I went through to figure out a solution. I wish you the best of luck!

Author avatar
Bo Andersen

About the Author

I am a back-end web developer with a passion for open source technologies. I have been a PHP developer for many years, and also have experience with Java and Spring Framework. I currently work full time as a lead developer. Apart from that, I also spend time on making online courses, so be sure to check those out!

15 comments on »Using Google Visualization with wkhtmltopdf«

  1. Diego Delon

    If you need a module in Zend Framework 2 that allow easy to thumbnail, snapshot or PDF generation from a url or a html you can take a look to MvlabsSnappy based on Snappy PHP (5.3+) wrapper for the wkhtmltopdf & wkhtmltoimage conversion utility.

  2. Jesse Sternberg

    YES! This works! Apparently wkhtmltopdf + charts requires callbacks to be wired up in a very specific way to work properly.

  3. Furbee

    This was absolutely helpful. I am so excited that I can incorporate javascript into the PDF process instead of sending it to the client to render the charts and such. I am having an issue running it from Apache, though. It generates the html in the temp location, then returns with an error code -6 for the CalledProcessError. I can run the command parts from the command line and it works perfectly. I think it has to do with Apache2 not being able to fork a child process. Perhaps I need to use Celery to be able to do this from Django on Apache. Do you have some other way of getting it to work with Apache? I noticed you were running it off Ubuntu, but are you using a different web server than Apache?

    Thanks for your help, great find with the javascript-delay getting the charts to render!

  4. Unsa

    Hi,
    I tried ur solution but its not working

  5. mezaga

    Thank you! How do you propose though to do it, if there is more than one google graph integrated into the page?

  6. Augusto Sabino

    Hi.

    It’s a very nice solution. I used it in my application and works perfect.
    I needed to make only a few minor adjustments to meet the needs of my application.

    Thanks.

    https://www.google.com/jsapi

    function init() {
    google.load(“visualization”, “1.1”, { packages:[“corechart”], callback: ‘drawChart’ });
    }

    function drawChart() {
    var data = google.visualization.arrayToDataTable( );
    var options = { legend: { position: ‘right’,
    alignment: ‘center’},
    vAxis: { title: ‘Kilos’},
    width: 1024,
    height: 400,
    //is3D: true,
    axisFontSize: 12,
    legendFontSize: 12
    };

    var chart = new google.visualization.ColumnChart(document.getElementById(‘chart_perdas’));
    chart.draw(data, options);
    }

  7. Thomas

    What if I need my drawChart() function to be an ajax call ?
    It doesn’t seem to work for me, probably wkhtmltopdf waits for the function to exit, but not the ajax call to return.
    Also tried with teh –window-status option, but no luck.

  8. Rafael Souza

    Thank you! Saved me a lot of time.

  9. dgbt

    Thank you a lot, you just saved my day.
    Tried every Version of Chart.js, C3/D3.js, Chartist.js etc.
    everything with svg shit, did not work probably in the wkhtmltopdf current version.
    So I tried to give Mr Don’t be evil a chance with his lib. And google did it (with your help), maybe the onload thing could be the solution for the other quirks, too.. but well google lib is free and allmighty.

  10. Glad to hear that it worked out for you and you hopefully saved some hours and frustration! :-)

  11. Sarah

    I wasn’t able to get this working with the new loader (see below). Has anyone had luck with the updated Google Visualization API? I had to switch my code back to call the older version for wkhtmlpdf to work.

    https://www.gstatic.com/charts/loader.js

    // Load the Visualization API and the corechart package.
    google.charts.load(‘current’, {‘packages’:[‘corechart’]});

    // Set a callback to run when the Google Visualization API is loaded.
    google.charts.setOnLoadCallback(drawChart);

  12. Rizwan Ashraf

    Hi, thanks for the great article.
    Actually some updates in google Api I am unable to load the google charts in Pdf.
    Can you help me with that?
    Thanks in advance

  13. Singh

    Hi,

    I am not able to include chart in pdf. Browser works fine with your html file though. please advise

  14. Chris Leake

    Hello Bo,

    Nice article. Was it really 7 years ago.

    I’ve inherited a PHP application which uses phpwkhtmltopdf. We also use Google Charts. We’ve found that the height of vertical bars, correct in a browser, end up proportionately half their correct height in the PDF extracted with wkhtmltopdf.

    Where would you start finding out why?

    Kind regards,

    Chris Leake

  15. Chris Leake

    Hello Bo,

    I have a problem producing a PDF from a Google Chart with wkhtmltopdf.

    Running my Google Chart HTML in a Browser gives perfect results. But extracting it to PDF with wkhtmltopdf, shows Bar heights in the PDF half the height against the scale to how they appears in the Browser. Also, the colour key is missing.

    Does anyone have a clue what’s going on here?

Leave a Reply

Your e-mail address will not be published.