Migrating DataTables and Highcharts integration from Google Sheets API v3 to v4

Need Help Converting Chart Implementation to New Google Sheets API

I’m working on a project that combines data tables with interactive charts. The current setup was working fine with the older Google Sheets API but stopped functioning after the API changes. I need to migrate my existing code to use the newer version of the Google Sheets API.

The main issue is that my current implementation relies on the old API structure and I’m not sure how to properly adapt the data parsing logic for the new API format. The charts display monthly data in an expandable table format.

Here’s my current working code structure:

$(document).ready(function() {
    var monthlyData = [];
    var timeLabels = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
    var apiEndpoint = "https://spreadsheets.google.com/feeds/list/SPREADSHEET_ID/od6/public/values?alt=json";

    $.getJSON(apiEndpoint)
        .done(function(response) {
            var entries = response.feed.entry;
            var recordIndex = 0;
            var recordArray = [];
            
            $(entries).each(function() {
                if (recordIndex % 2 === 0) {
                    recordArray = [
                        this.gsx$_cn6ca.$t,
                        this.gsx$organization.$t,
                        this.gsx$january.$t,
                        this.gsx$february.$t,
                        this.gsx$march.$t,
                        this.gsx$april.$t,
                        this.gsx$may.$t,
                        this.gsx$june.$t,
                        this.gsx$july.$t,
                        this.gsx$august.$t,
                        this.gsx$september.$t,
                        this.gsx$october.$t,
                        this.gsx$november.$t,
                        this.gsx$december.$t
                    ];
                } else {
                    recordArray = recordArray.concat([
                        this.gsx$_cn6ca.$t,
                        this.gsx$organization.$t,
                        this.gsx$january.$t,
                        this.gsx$february.$t,
                        this.gsx$march.$t,
                        this.gsx$april.$t,
                        this.gsx$may.$t,
                        this.gsx$june.$t,
                        this.gsx$july.$t,
                        this.gsx$august.$t,
                        this.gsx$september.$t,
                        this.gsx$october.$t,
                        this.gsx$november.$t,
                        this.gsx$december.$t
                    ]);
                    monthlyData.push(recordArray);
                }
                recordIndex++;
            });
            
            var dataGrid = $('#company-datatable').DataTable({
                data: monthlyData,
                deferRender: true,
                "processing": true,
                paging: false,
                columnDefs: [{
                    className: "expand-control",
                    "targets": [0]
                }]
            });
            
            function buildDetailView(rowInfo) {
                return '<div class="detail-container">' +
                    '<table class="info-table" border="0">' +
                    '<thead>' +
                    '<td>' + [rowInfo[14]].join(', ') + '</td>' +
                    '<td>' + [rowInfo[15]].join(', ') + '</td>' +
                    '<td>' + [rowInfo[16]].join(', ') + '</td>' +
                    '<td>' + [rowInfo[17]].join(', ') + '</td>' +
                    '<td>' + [rowInfo[18]].join(', ') + '</td>' +
                    '<td>' + [rowInfo[19]].join(', ') + '</td>' +
                    '<td>' + [rowInfo[20]].join(', ') + '</td>' +
                    '<td>' + [rowInfo[21]].join(', ') + '</td>' +
                    '<td>' + [rowInfo[22]].join(', ') + '</td>' +
                    '<td>' + [rowInfo[23]].join(', ') + '</td>' +
                    '<td>' + [rowInfo[24]].join(', ') + '</td>' +
                    '<td>' + [rowInfo[25]].join(', ') + '</td>' +
                    '</thead>' +
                    '<div id="visualization' + rowInfo[14] + '"></div>' +
                    '</div>';
            }
            
            $('#company-datatable tbody').on('click', 'td.expand-control', function() {
                var tableRow = $(this).closest('tr');
                var currentRow = dataGrid.row(tableRow);
                
                if (currentRow.child.isShown()) {
                    $('div.detail-container', currentRow.child()).slideUp(function() {
                        currentRow.child.hide();
                        tableRow.removeClass('expanded');
                    });
                } else {
                    currentRow.child(buildDetailView(currentRow.data()), 'no-padding').show();
                    tableRow.addClass('expanded');
                    renderVisualization('visualization' + currentRow.data()[14], currentRow.data().slice(16));
                    $('div.detail-container', currentRow.child()).slideDown();
                }
            });
        });
        
    function renderVisualization(elementId, chartData) {
        Highcharts.chart(elementId, {
            series: [{
                data: (function() {
                    chartData.forEach(function(value, index) {
                        chartData[index] = Number(value);
                    });
                    return chartData;
                })()
            }],
            chart: {
                zoomType: 'xy',
                type: 'area',
                backgroundColor: '#2a3f47'
            },
            plotOptions: {
                series: {
                    lineWidth: 3,
                    fillColor: "#00aadd",
                    lineColor: "#ff6b5b",
                    marker: {
                        enabled: true,
                        symbol: 'circle',
                        radius: 5,
                        states: {
                            hover: {
                                enabled: true,
                                fillColor: '#333333'
                            }
                        }
                    }
                }
            },
            title: {
                style: {
                    color: '#E0E0E3',
                    fontSize: '18px'
                }
            },
            yAxis: {
                labels: {
                    style: {
                        color: 'white'
                    }
                }
            },
            legend: {
                itemStyle: {
                    color: 'white'
                }
            },
            xAxis: {
                categories: timeLabels,
                labels: {
                    style: {
                        color: 'white'
                    }
                }
            }
        });
    }
});

