Multiple URLs into One PDF or into Multiple PDFs

Our regular Save As PDF Links are meant to quickly let your customers turn single webpages into PDF by adding a simple link to your pages. But there are also cases where you want to turn multiple URLs into PDF and still have a user do this live with the click of a button.

You can use our batch URL to PDF API with some simple JavaScript that we will explain below. You can see it in action when you click the button in the "Live Example" section on the right.

The button in the live example on the right shows how a "save as PDF" button can work when you have multiple URLs that you want to process into one larger PDF.

How does it work?

Our Batch URL to PDF API takes a list of URLs as input and returns a PDF. With the JavaScript below you take such a list of URLs and send it our API. Then our API will return a PDF and the JavaScript will update the user on the progress and then display the final PDF to the user.

Below is the basic JavaScript code that you should link to the click of your button. You can do this by adding onclick="PDFmyURL()" to your save as PDF button or link.

To fully customize this example for your own needs you need to do the following:

  • Update the PDFmyURL function to include your own URLs, license and other parameters
  • Update the callback functions for status & error monitoring, these are:
    • batchAPISuccess: is called when a job has been submitted to the batch API
    • batchAPIError: is called when a job has been submitted to the batch API, but it failed
    • monitorProgress: is called regularly when the job is running
    • monitorError: is called when the monitor can't be reached or otherwise fails

By looking at the source code of this page you can see how we customized the code for our own example on this page. Of course you can always send a mail for more help if needed. We'll be happy to help!

<script>
     /*
     * The below PDFmyURL function is a simple example of how you can call our batch API via JavaScript
     * 
     * note that you need to pass several parameters to the batch API in an array, most notably:
     * 
     * urls: this is a semi-colon separated list of the URLs that you want to process, but you could also use
     * sitemap: a URL to a sitemap in XML format
     * license: your license code, which is NOT needed if all the URLs are on the same domain and you've set that domain in our members area
     * email: the email of the person that should receive an email when the job completes or "none" if you don't want an email
     * 
     */
    function PDFmyURL() {
    	parameters = {
    		urls: "https://pdfmyurl.com/batch-web-to-pdf-api;https://pdfmyurl.com/faq",
    		license: "yourlicensehere",
    		email: "none"
    	};

    	callBatchAPI(parameters, batchAPISuccess, batchAPIError);
    }

     /*
     * this batchAPISuccess is called when the batch API has submitted a job
     * 
     * response.job: contains the job number
     * response.id: contains the long job ID
     * 
     */
    function batchAPISuccess(response) {
    	
    	// you can update the user with the job number here if you like before the monitoring begins
        monitorBatchApi({
            job: response.job, id: response.id
        }, monitorProgress, monitorError);
    }

    function batchAPIError(response) {
    	// this function is called in the rare case when the batch API returns an error, for example when you use an incorrect license or have no PDFs left on your plan
        // response.error: contains the error message
    	
    	// you should update the user with response.error here
        
    }

    /*
     * 
     * the monitorProgress function is called in regular intervals while the job is running so you can keep the user posted on the status
     * 
     * response contains the following fields:
     * 
     * response.submitted: the date & time when the job was submitted
     * response.status: either "waiting", "processing" or "completed"
     * response.conversions: the number of URLs processed in the following form "n out of N" where n is the current number and N is the total number of URLs
     * 
     * when response.status = "completed" also the following fields are available
     * response.success: true or false
     * response.finished: the date & time of finishing
     * response.pages: the number of total PDF pages created
     * response.download: the link of the PDF if a merged PDF was requested or otherwise the archive
     * response.archive: the link to the archive with all individual PDFs
     * 
     */
    function monitorProgress(response) {

    	// first you would use response.status & response.conversions to update the user
    	
    	// then when the job is completed you would then use reponse.download or response.archive to show a link to the download or download it straightaway
    	if (response.status === "completed") {
    		
    		// here's an example of opening the PDF immediately
			let a = document.createElement('a');
			a.href = response.download;
			a.download = "example.pdf";
			a.style.display = 'none';
			document.body.appendChild(a);
			a.click();
			
          
			// and this would be an example of showing a link to the PDF
            let a = document.createElement('a');
            a.innerHTML = " Download PDF";
            a.href = response.download;
            a.download = "example.pdf";
            statusElement.appendChild(a);
        }
    }

    /*
     * the monitorError function is called in the rare case when the monitor catches an error, for example when your server can't reach our servers
     * 
     * response: contains the HTTP error response
     */ 
    function monitorError(response) {
    	
    	// you can show an error message here if needed
        
    }

    /*
     * the callBatchAPI function calls the batch API
     * 
     * you should NOT need to update this function
     */ 
    function callBatchAPI(params, success, error) {

        // Now we prepare the data that we pass to the API
        const serialized = Object.keys(params)
            .map(function(k) {
                return encodeURIComponent(k) + "=" + encodeURIComponent(params[k]);
            })
            .join("&");


        // We now prepare the batch API call
        xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function() {
            if (xhttp.readyState === 4) {
                if (xhttp.status === 200) {
                    // call the success callback
                    return success(xhttp.response);
                } else {
                    // call the error callback
                    return error(xhttp.response)
                }
            }
        };

        xhttp.open("POST", "https://pdfmyurl.com/batch_api", true);
        xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        xhttp.responseType = "json";
        xhttp.send(serialized);
    }

    /*
     * the monitorBatchApi function calls the batch API
     * 
     * you should NOT need to update this function, but if you like you can increase POLLING_INTERVAL if you want to update the status less often
     */ 
    function monitorBatchApi(params, success, error) {
        const POLLING_INTERVAL = 500;

        const serialized = Object.keys(params)
            .map(function(k) {
                return encodeURIComponent(k) + "=" + encodeURIComponent(params[k]);
            })
            .join("&");

        // Monitor progress every POLLING_INTERVAL milliseconds
        let interval = setInterval(() => {
                // We now prepare the monitor API call
                xhttp = new XMLHttpRequest();

                xhttp.onreadystatechange = function() {
                    if (xhttp.readyState === 4) {
                        if (xhttp.status === 200) {
                            let job = xhttp.response[params.job];

                            if (job.hasOwnProperty('success')) {
                                // stop polling when the success field is found in response.
                                clearInterval(interval);
                            }
                            return success(job);
                        } else {
                            // If API sends http status code other than 200, then stop the polling 
                            clearInterval(interval);
                            return error(xhttp.response);
                        }
                    }
                };

                xhttp.open("POST", "https://pdfmyurl.com/batch_monitor", true);
                xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
                xhttp.responseType = "json";
                xhttp.send(serialized);
            },
            POLLING_INTERVAL);
    }
</script>