Using MongoDB / Node consider the following payload:
var myObj = {
"date" : "1-23-45",
"one" : [
{
"a" : 8
},
{
"b" : 1
},
{
"c" : 9
},
{
"d" : 10
},
{
"e" : 12424
},
{
"f" : 11
},
{
"g" : 7
}
],
"two" : [
{
"h" : 6
},
{
"i" : 10
}
]
},
{
"date" : "1-24-45",
"one" : [
{
"a" : 8
},
{
"b" : 1
},
{
"c" : 9
},
{
"d" : 10
},
{
"e" : 12424
},
{
"f" : 11
},
{
"g" : 7
}
],
"two" : [
{
"h" : 6
},
{
"i" : 10
}
]
}
I am using Google Charts API and I would like to plot these points to a line graph. (see snippet)
<html>
<head>
<script type="text/javascript" src="https://www.google.com/jsapi?autoload={
'modules':[{
'name':'visualization',
'version':'1',
'packages':['corechart']
}]
}"></script>
<script type="text/javascript">
google.setOnLoadCallback(drawChart);
var myObj = {
"cols": [{
"id": "",
"label": "year",
"type": "string"
}, {
"id": "",
"label": "sales",
"type": "number"
}, {
"id": "",
"label": "expenses",
"type": "number"
}],
"rows": [{
"c": [{
"v": "2001"
}, {
"v": 3
}, {
"v": 5
}]
}, {
"c": [{
"v": "2002"
}, {
"v": 5
}, {
"v": 10
}]
}, {
"c": [{
"v": "2003"
}, {
"v": 6
}, {
"v": 4
}]
}, {
"c": [{
"v": "2004"
}, {
"v": 8
}, {
"v": 32
}]
}, {
"c": [{
"v": "2005"
}, {
"v": 3
}, {
"v": 56
}]
}]
}
function drawChart() {
var data = new google.visualization.DataTable(myObj);
var options = {
title: 'My Chart',
curveType: 'function',
legend: {
position: 'right'
}
};
var chart = new google.visualization.LineChart(document.getElementById('curve_chart'));
chart.draw(data, options);
}
</script>
</head>
<body>
<div id="curve_chart" style="width: 100%; height: 500px"></div>
</body>
</html>
Using the JSON I am provided, what would be the most effective way to massage the data into the format accepted by Google Charts API? I have looked into D3 but it seemed to have a higher learning curve, would that be the most recommended route? Would it be better to query the dataset differently / aggregate the result?
Help is much appreciated, as this has been a 2 day long venture!
Update --
TL;DR
I need a script that goes from Format #1 => Format #2, no matter how big the payload is.
Format #1 - myObj
Format #2 -
var myObj = {
"cols": [{
"label": "Date",
"type": "string"
}, {
"label": "a",
"type": "number"
}, {
"label": "b",
"type": "number"
}, {
"label": "c",
"type": "number"
}, {
"label": "d",
"type": "number"
}, {
"label": "e",
"type": "number"
}, {
"label": "f",
"type": "number"
}, {
"label": "g",
"type": "number"
}, {
"label": "h",
"type": "number"
}, {
"label": "i",
"type": "number"
}
],
"rows": [{
"c": [{
"v": "day1"
}, {
"v": 300
}, {
"v": -500
}, {
"v": 23
}, {
"v": 120
}, {
"v": 150
}, {
"v": 1210
}, {
"v": 160
}, {
"v": 180
}, {
"v": 190
}]
}, {
"c": [{
"v": "day2"
}, {
"v": 1300
}, {
"v": -5200
}, {
"v": 253
}, {
"v": 6120
}, {
"v": 1350
}, {
"v": 110
}, {
"v": 2160
}, {
"v": 1180
}, {
"v": 1190
}]
}
]
}
Looking at your data and how it needs to be formatted, something like the below would work. You will need to loop over each object to get the cols and then map over each array to get the rows.
var dataObj = {
"cols": [],
"rows": []
};
for(property in myObj) {
if(typeof myObj[property] === 'string') {
dataObj.cols.push({
"label": property,
"type": "string"
});
} else {
dataObj.rows.push({
"c": []
});
dataObj.rows[dataObj.rows.length - 1]["c"].push({
"date": "day" + dataObj.rows.length // The day: 1, 2, 3, etc.
});
myObj[property].map(function(object) {
for(prop in object) {
dataObj.cols.push({
"label": prop,
"type": "number"
});
dataObj.rows[dataObj.rows.length - 1]["c"].push({
"v": object[prop]
});
}
});
}
}
JSFiddle with Google Chart example (Open Console to see formatted data)
Related
Sorry for the terrible title, I don't know how to properly describe this.
I have a set of table headers that are hierarchical, and I need to transform them from a multi-column tree structure, to a single column indented structure.
The Tree like structure looks like this (Sorry it's photos, I can't render it in MD):
And the version I would like to render looks like this:
In the first photo, the yellow cells are rollup cells. They don't actually have any information, they just act as placeholders for alignment.
The data structure for the first table headers looks like essentially like this:
{
"headers": [
[
{
"label": "A",
"span": "9"
}
],
[
{
"label": "B",
"span": "9"
}
],
[
{
"label": "C",
"span": "1"
},
{
"label": "D",
"span": "4"
},
{
"label": "E",
"span": "1"
},
{
"label": "F",
"span": "3"
}
],
[
{
"rollup": true,
"span": "1"
},
{
"label": "G",
"span": "2"
},
{
"label": "H",
"span": "2"
},
{
"rollup": true,
"span": "1"
},
{
"label": "I",
"span": "1"
},
{
"label": "J",
"span": "1"
},
{
"label": "K",
"span": "1"
}
],
[
{
"rollup": true,
"span": "1"
},
{
"label": "L",
"span": "1"
},
{
"label": "M",
"span": "1"
},
{
"label": "N",
"span": "1"
},
{
"label": "O",
"span": "1"
},
{
"rollup": true,
"span": "1"
},
{
"rollup": true,
"span": "1"
},
{
"rollup": true,
"span": "1"
},
{
"rollup": true,
"span": "1"
},
],
]
}
And the data for the actual values in the table looks like this (it's possible to have many columns, this the nested arrays, furthermore it's possible to have empty values in which case there will be a flag that indicated it's an empty cell like "empty":true):
const rows = {
"data": [
[
{
"value": 100
"empty": false // Could be used to indicate a cell is empty
}
],
[
{
"value": 200
}
],
[
{
"value": 300
}
],
[
{
"value": 400
}
],
[
{
"value": 500
}
],
[
{
"value": 600
}
],
[
{
"value": 700
}
],
[
{
"value": 800
}
],
[
{
"value": 900
}
],
]
}
I need to render the second header style, using the data above. This doesn't feel like it should be a very difficult problem, however I can't seem to solve it.
edit:
To render the data in the first table, we convert the initial data structure essentially into a 9x5 matrix, where the arrays are padded with null accordingly.
const yHeaders = {
"headers": [
[
{
"label": "A",
"span": "9",
},
null,
null,
null,
null,
null,
null,
null,
null,
],
[
{
"label": "B",
"span": "9"
},
null,
null,
null,
null,
null,
null,
null,
null,
],
[
{
"label": "C",
"span": "1",
},
{
"label": "D",
"span": "4",
},
null,
null,
null,
{
"label": "E",
"span": "1",
},
{
"label": "F",
"span": "3",
},
null,
null,
],
[
{
"rollup": true,
"span": "1",
},
{
"label": "G",
"span": "2",
},
null,
{
"label": "H",
"span": "2",
},
null,
{
"rollup": true,
"span": "1",
},
{
"label": "I",
"span": "1",
},
{
"label": "J",
"span": "1",
},
{
"label": "K",
"span": "1",
}
],
[
{
"rollup": true,
"span": "1",
},
{
"label": "L",
"span": "1",
},
{
"label": "M",
"span": "1",
},
{
"label": "N",
"span": "1",
},
{
"label": "O",
"span": "1",
},
{
"rollup": true,
"span": "1",
},
{
"rollup": true,
"span": "1",
},
{
"rollup": true,
"span": "1",
},
{
"rollup": true,
"span": "1",
},
],
]
}
To render the current table, we use something like this:
const renderBodyRow = (row: any, key: number, rows: any) => {
return (
<tr key={key}>
{yHeaders.headers.map((yHeaderColumn: any[], rowColumnHeaderKey: number) => {
// For many of these, yHeaderColumn[key] will be null, in which case the previous
// row will simply span into the new one
return (
yHeaderColumn.length > key &&
yHeaderColumn[key] && (
<th
key={rowColumnHeaderKey}
rowSpan={+get(yHeaderColumn[key], "span", 1)}
>
{get(yHeaderColumn[key], "label")}
</th>
)
);
})}
{row.map((cell: any, cellIndex: number) => {
return <td key={cellIndex}>{get(cell, "value", "")}</td>;
})}
</tr>
);
};
return (
<table id={tableId}>
<thead>...</thead>
<tbody >
{rows.data.map(renderBodyRow)}
</tbody>
</table>
)
You could take a virtual target by using span and the intermediate indices to get a tree structure and render a flat array with indented label and value, denoted here with data[0], which should be replaced by the real values.
const
headers = [[{ label: "A", span: "9" }], [{ label: "B", span: "9" }], [{ label: "C", span: "1" }, { label: "D", span: "4" }, { label: "E", span: "1" }, { label: "F", span: "3" }], [{ rollup: true, span: "1" }, { label: "G", span: "2" }, { label: "H", span: "2" }, { rollup: true, span: "1" }, { label: "I", span: "1" }, { label: "J", span: "1" }, { label: "K", span: "1" }], [{ rollup: true, span: "1" }, { label: "L", span: "1" }, { label: "M", span: "1" }, { label: "N", span: "1" }, { label: "O", span: "1" }, { rollup: true, span: "1" }, { rollup: true, span: "1" }, { rollup: true, span: "1" }, { rollup: true, span: "1" }]],
iter = (array, index = { i: 0 }) => array.flatMap(({ label, children }) => [
[label, children.length ? '' : `data[${index.i++}]`],
...iter(children, index)
]),
temp = [];
headers.reduce((r, a, i) => {
const parents = {};
let pos = 0;
a.forEach(({ label, span, rollup }) => {
span *= 1;
label = ' '.repeat(i) + label;
if (!rollup) {
r[pos].push({ label, children: parents[pos] = [] });
for (let i = 1; i < span; i++) parents[pos + i] = parents[pos];
}
pos += span;
});
return parents;
}, { 0: temp });
console.log(iter(temp));
console.log(temp);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I have the following array of javascript objects which I store in $scope.o
[{"id":"jimmy.cibby#redsss.com","label":"marc.cibby#redsss.com","type":"number","p":{}},{"id":"matthew.cibby#redsss.com","label":"matthew.cibby#redsss.com","type":"number","p":{}},{"id":"ari.grads#redsssdsss.com","label":"ari.grads#redsssdsss.com","type":"number","p":{}},{"id":"yup#redsssdsss.com","label":"yup#redsssdsss.com","type":"number","p":{}},{"id":"service#redsssdsss.com","label":"service#redsss.com","type":"number"}]
I then have the following setup for google charts:
$scope.data= {
"type": "LineChart",
"displayed": true,
"data": {
"cols":$scope.o,
"rows": [
{
"c": [
{
"v": "January"
},
{
"v": 19,
"f": "42 items"
},
{
"v": 12,
"f": "Ony 12 items"
},
{
"v": 7,
"f": "7 servers"
},
{
"v": 4
},
{"v": 5}
]
},
{
"c": [
{
"v": "February"
},
{
"v": 13
},
{
"v": 1,
"f": "1 unit (Out of stock this month)"
},
{
"v": 12
},
{
"v": 2
},
{
"v": 2
}
]
},
{
"c": [
{
"v": "March"
},
{
"v": 24
},
{
"v": 5
},
{
"v": 11
},
{
"v": 6
},
{
"v":12
}
]
}
]
},
"options": {
"title": "some data",
"tooltip": {trigger: "selection"},
"isStacked": "true",
"fill": 20,
"displayExactValues": true,
"chartArea": {width: "70%", height: "70%"},
"vAxis": {
"title": "data",
"gridlines": {
"count": 10
}
},
"hAxis": {
"title": "month"
}
},
"formatters": {}
}
}]);
as you can see, all I have done to the sample app here: http://angular-google-chart.github.io/angular-google-chart/docs/latest/examples/multi-chart/
is change the columns to custom ones.
This kind of works- the legend pulls through the email address labels but the graph is empty with no data on it.
Any suggestions as to why this would happen?
Fixed it... I needed to add:
$scope.o.push({
id: "month",
label: "Month",
type: "string"
});
before the for loop. Rookie mistake!
Was wondering if anyone knows of a way to use lodash, or vanilla JS to achieve this small problem?
I have this starting object:
{
"1": {
"null": {
"2": {
"3": {
"6": {
"7": "c"
},
"null": {
"null": {
"5": "b"
}
}
}
}
}
},
"8": {
"10": "e",
"null": {
"9": "d"
}
}
}
Each level (horizontally) means something. So level 1 is of type A, level 2 is of type B, 3 of type A, 4 of type B and so forth. So it alternates.
Is there a nice and simply way to "collapse" this object to look something like this:
[
{
"type": "A",
"label": "1",
"children": [
{
"type": "A",
"label": "2",
"children": [
{
"type": "B",
"label": "3",
"children": [
{
"type": "A",
"label": "6",
"children": [
{
"type": "A",
"label": "7",
"value": "c"
}
]
},
{
"type": "A",
"label": "8",
"children": [
{
"type": "A",
"label": "5",
"value": "b"
}
]
}
]
}
]
}
]
},
{
"type": "A",
"label": "8",
"children": [
{
"type": "B",
"label": "10",
"value": "e"
},
{
"type": "A",
"label": "9",
"value": "d"
}
]
}
]
In essence annotating each level with what type it is, and nesting its children.
Here is the code
function transformObj(obj, level) {
level = level || 1;
var result = _(obj).transform(function(result, value, key) {
var obj = {
type: (level % 2 === 0) ? 'B' : 'A',
label: key
};
if (key === 'null') {
result.push(transformObj(value, level+1));
} else {
if (_.isObject(value)) {
obj.children = transformObj(value, level+1);
} else {
obj.value = value;
}
result.push(obj);
}
}, [])
.flatten()
.value();
return result;
}
Here is the output
[
{
"type": "A",
"label": "1",
"children": [
{
"type": "A",
"label": "2",
"children": [
{
"type": "B",
"label": "3",
"children": [
{
"type": "A",
"label": "6",
"children": [
{
"type": "B",
"label": "7",
"value": "c"
}
]
},
{
"type": "A",
"label": "5",
"value": "b"
}
]
}
]
}
]
},
{
"type": "A",
"label": "8",
"children": [
{
"type": "B",
"label": "10",
"value": "e"
},
{
"type": "A",
"label": "9",
"value": "d"
}
]
}
]
This should do the trick:
var source = {
"1": {
"null": {
"2": {
"3": {
"6": {
"7": "c"
},
"null": {
"null": {
"5": "b"
}
}
}
}
}
},
"8": {
"10": "e",
"null": {
"9": "d"
}
}
};
function collapse(obj, parent, level){
var result = parent || [];
level = level || 0;
for(prop in obj){
var item = obj[prop];
var build = {
type : level % 2 ? "B" : "A",
label : prop
//, level : level
}
if(typeof item == 'object'){
build.children = [];
collapse(item, build.children, level + 1);
} else {
build.value = item;
}
result.push(build);
}
return result;
}
var output = collapse(source);
var result = JSON.stringify(output, null, ' ');
console.log(result);
var elem = document.getElementById("result");
elem.innerHTML = result;
<pre id="result"></pre>
function doIt(data){
return _.chain(data)
.transform(function(result, value, key){
if(key !== 'null'){
var type = _.parseInt(key) % 2 === 1 ? 'A' : 'B';
if(_.isObject(value) && !_.includes(_.keys(value), 'prop1')){
result.push({
type: type,
label: key,
children: doIt(value)
});
} else {
result.push({
type: type,
label: key,
value: value
});
}
} else {
if(_.isObject(value)){
result.push(doIt(value));
}
}
}, [])
.flatten()
.value();
}
var result = doIt(data);
result is
[
{
"type": "A",
"label": "1",
"children": [
{
"type": "B",
"label": "2",
"children": [
{
"type": "A",
"label": "3",
"children": [
{
"type": "B",
"label": "6",
"children": [
{
"type": "A",
"label": "7",
"value": "c"
}
]
},
{
"type": "A",
"label": "5",
"value": "b"
}
]
}
]
}
]
},
{
"type": "B",
"label": "8",
"children": [
{
"type": "B",
"label": "10",
"value": "e"
},
{
"type": "A",
"label": "9",
"value": "d"
}
]
}
]
I would like to have a Line Chart using angular-google-chart to show some statistics and also future projection. I want my projection to be dashed lines. Below is my sample code. Currently, my line chart will show the same color for the statistics and future projection. I want it to be different color or maybe dashed for the future projection.
HTML
<div google-chart chart="stat"></div>
JS
$scope.stat = {
"type": "LineChart",
"displayed": false,
"data": {
"cols": [
{
"id": "date",
"label": "Date",
"type": "string",
},
{
"id": "sales-id",
"label": "Sales",
"type": "number",
},
],
"rows": [
{
"c": [
{
"v": "20 Nov"
},
{
"v": 19,
}
]
},
{
"c": [
{
"v": "21 Nov"
},
{
"v": 17,
}
]
},
{
"c": [
{
"v": "22 Nov"
},
{
"v": 18,
}
]
},
{
"c": [
{
"v": "23 Nov"
},
{
"v": 18,
}
]
},
//FUTURE PROJECTION
{
"c": [
{
"v": "24 Nov"
},
{
"v": 17,
}
]
},
{
"c": [
{
"v": "25 Nov"
},
{
"v": 15,
}
]
},
]
},
"options": {
"isStacked": "true",
"fill": 20,
"displayExactValues": true,
"legend": {"position":'none'},
}
}
You could achieve the desired results by utilizing column roles:
A column role describes the purpose of the data in that column: for
example, a column might hold data describing tooltip text, data point
annotations, or uncertainty indicators.
So, let's introduce a style role column:
{
"type": "string",
"role": "style",
"p": { "role": "style" }
}
And then, specify line style:
{ "v": "line { stroke-color: green }" }
The following modified example demonstrates how to style line segments in different colors:
var app = angular.module('myApp', ['googlechart']);
app.controller('chartCtrl', function ($scope) {
$scope.stat = {
"type": "LineChart",
"displayed": false,
"data": {
"cols": [
{
"id": "date",
"label": "Date",
"type": "string",
},
{
"id": "sales-id",
"label": "Sales",
"type": "number",
},
{
"type": "string",
"role": "style",
"p": { "role": "style" }
}
],
"rows": [
{
"c": [
{
"v": "20 Nov"
},
{
"v": 19,
},
{ "v": null }
]
},
{
"c": [
{
"v": "21 Nov"
},
{
"v": 17,
},
{ "v": null }
]
},
{
"c": [
{
"v": "22 Nov"
},
{
"v": 18,
},
{ "v": null }
]
},
{
"c": [
{
"v": "23 Nov"
},
{
"v": 18,
},
{ "v": null }
]
},
//FUTURE PROJECTION
{
"c": [
{
"v": "24 Nov"
},
{
"v": 17,
},
{ "v": "line { stroke-color: green }" }
]
},
{
"c": [
{
"v": "25 Nov"
},
{
"v": 15,
},
{ "v": "line { stroke-color: green }" }
]
},
]
},
"options": {
"isStacked": "true",
"fill": 20,
"displayExactValues": true,
"legend": { "position": 'none' },
}
}
});
<script src="http://code.angularjs.org/1.2.10/angular.js"></script>
<script src="http://bouil.github.io/angular-google-chart/ng-google-chart.js"></script>
<div ng-app='myApp' ng-controller="chartCtrl">
<div google-chart chart="stat"></div>
</div>
JSFiddle
I have a page that connects to a google analytics account. On the page I have a GEO chart focused on the state of Florida.
When I hover over the markers on the map, about half of the markers appear to be correct. The other half are labeled with city names that dont match their marker on the map. Like markers in the middle of the state being labeled as a city in Brazil For examples see the screenshots below.
Here's my code that sets up the GEO Charts. Any idea what Im doing wrong?
Also here is a jsbin
(function(w,d,s,g,js,fjs){
g=w.gapi||(w.gapi={});g.analytics={q:[],ready:function(cb){this.q.push(cb);}};
js=d.createElement(s);fjs=d.getElementsByTagName(s)[0];
js.src='https://apis.google.com/js/platform.js';
fjs.parentNode.insertBefore(js,fjs);js.onload=function(){g.load('analytics');};
}(window,document,'script'));
gapi.analytics.ready(function() {
var CLIENT_ID = '663097249213-ankiu39ud1m7imaa4r5h5mtt4bnpp9b5.apps.googleusercontent.com';
gapi.analytics.auth.authorize({
container: 'auth-button',
clientid: CLIENT_ID,
});
var viewSelector = new gapi.analytics.ViewSelector({
container: 'view-selector'
});
var stateMap = new gapi.analytics.googleCharts.DataChart({
query: {
'dimensions': 'ga:city',
'metrics': 'ga:sessions',
'start-date': '14daysAgo',
'end-date': 'yesterday',
},
chart: {
type: 'GEO',
container: 'state',
options: {
region: 'US-FL',
resolution: 'metros',
displayMode: 'markers',
width:'100%',
height:'100%',
keepAspectRatio:true
}
}
});
gapi.analytics.auth.on('success', function(response) {
viewSelector.execute();
$('#auth-button').hide();
});
viewSelector.on('change', function(ids) {
var newIds = {
query: {
ids: ids
}
};
stateMap.set(newIds).execute();
});
});
Here are the request headers:
Remote Address:74.125.137.95:443
Request URL:https://content.googleapis.com/analytics/v3/data/ga?start-date=7daysAgo&end-date=yesterday&dimensions=ga%3AuserType&metrics=ga%3Asessions&sort=-ga%3Asessions&max-results=9&ids=ga%3A91097884&output=dataTable&embedApiVersion=v1
Request Method:GET
Status Code:200 OK
Request Headers
:host:content.googleapis.com
:method:GET
:path:/analytics/v3/data/ga?start-date=7daysAgo&end-date=yesterday&dimensions=ga%3AuserType&metrics=ga%3Asessions&sort=-ga%3Asessions&max-results=9&ids=ga%3A91097884&output=dataTable&embedApiVersion=v1
:scheme:https
:version:HTTP/1.1
accept:*/*
accept-encoding:gzip,deflate,sdch
accept-language:en-US,en;q=0.8
authorization:Bearer ya29.qgAhgT4Oq1u6e_cfcv1qP2ieP_QUbPM0WozLPpagwZ_9rmXM8G0s0uDK
cache-control:no-cache
pragma:no-cache
referer:https://content.googleapis.com/static/proxy.html?jsh=m%3B%2F_%2Fscs%2Fapps-static%2F_%2Fjs%2Fk%3Doz.gapi.en.FnxxMUT2ulE.O%2Fm%3D__features__%2Fam%3DAQ%2Frt%3Dj%2Fd%3D1%2Ft%3Dzcms%2Frs%3DAGLTcCMEC-DWdYC4P42L_5byzwhSZYF3Cg
user-agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.104 Safari/537.36
x-client-data:CJe2yQEIprbJAQiptskBCMG2yQEI8IjKAQiPlMoBCN6WygE=
x-clientdetails:appVersion=5.0%20(Macintosh%3B%20Intel%20Mac%20OS%20X%2010_10_0)%20AppleWebKit%2F537.36%20(KHTML%2C%20like%20Gecko)%20Chrome%2F38.0.2125.104%20Safari%2F537.36&platform=MacIntel&userAgent=Mozilla%2F5.0%20(Macintosh%3B%20Intel%20Mac%20OS%20X%2010_10_0)%20AppleWebKit%2F537.36%20(KHTML%2C%20like%20Gecko)%20Chrome%2F38.0.2125.104%20Safari%2F537.36
x-goog-encode-response-if-executable:base64
x-javascript-user-agent:google-api-javascript-client/1.1.0-beta
x-origin:http://affordable-glass.com
x-referer:http://affordable-glass.com
Query String Parametersview sourceview URL encoded
start-date:7daysAgo
end-date:yesterday
dimensions:ga:userType
metrics:ga:sessions
sort:-ga:sessions
max-results:9
ids:ga:91097884
output:dataTable
embedApiVersion:v1
Response Headers
alternate-protocol:443:quic,p=0.01
cache-control:private, max-age=0, must-revalidate, no-transform
content-encoding:gzip
content-length:555
content-type:application/json; charset=UTF-8
date:Sun, 26 Oct 2014 00:35:09 GMT
etag:"C7PuqpcNYAngGhjHeeJxl43WaQM/65Qv4TMpW0C9gHm-VUHXAtDeU9g"
expires:Sun, 26 Oct 2014 00:35:09 GMT
server:GSE
status:200 OK
vary:Referer
vary:X-Origin
vary:Origin
version:HTTP/1.1
x-content-type-options:nosniff
x-frame-options:SAMEORIGIN
x-xss-protection:1; mode=block
Here is the data that gets returned by Google:
{
"kind": "analytics#gaData",
"id": "https://www.googleapis.com/analytics/v3/data/ga?ids=ga:91097884&dimensions=ga:city&metrics=ga:sessions&start-date=14daysAgo&end-date=yesterday",
"query": {
"start-date": "14daysAgo",
"end-date": "yesterday",
"ids": "ga:91097884",
"dimensions": "ga:city",
"metrics": ["ga:sessions"],
"start-index": 1,
"max-results": 1000
},
"itemsPerPage": 1000,
"totalResults": 47,
"selfLink": "https://www.googleapis.com/analytics/v3/data/ga?ids=ga:91097884&dimensions=ga:city&metrics=ga:sessions&start-date=14daysAgo&end-date=yesterday",
"profileInfo": {
"profileId": "91097884",
"accountId": "54755159",
"webPropertyId": "UA-54755159-1",
"internalWebPropertyId": "87741876",
"profileName": "All Web Site Data",
"tableId": "ga:91097884"
},
"containsSampledData": false,
"columnHeaders": [{
"name": "ga:city",
"columnType": "DIMENSION",
"dataType": "STRING"
}, {
"name": "ga:sessions",
"columnType": "METRIC",
"dataType": "INTEGER"
}],
"totalsForAllResults": {
"ga:sessions": "75"
},
"dataTable": {
"cols": [{
"id": "ga:city",
"label": "ga:city",
"type": "string"
}, {
"id": "ga:sessions",
"label": "ga:sessions",
"type": "number"
}],
"rows": [{
"c": [{
"v": "(not set)"
}, {
"v": "3"
}]
}, {
"c": [{
"v": "Ashburn"
}, {
"v": "1"
}]
}, {
"c": [{
"v": "Atlanta"
}, {
"v": "4"
}]
}, {
"c": [{
"v": "Bari"
}, {
"v": "1"
}]
}, {
"c": [{
"v": "Belo Horizonte"
}, {
"v": "1"
}]
}, {
"c": [{
"v": "Biloxi"
}, {
"v": "1"
}]
}, {
"c": [{
"v": "Birmingham"
}, {
"v": "1"
}]
}, {
"c": [{
"v": "Bradenton"
}, {
"v": "2"
}]
}, {
"c": [{
"v": "Chandler"
}, {
"v": "2"
}]
}, {
"c": [{
"v": "Columbus"
}, {
"v": "1"
}]
}, {
"c": [{
"v": "Cordoba"
}, {
"v": "1"
}]
}, {
"c": [{
"v": "Dallas"
}, {
"v": "1"
}]
}, {
"c": [{
"v": "Eastpoint"
}, {
"v": "1"
}]
}, {
"c": [{
"v": "Erlanger"
}, {
"v": "1"
}]
}, {
"c": [{
"v": "Fort Bragg"
}, {
"v": "1"
}]
}, {
"c": [{
"v": "Foz do Iguacu"
}, {
"v": "1"
}]
}, {
"c": [{
"v": "Fresno"
}, {
"v": "1"
}]
}, {
"c": [{
"v": "Funchal"
}, {
"v": "1"
}]
}, {
"c": [{
"v": "Houston"
}, {
"v": "1"
}]
}, {
"c": [{
"v": "Jacksonville"
}, {
"v": "1"
}]
}, {
"c": [{
"v": "Lake Oswego"
}, {
"v": "1"
}]
}, {
"c": [{
"v": "Lake Worth"
}, {
"v": "2"
}]
}, {
"c": [{
"v": "Londrina"
}, {
"v": "2"
}]
}, {
"c": [{
"v": "Lynn Haven"
}, {
"v": "2"
}]
}, {
"c": [{
"v": "Mar del Plata"
}, {
"v": "1"
}]
}, {
"c": [{
"v": "Marianna"
}, {
"v": "2"
}]
}, {
"c": [{
"v": "Middletown"
}, {
"v": "2"
}]
}, {
"c": [{
"v": "Miramar Beach"
}, {
"v": "1"
}]
}, {
"c": [{
"v": "Montreal"
}, {
"v": "1"
}]
}, {
"c": [{
"v": "Navarre"
}, {
"v": "1"
}]
}, {
"c": [{
"v": "Panama City"
}, {
"v": "9"
}]
}, {
"c": [{
"v": "Panama City Beach"
}, {
"v": "7"
}]
}, {
"c": [{
"v": "Pecan Grove"
}, {
"v": "1"
}]
}, {
"c": [{
"v": "Porto Alegre"
}, {
"v": "1"
}]
}, {
"c": [{
"v": "Providence"
}, {
"v": "1"
}]
}, {
"c": [{
"v": "Rio de Janeiro"
}, {
"v": "1"
}]
}, {
"c": [{
"v": "Sabadell"
}, {
"v": "1"
}]
}, {
"c": [{
"v": "Sao Paulo"
}, {
"v": "3"
}]
}, {
"c": [{
"v": "Seria"
}, {
"v": "1"
}]
}, {
"c": [{
"v": "Surrey"
}, {
"v": "1"
}]
}, {
"c": [{
"v": "Tallahassee"
}, {
"v": "1"
}]
}, {
"c": [{
"v": "Tampa"
}, {
"v": "1"
}]
}, {
"c": [{
"v": "The Woodlands"
}, {
"v": "1"
}]
}, {
"c": [{
"v": "Toronto"
}, {
"v": "1"
}]
}, {
"c": [{
"v": "Virginia Beach"
}, {
"v": "1"
}]
}, {
"c": [{
"v": "Wellington"
}, {
"v": "1"
}]
}, {
"c": [{
"v": "Wyndham"
}, {
"v": "1"
}]
}]
}
}
It does the same if I try it with a US map:
I have been working with the GEO chart for the EMBED api and had the exact same issues. It seems to me that the GEO chart is pretty feature limited, and the region you set has no bearing on what data it shows, but instead, only zooms the map to the appropriate viewing area. I added a filter to my query, I think this will work for you...
"query": {
"start-date": "14daysAgo",
"end-date": "yesterday",
"ids": "ga:91097884",
"dimensions": "ga:city",
"metrics": ["ga:sessions"],
"start-index": 1,
"max-results": 1000,
"filters": "ga:region==Florida"
},
Note the last line with the filter, I know this may not be ideal, but it is the only way I could get the Embed GEO chart to work properly.