How can I update this code to work with the current Google Sheets API? What changes do I need to make to the data parsing and API call structure?

API v4 changed everything - totally different endpoints now. You can’t use the old feeds URL anymore. Switch to https://sheets.googleapis.com/v4/spreadsheets/SPREADSHEET_ID/values/RANGE instead. The response is much cleaner too. No more gsx mess, just a simple values array. One catch though - you’ll need an API key.

Went through this migration 6 months ago and the auth stuff hit me hardest. You’ll need to enable the Sheets API in Google Cloud Console and grab an API key - it’s not just about switching endpoints. The data structure’s actually cleaner once you get used to it. No more cryptic gsx$month.$t syntax - just response.values[rowIndex][columnIndex]. I mapped out my columns first since v4 drops the named properties completely. Your every-other-row logic will break since the entry iteration pattern’s gone. Chart rendering stays the same thankfully, but plan extra time for debugging the array-based extraction. Make sure your spreadsheet’s public or set up OAuth for private ones.

Been there, done that - manual API migrations are exactly why I stopped doing them.

Skip v4’s authentication mess and rewriting all that parsing logic. Set up automation that handles your entire data pipeline instead. Pull from Google Sheets, transform the data for DataTables, push to frontend. Done. No more API versions breaking your stuff.

I’ve built similar dashboards where data flows from spreadsheets to charts without touching API code. Automation handles monthly extraction, formats everything for Highcharts, manages expandable table logic. When Google changes their API again, you update one workflow instead of hunting through JavaScript.

Your every-other-row processing and chart rendering? Perfect for this approach. Automation replicates that exact logic but makes it bulletproof.

Check it out: https://latenode.com

Went through this exact migration nightmare last year. V4’s data structure is totally different - you get a clean response.values array where each row is just cell values in an array. No more response.feed.entry or that confusing gsx$ property mess. Your parsing logic needs a complete rewrite. Gone are the days of this.gsx$january.$t - now you’re working with array indices like row[2] for the third column. The new endpoint needs authentication but it’s way more predictable. You’ll have to ditch $.getJSON and restructure how you grab cell data. But here’s the silver lining - once you fix the data parsing, your DataTables and Highcharts code won’t need any changes since you’re still building the same monthlyData array.