Prebid - exisiting gpt tag conflicts with Prebid js script - google-dfp

We have an existing gpt tag(Not Prebid) placed on our site for ad. Recently we integrated prebid.js in our website. Our prebid code works well but existing gpt tag does not return anything. My assumptions are given below after some testing.
gpt tag conflicts with header bidding.
gpt tag is not calling defineSlot Because no google-query-id is generated on ad tag.
I have searched on google but did not find anything useful. Can anyone help?
gpt tag Code:
<script async src="https://securepubads.g.doubleclick.net/tag/js/gpt.js"></script>
<script>
window.googletag = window.googletag || {cmd: []};
googletag.cmd.push(function() {
googletag.defineSlot('/xxxx/xxxx', 'div-gpt-ad-xxxxxx').addService(googletag.pubads());
googletag.pubads().enableSingleRequest();
googletag.enableServices();
});
</script>
Prebid Code:
var div_1_sizes = [
[300, 75],
[320, 50],
[728, 90],
[300, 50],
];
var PREBID_TIMEOUT = 100000;
var FAILSAFE_TIMEOUT = 3000;
var adUnits = [
{
code: "xxxxx",
mediaTypes: {
banner: {
sizes: div_1_sizes,
},
},
bids: [
{
bidder: "minutemedia",
labelAny: ["desktop", "phone"],
params: {
org: "xxxx",
placementId: "xxx",
floorPrice: 0.05,
},
},
],
},
];
// ======== DO NOT EDIT BELOW THIS LINE =========== //
var googletag = googletag || {};
googletag.cmd = googletag.cmd || [];
googletag.cmd.push(function () {
googletag.pubads().disableInitialLoad();
});
var pbjs = pbjs || {};
pbjs.que = pbjs.que || [];
pbjs.que.push(function () {
pbjs.addAdUnits(adUnits);
pbjs.setConfig({
enableSendAllBids: true,
sizeConfig: [
{
mediaQuery: "(min-width: 1000px)",
sizesSupported: [
[728, 90],
],
labels: ["desktop"],
},
{
mediaQuery: "(min-width: 0px) and (max-width: 600px)",
sizesSupported: [
[300, 75],
[320, 50],
[300, 50],
],
labels: ["phone"],
},
],
});
pbjs.requestBids({
bidsBackHandler: initAdserver,
timeout: PREBID_TIMEOUT,
});
});
function initAdserver() {
if (pbjs.initAdserverSet) return;
pbjs.initAdserverSet = true;
googletag.cmd.push(function () {
pbjs.que.push(function () {
pbjs.setTargetingForGPTAsync();
googletag.pubads().refresh();
});
});
}
// in case PBJS doesn't load
setTimeout(function () {
initAdserver();
}, FAILSAFE_TIMEOUT);
googletag.cmd.push(function () {
var mapping1 = googletag
.sizeMapping()
.addSize([1200, 0], [[728, 90]])
.addSize(
[320, 0],
[
[300, 50],
[320, 50],
[300, 75],
]
)
.addSize(
[0, 0],
[
[300, 50],
[320, 50],
[300, 75],
]
)
.build();
googletag
.defineSlot(
"xxxx",
div_1_sizes,
"xxxx"
)
.defineSizeMapping(mapping1)
.addService(googletag.pubads());
googletag.pubads().enableSingleRequest();
googletag.pubads().collapseEmptyDivs();
googletag.enableServices();
});
`

Remove these 2 lines from your original GPT call and it should be fine
googletag.pubads().enableSingleRequest();
googletag.enableServices();

Related

Google Bar Chart - custom Legend text with total values & column wise total for Table chart

i would like get the total value of Grades in Stacked Bar Graph Legend. picture attached how i wud like to have... for the following working snippet.
and also the Column wise Total for the Table Chart...
i think this can be done with following but how to get it done..
data.setFormattedValue(i, 0, key + ' (' + val + ')');
can have something like this.. when mouseover one location on Bar... need to show all the grades values in single annotation..??
is it possible to have the different values in highlighted places like in below picture? circle B is overall total of Grade1 in graph is correct. and circle A the tooltip total should show for that particular locations total of every Grade's annotation like below.
['Location', 'Company', 'Grade1',{ role: 'annotation' }, 'Grade2',{ role: 'annotation' }, 'Grade3',{ role: 'annotation' }, 'Bal-Grade', 'Total', { role: 'annotation' } ],
google.charts.load('current', {
packages: ['corechart', 'table', 'gauge', 'controls']
}).then(function () {
drawMainDashboard();
});
function drawMainDashboard() {
var dashboard = new google.visualization.Dashboard(
document.getElementById('dashboard_division1'));
var categoryPicker = new google.visualization.ControlWrapper({
'controlType': 'CategoryFilter',
'containerId': 'categoryPicker_div',
'options': {
'filterColumnIndex': 1,
'ui': {
'labelStacking': 'vertical',
'label': 'Company Selection:',
'allowTyping': false,
'allowMultiple': false
}
}
});
var categoryPicker1 = new google.visualization.ControlWrapper({
'controlType': 'CategoryFilter',
'containerId': 'categoryPicker_div1',
'options': {
'filterColumnIndex': 0,
'ui': {
'labelStacking': 'vertical',
'label': 'Location Selection:',
'allowTyping': false,
'allowMultiple': false
}
}
});
var columnchrt = new google.visualization.ChartWrapper({
'chartType': 'ColumnChart',
'containerId': 'chart_div',
'options': {
title: "Locations charts",
width: 850,
height: 500,
legend: { position: 'top', maxLines: 2 },
bar: { groupWidth: '70%' },
isStacked: true,
focusTarget: 'category',
aggregationTarget: 'category',
explorer: {keepInBounds: true, maxZoomIn: 10.0}
}
});
var table = new google.visualization.ChartWrapper({
'chartType': 'Table',
'containerId': 'table_div',
'options': {
showRowNumber: true,
width: '100%',
height: '100%',
allowHtml: true
},
'view': {'columns': [0,1,2,3,4,5,6]}
});
google.visualization.events.addOneTimeListener(table, 'ready', calcTotals);
function calcTotals() {
// get filtered data table from table chart
var dt = table.getDataTable();
// build aggregation and view columns
var aggColumns = [];
var viewColumns = [0];
for (var i = 2; i < dt.getNumberOfColumns(); i++) {
if (i !== dt.getNumberOfColumns() - 1) {
if (dt.getColumnType(i) === 'number') {
if (dt.getColumnRole(i) !== 'annotation') {
addAggColumn(i);
if (i !== dt.getNumberOfColumns() - 2) {
viewColumns.push(i - 1);
}
}
}
}
}
function addAggColumn(index) {
aggColumns.push({
aggregation: google.visualization.data.sum,
column: index,
label: dt.getColumnLabel(index),
type: dt.getColumnType(index)
});
}
// aggregate data table
var agg = google.visualization.data.group(
dt,
[0],
aggColumns
);
var aggTotal = google.visualization.data.group(
dt,
[{
column: 0,
label: 'Total',
modifier: function (val) {
return 'Total';
},
type: 'string'
}],
aggColumns
);
dt = dt.toDataTable();
dt.addRow(['Total', '--', aggTotal.getValue(0, 1), aggTotal.getValue(0, 2), aggTotal.getValue(0, 3), aggTotal.getValue(0, 4), aggTotal.getValue(0, 5), null]);
table.setDataTable(dt);
table.draw();
viewColumns.push({
calc: function (dt, row) {
var total = 0;
for (var c = 1; c < dt.getNumberOfColumns(); c++) {
if (dt.getColumnLabel(c) !== 'Total') {
total += dt.getValue(row, c);
}
}
return total.toFixed(0);
},
role: 'annotation',
type: 'string'
});
// create agg data view to add annotation
var view = new google.visualization.DataView(agg);
view.setColumns(viewColumns);
view = view.toDataTable();
for (var vc = 0; vc < view.getNumberOfColumns(); vc++) {
var viewLabel = view.getColumnLabel(vc);
for (var ac = 0; ac < agg.getNumberOfColumns(); ac++) {
var aggLabel = agg.getColumnLabel(ac);
if (viewLabel === aggLabel) {
view.setColumnLabel(vc, viewLabel + ' (' + aggTotal.getFormattedValue(0, ac) + ')');
}
}
}
// draw chart
columnchrt.setDataTable(view);
columnchrt.draw();
google.visualization.events.addOneTimeListener(table, 'ready', calcTotals);
}
var data = google.visualization.arrayToDataTable([
['Location', 'Company', 'Grade1', 'Grade2', 'Grade3', 'Bal-Grade', 'Total', { role: 'annotation' } ],
['NYC', 'CUSTOMERS', 0, 0, 13, 5, 19, 29],
['CALI', 'ORG', 270, 210, 0, 32, 51, 60],
['CALI', 'CUSTOMERS', 35.942, 39, 0, 50, 126, 150],
['WDC', 'CUSTOMERS', 0, 0, 35, 52, 88, 100],
['WDC', 'CUSTOMERS', 44.507, 0, 25, 18, 88, 110],
['NJ', 'ORG', 0, 0, 54, 22, 28, 45],
['TXS', 'CUSTOMERS', 0, 0, 0, 10, 11, 20]
]);
dashboard.bind([categoryPicker,categoryPicker1], [table]);
dashboard.draw(data);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="dashboard_division" style="clear:left; display:inline-block; width:100%; float:left; margin-top:5px;">
<div class="float_left panel" style="float:left; width:50%; padding:0px;">
<div id="chart_div"></div>
</div>
<div class="float_left panel" style="width:50%; padding:0px;">
<div class="table_bbar" style="background-color:#27ae60;" >
<div id="categoryPicker_div" style="right:15px; position:absolute;"></div>
<div id="categoryPicker_div1" ></div>
</div>
<div id="table_div"></div>
</div>
</div>
to get the total row for the table chart,
we can use a modifier function in the aggregation.
we aggregate once by location,
then again in total.
the modifier function allows us to return the same value for every row,
thus giving us the total for all rows.
then we can add the results from the total agg to the location agg.
// aggregate data table
var agg = google.visualization.data.group(
dt,
[0],
aggColumns
);
var aggTotal = google.visualization.data.group(
dt,
[{
column: 0,
label: 'Total',
modifier: function (val) {
return 'Total';
},
type: 'string'
}],
aggColumns
);
var rowIndex = agg.addRow();
for (var i = 0; i < agg.getNumberOfColumns(); i++) {
agg.setValue(rowIndex, i, aggTotal.getValue(0, i));
}
then we can use the agg total data table to set the labels in the column chart legend.
// create agg data view to add annotation
var view = new google.visualization.DataView(agg);
view.setColumns(viewColumns);
view = view.toDataTable();
for (var vc = 0; vc < view.getNumberOfColumns(); vc++) {
var viewLabel = view.getColumnLabel(vc);
for (var ac = 0; ac < agg.getNumberOfColumns(); ac++) {
var aggLabel = agg.getColumnLabel(ac);
if (viewLabel === aggLabel) {
view.setColumnLabel(vc, viewLabel + ' (' + aggTotal.getFormattedValue(0, ac) + ')');
}
}
}
one other slight change, since we are re-drawing the charts inside the 'ready' event,
we must use a one time event, else we'll go into an endless loop.
google.visualization.events.addOneTimeListener(table, 'ready', calcTotals);
see following working snippet...
google.charts.load('current', {
packages: ['corechart', 'table', 'gauge', 'controls']
}).then(function () {
drawMainDashboard();
});
function drawMainDashboard() {
var dashboard = new google.visualization.Dashboard(
document.getElementById('dashboard_division1'));
var categoryPicker = new google.visualization.ControlWrapper({
'controlType': 'CategoryFilter',
'containerId': 'categoryPicker_div',
'options': {
'filterColumnIndex': 1,
'ui': {
'labelStacking': 'vertical',
'label': 'Company Selection:',
'allowTyping': false,
'allowMultiple': false
}
}
});
var categoryPicker1 = new google.visualization.ControlWrapper({
'controlType': 'CategoryFilter',
'containerId': 'categoryPicker_div1',
'options': {
'filterColumnIndex': 0,
'ui': {
'labelStacking': 'vertical',
'label': 'Location Selection:',
'allowTyping': false,
'allowMultiple': false
}
}
});
var columnchrt = new google.visualization.ChartWrapper({
'chartType': 'ColumnChart',
'containerId': 'chart_div',
'options': {
title: "Locations charts",
width: 850,
height: 500,
legend: { position: 'top', maxLines: 2 },
bar: { groupWidth: '70%' },
isStacked: true,
explorer: {keepInBounds: true, maxZoomIn: 10.0}
}
});
var table = new google.visualization.ChartWrapper({
'chartType': 'Table',
'containerId': 'table_div',
'options': {
showRowNumber: true,
width: '100%',
height: '100%',
allowHtml: true
},
'view': {'columns': [0,1,2,3,4,5,6]}
});
google.visualization.events.addOneTimeListener(table, 'ready', calcTotals);
function calcTotals() {
// get filtered data table from table chart
var dt = table.getDataTable();
// build aggregation and view columns
var aggColumns = [];
var viewColumns = [0];
for (var i = 2; i < dt.getNumberOfColumns(); i++) {
if (i !== dt.getNumberOfColumns() - 1) {
if (dt.getColumnType(i) === 'number') {
if (dt.getColumnRole(i) !== 'annotation') {
addAggColumn(i);
if (i !== dt.getNumberOfColumns() - 2) {
viewColumns.push(i - 1);
}
}
}
}
}
function addAggColumn(index) {
aggColumns.push({
aggregation: google.visualization.data.sum,
column: index,
label: dt.getColumnLabel(index),
type: dt.getColumnType(index)
});
}
// aggregate data table
var agg = google.visualization.data.group(
dt,
[0],
aggColumns
);
var aggTotal = google.visualization.data.group(
dt,
[{
column: 0,
label: 'Total',
modifier: function (val) {
return 'Total';
},
type: 'string'
}],
aggColumns
);
dt = dt.toDataTable();
dt.addRow(['Total', '--', aggTotal.getValue(0, 1), aggTotal.getValue(0, 2), aggTotal.getValue(0, 3), aggTotal.getValue(0, 4), aggTotal.getValue(0, 5), null]);
table.setDataTable(dt);
table.draw();
viewColumns.push({
calc: function (dt, row) {
var total = 0;
for (var c = 1; c < dt.getNumberOfColumns(); c++) {
if (dt.getColumnLabel(c) !== 'Total') {
total += dt.getValue(row, c);
}
}
return total.toFixed(0);
},
role: 'annotation',
type: 'string'
});
// create agg data view to add annotation
var view = new google.visualization.DataView(agg);
view.setColumns(viewColumns);
view = view.toDataTable();
for (var vc = 0; vc < view.getNumberOfColumns(); vc++) {
var viewLabel = view.getColumnLabel(vc);
for (var ac = 0; ac < agg.getNumberOfColumns(); ac++) {
var aggLabel = agg.getColumnLabel(ac);
if (viewLabel === aggLabel) {
view.setColumnLabel(vc, viewLabel + ' (' + aggTotal.getFormattedValue(0, ac) + ')');
}
}
}
// draw chart
columnchrt.setDataTable(view);
columnchrt.draw();
google.visualization.events.addOneTimeListener(table, 'ready', calcTotals);
}
var data = google.visualization.arrayToDataTable([
['Location', 'Company', 'Grade1', 'Grade2', 'Grade3', 'Bal-Grade', 'Total', { role: 'annotation' } ],
['NYC', 'CUSTOMERS', 0, 0, 13, 5, 19, 19],
['CALI', 'ORG', 270, 210, 0, 32, 51, 51],
['CALI', 'CUSTOMERS', 35.942, 39, 0, 50, 126, 126],
['WDC', 'CUSTOMERS', 0, 0, 35, 52, 88, 88],
['WDC', 'CUSTOMERS', 44.507, 0, 25, 18, 88, 88],
['NJ', 'ORG', 0, 0, 54, 22, 28, 28],
['TXS', 'CUSTOMERS', 0, 0, 0, 10, 11, 11]
]);
dashboard.bind([categoryPicker,categoryPicker1], [table]);
dashboard.draw(data);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="dashboard_division" style="clear:left; display:inline-block; width:100%; float:left; margin-top:5px;">
<div class="float_left panel" style="float:left; width:50%; padding:0px;">
<div id="chart_div"></div>
</div>
<div class="float_left panel" style="width:50%; padding:0px;">
<div class="table_bbar" style="background-color:#27ae60;" >
<div id="categoryPicker_div" style="right:15px; position:absolute;"></div>
<div id="categoryPicker_div1" ></div>
</div>
<div id="table_div"></div>
</div>
</div>

Google Stepped Area Chart with custom annotation

Thanks to White Hat in this post ,I was able to make a custom annotation for the area chart. Somehow it doesn't work the stepped area chart.
The chart draws at first everything correctly but then sets the annotation in the stepped area chart back. With help of the MutationObserver, the settings should be overridden when the chart is drawn but this applies just for the area chart.
How can I solve this ?
<html>
<head>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var data1 = new google.visualization.DataTable();
data1.addColumn('number', 'x');
data1.addColumn('number', 'green');
data1.addRows([
[0.005, 3],
[0.006, 6],
[0.007, 5],
[0.008, 8],
[0.009, 2],
[0.010, 5],
[0.011, 5],
[0.012, 4],
[0.013, 8]
]);
var data2 = new google.visualization.DataTable();
data2.addColumn('number', 'x');
data2.addColumn('number', 'red');
data2.addRows([
[0.016, 5],
[0.017, 1],
[0.018, 3],
[0.019, 9],
[0.020, 4],
[0.021, 5],
[0.022, 7],
[0.023, 7],
[0.024, 3]
]);
var joinedData = google.visualization.data.join(data1, data2, 'full',
[[0, 0]], [1], [1]);
var options = {
annotations: {
stem: {
length: 10
}
},
title: 'Playground',
colors: ['#007f01', '#fe0002'],
interpolateNulls: true,
hAxis: {
titleTextStyle: {
color: '#333'
},
direction: 1,
format: 'decimal'
},
vAxis: {
direction: 1
},
orientation: 'horizontal',
// customize colum
series: {
0: {type: "steppedArea"},
1: {type: "area"},
},
// legend: {position : 'left'},
animation: {
startup: true,
duration: 1000,
easing: 'out',
}
};
var view = new google.visualization.DataView(joinedData);
view.setColumns([0,
1,
{
calc: "stringify",
sourceColumn: 1,
type: "string",
role: "annotation"
},
2,
{
calc: "stringify",
sourceColumn: 2,
type: "string",
role: "annotation"
}
]);
var container = document.getElementById('chart_div');
var chart = new google.visualization.ComboChart(container);
var observer = new MutationObserver(moveAnnotations);
observer.observe(container, {
childList: true,
subtree: true
});
function moveAnnotations() {
var chartLayout = chart.getChartLayoutInterface();
var chartBounds = chartLayout.getChartAreaBoundingBox();
var labels = container.getElementsByTagName('text');
var labelSize = 0;
Array.prototype.forEach.call(labels, function(label) {
if (label.getAttribute('text-anchor') === 'middle') {
if (options.colors.indexOf(label.getAttribute('fill')) > -1) {
labelSize = (parseFloat(label.getAttribute('font-size')) / 2);
label.setAttribute('y', chartBounds.top + labelSize);
}
}
});
var stems = container.getElementsByTagName('rect');
Array.prototype.forEach.call(stems, function(stem) {
if ((parseInt(stem.getAttribute('height')) === options.annotations.stem.length) && (stem.getAttribute('fill') === '#999999')) {
var height = parseFloat(stem.getAttribute('y')) - chartBounds.top;
stem.setAttribute('height', height);
stem.setAttribute('y', chartBounds.top + labelSize);
}
});
}
chart.draw(view.toDataTable(), options);
});
</script>
</head>
<body>
<div id="chart_div" style="width: 100%; height: 500px;"></div>
</body>
</html>
the default annotation settings for stepped area charts differ from normal area charts
for stepped, the annotations appear inside the area, which changes the color to white,
which is not a color used to find the labels and move them
an easy fix is to specify that the annotation always be outside the area...
annotations: {
alwaysOutside: true,
...
see following working snippet...
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var data1 = new google.visualization.DataTable();
data1.addColumn('number', 'x');
data1.addColumn('number', 'green');
data1.addRows([
[0.005, 3],
[0.006, 6],
[0.007, 5],
[0.008, 8],
[0.009, 2],
[0.010, 5],
[0.011, 5],
[0.012, 4],
[0.013, 8]
]);
var data2 = new google.visualization.DataTable();
data2.addColumn('number', 'x');
data2.addColumn('number', 'red');
data2.addRows([
[0.016, 5],
[0.017, 1],
[0.018, 3],
[0.019, 9],
[0.020, 4],
[0.021, 5],
[0.022, 7],
[0.023, 7],
[0.024, 3]
]);
var joinedData = google.visualization.data.join(data1, data2, 'full',
[[0, 0]], [1], [1]);
var options = {
annotations: {
alwaysOutside: true,
stem: {
length: 10
}
},
title: 'Playground',
colors: ['#007f01', '#fe0002'],
interpolateNulls: true,
hAxis: {
titleTextStyle: {
color: '#333'
},
direction: 1,
format: 'decimal'
},
vAxis: {
direction: 1
},
orientation: 'horizontal',
// customize colum
series: {
0: {type: "steppedArea"},
1: {type: "area"},
},
// legend: {position : 'left'},
animation: {
startup: true,
duration: 1000,
easing: 'out',
}
};
var view = new google.visualization.DataView(joinedData);
view.setColumns([0,
1,
{
calc: "stringify",
sourceColumn: 1,
type: "string",
role: "annotation"
},
2,
{
calc: "stringify",
sourceColumn: 2,
type: "string",
role: "annotation"
}
]);
var container = document.getElementById('chart_div');
var chart = new google.visualization.ComboChart(container);
var observer = new MutationObserver(moveAnnotations);
observer.observe(container, {
childList: true,
subtree: true
});
function moveAnnotations() {
var chartLayout = chart.getChartLayoutInterface();
var chartBounds = chartLayout.getChartAreaBoundingBox();
var labels = container.getElementsByTagName('text');
var labelSize = 0;
Array.prototype.forEach.call(labels, function(label) {
if (label.getAttribute('text-anchor') === 'middle') {
if (options.colors.indexOf(label.getAttribute('fill')) > -1) {
labelSize = (parseFloat(label.getAttribute('font-size')) / 2);
label.setAttribute('y', chartBounds.top + labelSize);
}
}
});
var stems = container.getElementsByTagName('rect');
Array.prototype.forEach.call(stems, function(stem) {
if ((parseInt(stem.getAttribute('height')) === options.annotations.stem.length) && (stem.getAttribute('fill') === '#999999')) {
var height = parseFloat(stem.getAttribute('y')) - chartBounds.top;
stem.setAttribute('height', height);
stem.setAttribute('y', chartBounds.top + labelSize);
}
});
}
chart.draw(view.toDataTable(), options);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>

DFP refresh ad afer X seconds in view

i'm looking to also do this but using the GPT APi ( i'm pretty new to this coding stuff, so no real clue what doing, so looking for help in effect)
I found this in the GPT ApI docs:
Impression viewable listener, slot specific logic.
The listener will be called when the impression is considered viewable.
This event also operates at service level, but, as above, you can filter
to respond only to a certain ad slot by using this pattern
googletag.pubads().addEventListener('impressionViewable', function(event) {
if (event.slot == targetSlot) {
//Slot specific logic.
}
});
and already have this, which is refreshing the ads after X seconds
googletag.cmd.push(function() {
var mappingleaderslot = googletag.sizeMapping().
addSize([1024, 769], [[970,250],[970,90],[728,90],[468,60],[320,50],[234,60]]).
addSize([768, 500], [[728,90],[468,60],[320,50],[234,60]]).
addSize([1, 1], [[320,50],[234,60]]).
build();
var mappingbigboxslot = googletag.sizeMapping().
addSize([1024, 769], [[300,600],[300,250],[160,600],[120,600],[250,250]]).
addSize([768, 500], [[300,250],[250,250]]).
addSize([1, 1], [[300,250],[250,250]]).
build();
topSlot = googletag.defineSlot('/1001824/prebid_test2', [[970, 250],[970, 90],[728, 90],[468, 60],[320, 50],[234, 60]], 'topSlot').defineSizeMapping(mappingleaderslot).setTargeting("test", "refresh").addService(googletag.pubads());
middlerightSlot = googletag.defineSlot('/1001824/prebid_test3', [[300, 600],[300, 250],[160, 600],[120, 600],[250, 250]], 'middlerightSlot').defineSizeMapping(mappingbigboxslot).setTargeting("test", "refresh").addService(googletag.pubads());
bottomrightSlot = googletag.defineSlot('/1001824/prebid_test1', [[300, 600],[300, 250],[160, 600],[120, 600],[250, 250]], 'bottomrightSlot').defineSizeMapping(mappingbigboxslot).setTargeting("test", "refresh").addService(googletag.pubads());
bottomleftSlot = googletag.defineSlot('/1001824/prebid_test4', [[300, 600],[300, 250],[160, 600],[120, 600],[250,250]], 'bottomleftSlot').defineSizeMapping(mappingbigboxslot).setTargeting("test", "refresh").addService(googletag.pubads());
googletag.pubads().enableSingleRequest();
googletag.pubads().collapseEmptyDivs(true, true);
googletag.pubads().setCentering(true);
googletag.enableServices();
googletag.display("topSlot");
googletag.display("middlerightSlot");
googletag.display("bottomrightSlot");
googletag.display("bottomleftSlot");
setInterval(function(){googletag.pubads().refresh([topSlot]);}, 120000);
setInterval(function(){googletag.pubads().refresh([middlerightSlot]);}, 120000);
setInterval(function(){googletag.pubads().refresh([bottomrightSlot]);}, 120000);
setInterval(function(){googletag.pubads().refresh([bottomleftSlot]);}, 120000);
});
function refreshSlot(slot) {
pbjs.que.push(function() {
pbjs.requestBids({
timeout: PREBID_TIMEOUT,
adUnitCodes: [slot.getSlotElementId()],
bidsBackHandler: function() {
pbjs.setTargetingForGPTAsync([slot.getSlotElementId()]);
googletag.pubads().refresh([slot]);
}
});
});
}
function refreshtopSlot() {
refreshSlot(topSlot);
}
function refreshmiddlerightSlot() {
refreshSlot(middlerightSlot);
}
function refreshbottomrightSlot() {
refreshSlot(bottomrightSlot);
}
function refreshbottomleftSlot() {
refreshSlot(bottomleftSlot);
}
but no clue how i can combine the two, so as the ad refreshes once its been "in view" for X seconds, any pointers/can anyone help me?
think i found another issue, if a prebid ad renders first, it doest then push the prebid que/ page bids to the "next" prebid bid, it refreshes the same bid, so there is no subsiquent "rev" to be had. i tried adding this but dont seem to work
googletag.pubads().addEventListener('impressionViewable', function
(event) {
var elementId = event.slot.getSlotElementId();
var slotConfig = slots[elementId];
if (slotConfig) {
var handle = setTimeout(function () {
googletag.cmd.push(function () {
function refreshBid() {
pbjs.que.push(function() {
pbjs.requestBids({
timeout: PREBID_TIMEOUT,
bidsBackHandler: function() {
googletag.pubads().refresh([slot1]);
You can take a look a this Gist, it has a full code example.
Here is the Javascript example
var size = [
//[300, 600],
//[300, 250],
//[160, 600],
//[120, 600],
[250, 250]
];
var PREBID_TIMEOUT = 1000;
googletag.cmd.push(function () {
(function (googletag, pbjs, config) {
var sizeMappings = {};
var slots = {};
function refreshSlot(slot) {
pbjs.que.push(function() {
pbjs.requestBids({
timeout: PREBID_TIMEOUT,
adUnitCodes: [slot.getSlotElementId()],
bidsBackHandler: function() {
pbjs.setTargetingForGPTAsync([slot.getSlotElementId()]);
googletag.pubads().refresh([slot]);
}
});
});
}
Object.keys(config.sizeMappings).forEach(function (key) {
var sizeMappingBuilder = googletag.sizeMapping();
config.sizeMappings[key].forEach(function (mapping) {
sizeMappingBuilder.addSize(mapping[0], mapping[1]);
});
var sizeMapping = sizeMappingBuilder.build();
sizeMappings[key] = sizeMapping;
console.log('created sizemapping ', key, ' ', sizeMappings[key]);
});
//googletag.pubads().enableSingleRequest();
googletag.pubads().collapseEmptyDivs(true, true);
googletag.pubads().setCentering(true);
googletag.pubads().disableInitialLoad();
googletag.enableServices();
googletag.pubads().addEventListener('impressionViewable', function (event) {
var elementId = event.slot.getSlotElementId();
var slotConfig = slots[elementId];
if (slotConfig) {
var handle = setTimeout(function () {
googletag.cmd.push(function () {
refreshSlot(event.slot);
});
}, config.definitons[elementId].timeout);
console.log('handle for time ', handle, ' elementId ', elementId, ' duration ', config.definitons[elementId].timeout);
}
});
Object.keys(config.definitons).forEach(function (key) {
var def = config.definitons[key];
var slot = googletag.defineSlot(def.adUnitPath, def.size, key);
slot.setTargeting('test', 'refresh');
slot.defineSizeMapping(sizeMappings[def.sizeMapping]);
slot.addService(googletag.pubads());
googletag.display(key);
slots[key] = { slot: slot };
});
googletag.pubads().refresh();
})(window.googletag, window.pbjs, {
definitons: {
topSlot: {
adUnitPath: '/1001824/prebid_test2',
size: size,
sizeMapping: 'mappingleaderslot',
timeout: 5000,
},
middlerightSlot: {
adUnitPath: '/1001824/prebid_test3',
size: size,
sizeMapping: 'mappingbigboxslot',
timeout: 3000,
},
bottomrightSlot: {
adUnitPath: '/1001824/prebid_test1',
size: size,
sizeMapping: 'mappingbigboxslot',
timeout: 3000,
},
bottomleftSlot: {
adUnitPath: '/1001824/prebid_test4',
size: size,
sizeMapping: 'mappingbigboxslot',
timeout: 3000,
},
},
sizeMappings: {
mappingleaderslot: [
[
[1024, 769],
[
[970, 250],
[970, 90],
[728, 90],
[468, 60],
[320, 50],
[234, 60]
]
],
[
[768, 500],
[
[728, 90],
[468, 60],
[320, 50],
[234, 60]
]
],
[
[1, 1],
[
[320, 50],
[234, 60]
]
],
],
mappingbigboxslot: [
[
[1024, 769],
[
[300, 600],
[300, 250],
[160, 600],
[120, 600],
[250, 250]
]
],
[
[768, 500],
[
[300, 250],
[250, 250]
]
],
[
[1, 1],
[
[300, 250],
[250, 250]
]
],
]
}
});
});

Dashed line animations in Mapbox GL JS

Is there a way I can do something like this in Mapbox with a LineString?
Here's my initial attempt at a dashed line animation using Map#setPaintProperty(xx, 'line-dasharray', yy) within a setInterval function.
Some rendering artifacts could be eliminated with some creativity and data preprocessing.
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title></title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.34.0/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.34.0/mapbox-gl.css' rel='stylesheet' />
<style>
body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>
<div id='map'></div>
<script>
mapboxgl.accessToken = 'pk.eyJ1IjoibHVjYXN3b2oiLCJhIjoiY2l5Nmg4cWU1MDA0ejMzcDJtNHJmZzJkcyJ9.WhcEdTYQH6sSw2pm0RSP9Q';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v9',
center: [-122.486052, 37.830348],
zoom: 15
});
map.on('load', function () {
map.addLayer({
"id": "route",
"type": "line",
"source": {
"type": "geojson",
"data": {
"type": "Feature",
"properties": {},
"geometry": {
"type": "LineString",
"coordinates": [
[-122.48369693756104, 37.83381888486939],
[-122.48348236083984, 37.83317489144141],
[-122.48339653015138, 37.83270036637107],
[-122.48356819152832, 37.832056363179625],
[-122.48404026031496, 37.83114119107971],
[-122.48404026031496, 37.83049717427869],
[-122.48348236083984, 37.829920943955045],
[-122.48356819152832, 37.82954808664175],
[-122.48507022857666, 37.82944639795659],
[-122.48610019683838, 37.82880236636284],
[-122.48695850372314, 37.82931081282506],
[-122.48700141906738, 37.83080223556934],
[-122.48751640319824, 37.83168351665737],
[-122.48803138732912, 37.832158048267786],
[-122.48888969421387, 37.83297152392784],
[-122.48987674713133, 37.83263257682617],
[-122.49043464660643, 37.832937629287755],
[-122.49125003814696, 37.832429207817725],
[-122.49163627624512, 37.832564787218985],
[-122.49223709106445, 37.83337825839438],
[-122.49378204345702, 37.83368330777276]
]
}
}
},
"layout": {
"line-join": "round",
"line-cap": "butt"
},
"paint": {
"line-color": "#888",
"line-width": 8
}
});
var dashLength = 1;
var gapLength = 3;
// We divide the animation up into 40 steps to make careful use of the finite space in
// LineAtlas
var steps = 40;
// A # of steps proportional to the dashLength are devoted to manipulating the dash
var dashSteps = steps * dashLength / (gapLength + dashLength);
// A # of steps proportional to the gapLength are devoted to manipulating the gap
var gapSteps = steps - dashSteps;
// The current step #
var step = 0;
setInterval(function() {
step = step + 1;
if (step >= steps) step = 0;
var t, a, b, c, d;
if (step < dashSteps) {
t = step / dashSteps;
a = (1 - t) * dashLength;
b = gapLength;
c = t * dashLength;
d = 0;
} else {
t = (step - dashSteps) / (gapSteps);
a = 0;
b = (1 - t) * gapLength;
c = dashLength;
d = t * gapLength;
}
map.setPaintProperty("route", "line-dasharray", [a, b, c, d]);
}, 25);
});
</script>
</body>
</html>
I prepared a simple animation in this jsfiddle:
https://jsfiddle.net/2mws8y3q/
var animationStep = 50;
var step = 0;
let dashArraySeq = [
[0, 4, 3],
[1, 4, 2],
[2, 4, 1],
[3, 4, 0],
[0, 1, 3, 3],
[0, 2, 3, 2],
[0, 3, 3, 1]
];
setInterval(() => {
step = (step + 1) % dashArraySeq.length;
map.setPaintProperty(layerId, 'line-dasharray', dashArraySeq[step]);
}, animationStep);
Mapbox has recently added an example, in its documentation, on how to do this animation :
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Add an ant path animation to a line</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<link href="https://api.mapbox.com/mapbox-gl-js/v2.12.0/mapbox-gl.css" rel="stylesheet">
<script src="https://api.mapbox.com/mapbox-gl-js/v2.12.0/mapbox-gl.js"></script>
<style>
body {
margin: 0;
padding: 0;
}
#map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
mapboxgl.accessToken = 'pk.eyJ1IjoibmFteXNoIiwiYSI6ImNsNm5qYmIwajAxZHIzaXFwOHpraWhsNHoifQ.x6kTRjPrVRWz9JVl_doDPQ';
const map = new mapboxgl.Map({
container: 'map', // container ID
// Choose from Mapbox's core styles, or make your own style with Mapbox Studio
style: 'mapbox://styles/mapbox/dark-v11', // style URL
center: [-73.9709, 40.6712], // starting position [lng, lat]
zoom: 15.773 // starting zoom
});
const geojson = {
'type': 'FeatureCollection',
'features': [{
'type': 'Feature',
'properties': {},
'geometry': {
'coordinates': [
[-73.97003, 40.67264],
[-73.96985, 40.67235],
[-73.96974, 40.67191],
[-73.96972, 40.67175],
[-73.96975, 40.67154],
[-73.96987, 40.67134],
[-73.97015, 40.67117],
[-73.97045, 40.67098],
[-73.97064, 40.67078],
[-73.97091, 40.67038],
[-73.97107, 40.67011],
[-73.97121, 40.66994],
[-73.97149, 40.66969],
[-73.97169, 40.66985],
[-73.97175, 40.66994],
[-73.97191, 40.66998],
[-73.97206, 40.66998],
[-73.97228, 40.67008]
],
'type': 'LineString'
}
}]
};
map.on('load', () => {
map.addSource('line', {
type: 'geojson',
data: geojson
});
// add a line layer without line-dasharray defined to fill the gaps in the dashed line
map.addLayer({
type: 'line',
source: 'line',
id: 'line-background',
paint: {
'line-color': 'yellow',
'line-width': 6,
'line-opacity': 0.4
}
});
// add a line layer with line-dasharray set to the first value in dashArraySequence
map.addLayer({
type: 'line',
source: 'line',
id: 'line-dashed',
paint: {
'line-color': 'yellow',
'line-width': 6,
'line-dasharray': [0, 4, 3]
}
});
// technique based on https://jsfiddle.net/2mws8y3q/
// an array of valid line-dasharray values, specifying the lengths of the alternating dashes and gaps that form the dash pattern
const dashArraySequence = [
[0, 4, 3],
[0.5, 4, 2.5],
[1, 4, 2],
[1.5, 4, 1.5],
[2, 4, 1],
[2.5, 4, 0.5],
[3, 4, 0],
[0, 0.5, 3, 3.5],
[0, 1, 3, 3],
[0, 1.5, 3, 2.5],
[0, 2, 3, 2],
[0, 2.5, 3, 1.5],
[0, 3, 3, 1]
];
let step = 0;
function animateDashArray(timestamp) {
// Update line-dasharray using the next value in dashArraySequence. The
// divisor in the expression `timestamp / 50` controls the animation speed.
const newStep = parseInt(
(timestamp / 50) % dashArraySequence.length);
if (newStep !== step) {
map.setPaintProperty('line-dashed', 'line-dasharray', dashArraySequence[step]);
step = newStep;
}
// Request the next frame of the animation.
requestAnimationFrame(animateDashArray);
}
// start the animation
animateDashArray(0);
});
</script>
</body>
</html>
Here the link of the documentation
Not directly. The closest I can think of is to set line-dasharray to something like 10,5,0, then a short time later, change it to 9,5,1, then 8,5,2 etc.
I haven't tried this, though. It's possible it will redraw in a weird way which doesn't look good.

Different colors for annotations in google charts

I have two types of annotations, one has links and other doesn't. I want to color them both in different colors. Is it possible?
type 1 is -
{
v: 'sample',
Link: 'some link
}
type 2 is -
{
v: 'sample',
}
I want to color type1 in some color and type2 in other, is it possible ?
you can style the annotations for the overall chart,
or for each series individually
see following working snippet,
the fontSize is set to 10 for all annotations
then the colors are changed for the individual series
google.charts.load('current', {
callback: drawStacked,
packages: ['corechart']
});
function drawStacked() {
var data = new google.visualization.arrayToDataTable([
['Month', 'A', {role: 'annotation'}, 'B', {role: 'annotation'}],
['Aug', 3754, '3,754', 2089, '2,089'],
['Sept', 900, '900', 200, '200'],
['Oct', 2000, '2,000', 4900, '4,900'],
['Nov', 1700, '1,700', 2200, '2,200'],
['Dec', 2400, '2,400', 2089, '2,089']
]);
var options = {
annotations: {
textStyle: {
fontSize: 10
}
},
series: {
0: {
annotations: {
stem: {
color: 'cyan',
length: 5
},
textStyle: {
color: 'cyan'
}
}
},
1: {
annotations: {
stem: {
color: 'magenta',
length: 10
},
textStyle: {
color: 'magenta'
}
}
}
}
};
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
EDIT
to have different colors for annotations in a single series,
need to change color manually when the 'ready' event fires
see following working snippet...
google.charts.load('current', {
callback: drawStacked,
packages: ['corechart']
});
function drawStacked() {
var data = new google.visualization.arrayToDataTable([
['Month', 'A', {role: 'annotation'}],
['Aug', 3754, '3,754'],
['Sept', {v: 900, p: {link: 'type A'}}, '900'],
['Oct', {v: 2000, p: {link: 'type B'}}, '2,000'],
['Nov', 1700, '1,700'],
['Dec', 2400, '2,400']
]);
var options = {
annotations: {
textStyle: {
color: '#000000',
fontSize: 10
}
}
};
var container = document.getElementById('chart_div');
var chart = new google.visualization.LineChart(container);
google.visualization.events.addListener(chart, 'ready', function () {
Array.prototype.forEach.call(container.getElementsByTagName('text'), function (text, index) {
for (var i = 0; i < data.getNumberOfRows(); i++) {
if ((text.getAttribute('text-anchor') === 'middle') && (text.innerHTML === data.getFormattedValue(i, 1))) {
switch (data.getProperty(i, 1, 'link')) {
case 'type A':
text.setAttribute('fill', 'magenta');
break;
case 'type B':
text.setAttribute('fill', 'cyan');
break;
}
}
}
});
});
chart.draw(data, options);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>