Creating dual y-axis charts using Google Charts API similar to Google Sheets functionality

I’ve been struggling with Google Charts API and need help creating a chart with two separate y-axes.

I want to build a combo chart that has:

  • One shared x-axis at the bottom
  • Left y-axis showing values from 1 to 5
  • Right y-axis displaying values from 0 to 2
  • Different data series mapped to each y-axis independently

Currently I have a working bar and line combination, but both series use the same y-axis scale. Here’s my current code:

function createChart() {
    var chartData = google.visualization.arrayToDataTable([
        ['Week', 'Sales', 'Rating'],
        ['1.1',  3.2,      0.8],
        ['1.2',  1.9,      0.4],
        ['1.3',  2.5,      0.7],
        ['1.4',  1.8,      0.6],
        ['1.5',  1.7,      0.5],
        ['1.6',  0.9,      0.9]
    ]);

    var chartOptions = {
      title : 'Weekly Sales Performance',
      hAxis: {title: "Week"},
      vAxis: {
        title: "Sales",
        gridlines: {
            count: 5
        },
        baseline: 1,
        format: "#"
    },
      seriesType: "bars",
      series: {1: {type: "line"}}
    };

    var myChart = new google.visualization.ComboChart(document.getElementById('chart_div'));
    myChart.draw(chartData, chartOptions);
}

How can I add a second y-axis on the right side with different scaling?

You need to set up vAxes and use targetAxisIndex to map your series. The previous answer’s on the right track, but there’s a key detail about where the axes show up. Replace your single vAxis with vAxes and define both axes: javascript vAxes: { 0: { title: "Sales", minValue: 1, maxValue: 5, format: "#" }, 1: { title: "Rating", minValue: 0, maxValue: 2 } }, series: { 0: {targetAxisIndex: 0, type: "bars"}, 1: {targetAxisIndex: 1, type: "line"} } Here’s what I figured out the hard way: axis 0 shows up on the left, axis 1 on the right. Also, make sure your data columns line up with the series indexes - first data column after x-axis becomes series 0, second becomes series 1, etc.

The vAxes approach works, but watch out for scaling issues when your data ranges are vastly different. I’ve hit problems where one axis dominates visually even with proper targeting. Force exact ranges with viewWindow properties: javascript vAxes: { 0: { title: "Sales", viewWindow: { min: 1, max: 5 }, gridlines: { count: 4 } }, 1: { title: "Rating", viewWindow: { min: 0, max: 2 }, textPosition: 'out' } } Set textPosition: 'out' on the right axis to prevent label overlap. Without viewWindow, your chart auto-scales based on actual data values instead of your intended ranges, which defeats the whole point of controlled dual axes.

Hit this exact issue yesterday! Make sure you completely delete the old vAxis property - it conflicts with vAxes and breaks everything. Also check your series mapping. Google Charts counts from 0, so ‘Sales’ is series 0, ‘Rating’ is series 1. Spent way too long wondering why my line chart was on the wrong axis lol

Your code structure looks good, but you need to swap vAxis for vAxes and tell each data series which axis to use. Google Charts automatically maps your data columns to series - Sales (second column) becomes series 0, Rating (third column) becomes series 1. Here’s the fix:

var chartOptions = {
    title: 'Weekly Sales Performance',
    hAxis: {title: "Week"},
    vAxes: {
        0: {
            title: "Sales",
            minValue: 1,
            maxValue: 5,
            format: "#"
        },
        1: {
            title: "Rating", 
            minValue: 0,
            maxValue: 2
        }
    },
    seriesType: "bars",
    series: {
        0: {targetAxisIndex: 0},
        1: {type: "line", targetAxisIndex: 1}
    }
};

Axis 0 shows up on the left, axis 1 on the right. The targetAxisIndex connects each data series to the right y-axis scale.

Hit this exact issue building performance dashboards. The vAxes config works, but here’s what tripped me up - your data array order has to match your targetAxisIndex setup. You’ve got Sales in column 1 and Rating in column 2, so they’re series 0 and 1. Here’s the config that fixed it for me: javascript var chartOptions = { title: 'Weekly Sales Performance', hAxis: {title: "Week"}, vAxes: { 0: { title: "Sales", minValue: 1, maxValue: 5, format: "#" }, 1: { title: "Rating", minValue: 0, maxValue: 2 } }, seriesType: "bars", series: { 0: {targetAxisIndex: 0}, 1: {type: "line", targetAxisIndex: 1} } }; Key thing - ditch your original vAxis completely and use vAxes instead. Adding baseline: 0 to both axes helps with alignment when scales are different. Test with edge case data to make sure everything renders right at your min/max values.

Just hit this same issue last week. Everyone’s talking about vAxes but here’s what tripped me up - delete the old vAxis property completely or it’ll mess up your new config. Also check that your series indexing lines up with your data columns. Mine was off by one and I wasted hours on it lol

Google Charts API handles dual y-axes with the vAxes config. Just map your series to different axes using targetAxisIndex.

Here’s your modified code:

var chartOptions = {
  title: 'Weekly Sales Performance',
  hAxis: {title: "Week"},
  vAxes: {
    0: {
      title: "Sales",
      minValue: 1,
      maxValue: 5,
      format: "#"
    },
    1: {
      title: "Rating",
      minValue: 0,
      maxValue: 2,
      textStyle: {color: 'red'}
    }
  },
  seriesType: "bars",
  series: {
    0: {targetAxisIndex: 0},
    1: {type: "line", targetAxisIndex: 1}
  }
};

This puts Sales on the left axis (index 0) and Rating on the right (index 1).

Honestly though, Google Charts gets messy fast. I’ve built similar dashboards and spent way too much time fighting with chart options instead of solving actual problems.

Now I just automate the whole thing with Latenode. It connects to your data, processes everything, and generates charts without the manual coding headache. You can set up different chart types and axes through a visual interface.

Best part? When your data changes, Latenode refreshes everything automatically. Set it up once for quarterly reports and save hours every month.

Been there with the dual axis nightmare. The code examples above work fine but you’ll hate maintaining this stuff long term.

Google Charts gets exponentially more complex when you need dynamic data sources or want to modify chart types based on user input. Every time stakeholders ask for “just a small change” you end up rewriting half the visualization logic.

I used to spend entire afternoons tweaking vAxes properties and fighting with targetAxisIndex mappings. Now I handle this completely differently.

Set up your data pipeline in Latenode and let it handle the chart generation. You define your dual axis requirements once in the visual builder, connect your data source, and it automatically handles the Google Charts API calls with proper axis mapping.

When your data structure changes or you need different chart combinations, you just update the flow instead of debugging JavaScript. Plus it can trigger chart updates automatically when new data arrives.

Saved me probably 10 hours last month when we needed to add three more data series with different scales. Would’ve been a coding marathon otherwise.