Google remarketing/conversion currency code errors - tracking

I am implementing a simple Google remarketing/conversion script to a client site... But having issues with the setting of the currency code for some reason.
I get 2 errors using the tag assistant which are:
Conversion Value should be prefixed with standard currency.
Non-standard implementation
Code
<script type="text/javascript">
/* <![CDATA[ */
var google_conversion_id = ABC123;
var google_conversion_language = "en";
var google_conversion_format = "3";
var google_conversion_color = "ffffff";
var google_conversion_label = "ABC123";
var google_remarketing_only = false;
var google_conversion_value = 1.00;
var google_conversion_currency = "GBP";
/* ]]> */
</script>
<script type="text/javascript"
src="//www.googleadservices.com/pagead/conversion.js">
</script>
<noscript>
<div style="display:inline;">
<img height="1" width="1" style="border-style:none;" alt=""
src="//www.googleadservices.com/pagead/conversion/ABC123/?value=1&currency_code=GBP&label=ABC123&guid=ON&script=0"/>
Anyone know what the issue is? Google help online seems to skip this issue!

Related

UniqueValueRenderer with graphicsLayer

graphicsLayer has a method: setRenderer(renderer)
How can I set certain graphic elements of graphicsLayer using UniqueValueRenderer?
Did not find anything like this on Google therefore opened this issue here.
Any example available?
Using: js arcgis 3.23
Is this actually supported in js arcgis version 3.x?
As far as I know it is not supported in js arcgis version 4.x
Did not find a solution on the web so I had no choice but to investigate it on my own.
The main question was: how to talk to each graphic element that belongs to a certain graphicsLayer using UniqueValueRenderer.
Could not figure out from the ESRI js arcgis 3.23 API and examples what could be the right interface and syntax to use.
After experimenting a lot with the code came to the following conclusions:
Symbols defined at the Graphic layer always override symbols
defined in a renderer. Therefore I instanced each Graphic using no
Symbol.
In order to communicate with each Graphic separately UniqueValueRenderer needs to find some attribute on each Graphic therefore I added an attribute to each Graphic.
Now I attempted to use the Graphic attribute name in the UniqueValueRenderer while using Graphic attribute value to let UniqueValueRenderer select custom symbol for each Graphic.
The syntax for UniqueValueRenderer integration with graphicsLayer was not clear from the available documentation and ESRI examples but I experimented with various options and possibilities intuitively and I managed to make it work!
You can see the solution in the attached code snippet.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
<title>Renderer</title>
<style>
html,
body,
#map {
height: 100%;
padding: 0;
margin: 0;
}
</style>
<link rel="stylesheet" href="https://js.arcgis.com/3.23/esri/css/esri.css">
<link rel="stylesheet" href="https://js.arcgis.com/3.23/dijit/themes/tundra/tundra.css">
<script src="https://js.arcgis.com/3.23/"></script>
<script>
var map;
require([
"esri/map",
"esri/renderers/Renderer",
"esri/renderers/SimpleRenderer",
"esri/renderers/UniqueValueRenderer",
"esri/layers/ArcGISTiledMapServiceLayer",
"esri/graphic",
"esri/layers/GraphicsLayer",
"esri/geometry/Point",
"esri/Color",
"esri/SpatialReference",
"esri/symbols/SimpleLineSymbol",
"esri/symbols/SimpleMarkerSymbol",
"esri/symbols/PictureMarkerSymbol",
"esri/InfoTemplate",
"dojo/domReady!"
],
function(Map, Renderer, SimpleRenderer, UniqueValueRenderer, ArcGISTiledMapServiceLayer, Graphic, GraphicsLayer, Point, Color, SpatialReference, SimpleLineSymbol, SimpleMarkerSymbol, PictureMarkerSymbol, InfoTemplate) {
map = new Map("map", {
basemap: "topo",
center: [34.9891877, 31.712805039],
zoom: 13,
logo: false
});
var locationGraphicsLayer = new GraphicsLayer();
var symbol1 = new SimpleMarkerSymbol().
setOffset(0, 0).
setColor([0, 255, 55, 0.33]).
setSize(40).
setStyle(SimpleMarkerSymbol.STYLE_PATH).
setPath("M16,3.5c-4.142,0-7.5,3.358-7.5,7.5c0,4.143,7.5,18.121,7.5,18.121S23.5,15.143,23.5,11C23.5,6.858,20.143,3.5,16,3.5z M16,14.584c-1.979,0-3.584-1.604-3.584-3.584S14.021,7.416,16,7.416S19.584,9.021,19.584,11S17.979,14.584,16,14.584z");
var symbol2 = new SimpleMarkerSymbol().
setOffset(0, 0).
setColor([55, 0, 255, 0.33]).
setSize(40).
setStyle(SimpleMarkerSymbol.STYLE_PATH).
setPath("M16,3.5c-4.142,0-7.5,3.358-7.5,7.5c0,4.143,7.5,18.121,7.5,18.121S23.5,15.143,23.5,11C23.5,6.858,20.143,3.5,16,3.5z M16,14.584c-1.979,0-3.584-1.604-3.584-3.584S14.021,7.416,16,7.416S19.584,9.021,19.584,11S17.979,14.584,16,14.584z");
var symbol3 = new SimpleMarkerSymbol().
setOffset(0, 0).
setColor([255, 0, 55, 0.33]).
setSize(40).
setStyle(SimpleMarkerSymbol.STYLE_PATH).
setPath("M16,3.5c-4.142,0-7.5,3.358-7.5,7.5c0,4.143,7.5,18.121,7.5,18.121S23.5,15.143,23.5,11C23.5,6.858,20.143,3.5,16,3.5z M16,14.584c-1.979,0-3.584-1.604-3.584-3.584S14.021,7.416,16,7.416S19.584,9.021,19.584,11S17.979,14.584,16,14.584z");
var attr1 = {
"MY_VALUE": 1
};
var attr2 = {
"MY_VALUE": 2
};
var attr3 = {
"MY_VALUE": 3
};
var attr4 = {
"MY_VALUE": 4
};
var attr5 = {
"MY_VALUE": 5
};
var attr6 = {
"MY_VALUE": 6
};
var attr7 = {
"MY_VALUE": 7
};
var attr8 = {
"MY_VALUE": 8
};
var point1 = new Point(34.9891417, 31.712785039);
var point2 = new Point(34.9863217, 31.712911039);
var point3 = new Point(34.95059216533203, 31.740442520689456);
var point4 = new Point(34.958138448443606, 31.719220882963626);
var point5 = new Point(34.993487748107846, 31.728375175600405);
var point6 = new Point(34.990054520568776, 31.73875923932111);
var point7 = new Point(34.978845102038576, 31.732417351316897);
var point8 = new Point(34.974815102038576, 31.735412351316897);
var graphic1 = new Graphic(point1);
var graphic2 = new Graphic(point2);
var graphic3 = new Graphic(point3);
var graphic4 = new Graphic(point4);
var graphic5 = new Graphic(point5);
var graphic6 = new Graphic(point6);
var graphic7 = new Graphic(point7);
var graphic8 = new Graphic(point8);
graphic1.setAttributes(attr1);
graphic2.setAttributes(attr2);
graphic3.setAttributes(attr3);
graphic4.setAttributes(attr4);
graphic5.setAttributes(attr5);
graphic6.setAttributes(attr6);
graphic7.setAttributes(attr7);
graphic8.setAttributes(attr8);
locationGraphicsLayer.add(graphic1);
locationGraphicsLayer.add(graphic2);
locationGraphicsLayer.add(graphic3);
locationGraphicsLayer.add(graphic4);
locationGraphicsLayer.add(graphic5);
locationGraphicsLayer.add(graphic6);
locationGraphicsLayer.add(graphic7);
locationGraphicsLayer.add(graphic8);
renderer = new UniqueValueRenderer(symbol2, "MY_VALUE");
renderer.addValue({
value: "6",
symbol: symbol1
});
renderer.addValue({
value: "3",
symbol: symbol3
});
locationGraphicsLayer.setRenderer(renderer);
map.addLayer(locationGraphicsLayer);
});
</script>
<title></title>
</head>
<body class="tundra">
<div id="map"></div>
</body>
</html>

Speech Synthesis API offline languages

Is it possible to use the speech synthesis API offline? If so, can I use multiple languages or just the default language?
I have tried this code and it works online, but it does not work offline. How can I make it work online?
<html>
<head>
<title>Index</title>
</head>
<p id = "1"></p>
<script src="../js/jquery-3.2.1.js"></script>
<script type="text/javascript">
$(document).ready(function() {
document.addEventListener("keydown", function (e) {
var audio = document.getElementById("myAudio");
if (e.keyCode ===49 || e.keyCode ===97) { //1 is pressed
mySpeech();
}
});
})
function mySpeech(){
var msg = new SpeechSynthesisUtterance();
var voices = window.speechSynthesis.getVoices();
msg.voiceURI = 'native';
msg.lang = 'it-IT'
//msg.voice = voices[$('#voices').val()];
msg.rate = 1; // 0 to 1
msg.pitch = 1; // 0 to 2
msg.text = "hello world";
speechSynthesis.speak(msg);
}
</script>
</body>
The only languages that will work offline are the browser's local voices.

Google AdWord Example to haml

Given this example: https://support.google.com/adwords/answer/3207306?hl=en&rd=1
How would I convert the code listed under the "Troubleshooting your code snippet" section to haml?
The closest I've come is:
%script{:type=>"text/javascript"}
:cdata
var google_conversion_id = 123456789;
var google_conversion_language = "en";
var google_conversion_format = "3";
var google_conversion_color = "ffffff";
var google_conversion_label = "AAAAAAAAAAAAAAAAAAA";
var google_conversion_value = 0;
var google_remarketing_only = false;
%script{:type => "text/javascript", :src => "//www.googleadservices.com/pagead/conversion.js"}
%noscript
%div{:style => "display:inline;"}
%img{:height => "1", :width => "1", :style => "border-style:none;", :alt => "", :src => "//www.googleadservices.com/pagead/conversion/123456789/?value=0&label= AAAAAAAAAAAAAAAAAAA&guid=ON&script=0".html_safe}
The problem with above is the :cdata tag produces:
<script type="text/javascript">
<![CDATA[
var google_conversion_id = 123456789;
var google_conversion_language = "en";
var google_conversion_format = "3";
var google_conversion_color = "ffffff";
var google_conversion_label = "AAAAAAAAAAAAAAAAAAA";
var google_conversion_value = 0;
var google_remarketing_only = false;
]]>
</script>
And not:
<script type="text/javascript">
/* <![CDATA[ */
var google_conversion_id = 123456789;
var google_conversion_language = "en";
var google_conversion_format = "2";
var google_conversion_color = "ffffff";
var google_conversion_label = "AAAAAAAAAAAAAAAAAAA";
var google_conversion_value = 0;
/* ]]> */
</script>
Is there a way to explicitly declare the CDATA tag? Or is Google not that picky about it?
You can escape / in haml with a \ at the beginning of the line. I had the same issue and the following worked for me to include the google adwords conversion tracking code in our site:
<script type="text/javascript">
\/* <![CDATA[ */
var google_conversion_id = 123456789;
var google_conversion_language = "en";
var google_conversion_format = "2";
var google_conversion_color = "ffffff";
var google_conversion_label = "AAAAAAAAAAAAAAAAAAA";
var google_conversion_value = 0;
\/* ]]> */
</script>
which after haml processing turns into:
<script type="text/javascript">
/* <![CDATA[ */
var google_conversion_id = 123456789;
var google_conversion_language = "en";
var google_conversion_format = "2";
var google_conversion_color = "ffffff";
var google_conversion_label = "AAAAAAAAAAAAAAAAAAA";
var google_conversion_value = 0;
/* ]]> */
</script>
After haggling with many variations of the above, I finally "cheated" and just used the :plain tag to get it exactly the way I wanted. The code below exactly replicates what was on the Google Analytics example page, and the Google Tag Assistant plugin for Chrome confirms that it's coming through properly. Note: I also had to change the googleadservices link to HTTPS so that it would match the rest of my page (that was causing other problems that were hard to chase down, and Tag Assistant helped to sort it out).
This should do it for you:
%script{:type=>"text/javascript"}
:plain
/* <![CDATA[ */
var google_conversion_id = 123456789;
var google_conversion_language = "en";
var google_conversion_format = "3";
var google_conversion_color = "ffffff";
var google_conversion_label = "AAAAAAAAAAAAAAAAAAA";
var google_conversion_value = 0;
var google_remarketing_only = false;
/* ]]> */
%script{:type => "text/javascript", :src => "https://www.googleadservices.com/pagead/conversion.js"}
The CDATA tag isn’t really needed in HTML. The intention is that it allows the use of things like literal < in the javascript without having to escape them. CDATA sections are sometimes used with XHTML, but even then XHTML is usually treated as HTML by the browser.
With Haml, you could use the :javascript filter for blocks like this. That will add the CDATA section if your document format is XHTML, and leave it out otherwise. It will also omit the type attribute if the format is HTML5, since the default is text/javascript in that case.
So:
:javascript
var google_conversion_id = 123456789;
// etc ...
Will produce this when the format is HTML5 (the default)
<script>
var google_conversion_id = 123456789;
// etc ...
</script>
and this when the format is XHTML:
<script type='text/javascript'>
//<![CDATA[
var google_conversion_id = 123456789;
// etc ...
//]]>
</script>
Note that this uses // comments for the CDATA markers rather than /* ... */ that the Google page suggests, but this shouldn’t matter.

Multiple Bing Map Pushpins from SQL not showing in Firefox & Chrome but do in IE

I'm displaying a Bing Map (v7) in my Webmatrix2 website with a series of pushpins & infoboxes drawn from a SQL Express database using a JSON enquiry.
While the maps appears in all 3 browsers I'm testing (IE, FF & Chrome) the pushpins are sometimes not showing in FF & Chrome, particularly if I refresh with Cntrl+F5
This is my first JSON and Bing Maps app so expect there's a few mistakes.
Any suggestions on how to improve the code and get display consistency?
#{
Layout = "~/_MapLayout.cshtml";
}
<script type="text/javascript" src="~/Scripts/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0"></script>
<link rel="StyleSheet" href="infoboxStyles.css" type="text/css">
<script type="text/javascript">
var map = null;
var pinLayer, pinInfobox;
var mouseover;
var pushpinFrameHTML = '<div class="infobox"><a class="infobox_close" href="javascript:closeInfobox()"><img src="/Images/close2.jpg" /></a><div class="infobox_content">{content}</div></div><div class="infobox_pointer"><img src="images/pointer_shadow.png"></div>';
var pinLayer = new Microsoft.Maps.EntityCollection();
var infoboxLayer = new Microsoft.Maps.EntityCollection();
function getMap() {
map = new Microsoft.Maps.Map(document.getElementById('map'), {
credentials: "my-key",
zoom: 4,
center: new Microsoft.Maps.Location(-25, 135),
mapTypeId: Microsoft.Maps.MapTypeId.road
});
pinInfobox = new Microsoft.Maps.Infobox(new Microsoft.Maps.Location(0, 0), { visible: false });
AddData();
}
$(function AddData() {
$.getJSON('/ListSchools', function (data) {
var schools = data;
$.each(schools, function (index, school) {
for (var i = 0; i < schools.length; i++) {
var pinLocation = new Microsoft.Maps.Location(school.SchoolLat, school.SchoolLon);
var NewPin = new Microsoft.Maps.Pushpin(pinLocation);
NewPin.title = school.SchoolName;
NewPin.description = "-- Learn More --";
pinLayer.push(NewPin); //add pushpin to pinLayer
Microsoft.Maps.Events.addHandler(NewPin, 'mouseover', displayInfobox);
}
});
infoboxLayer.push(pinInfobox);
map.entities.push(pinLayer);
map.entities.push(infoboxLayer);
});
})
function displayInfobox(e) {
if (e.targetType == "pushpin") {
var pin = e.target;
var html = "<span class='infobox_title'>" + pin.title + "</span><br/>" + pin.description;
pinInfobox.setOptions({
visible: true,
offset: new Microsoft.Maps.Point(-33, 20),
htmlContent: pushpinFrameHTML.replace('{content}', html)
});
//set location of infobox
pinInfobox.setLocation(pin.getLocation());
}
}
function closeInfobox() {
pinInfobox.setOptions({ visible: false });
}
function getCurrentLocation() {
var geoLocationProvider = new Microsoft.Maps.GeoLocationProvider(map);
geoLocationProvider.getCurrentPosition();
}
</script>
<body onload="getMap();">
<div id="map" style="position:relative; width:800px; height:600px;"></div>
<div>
<input type="button" value="Find Nearest Schools" onclick="getCurrentLocation();" />
</div>
</body>
The JSON file is simply
#{
var db = Database.Open("StarterSite");
var sql = #"SELECT * FROM Schools WHERE SchoolLon != ' ' AND SchoolLon != 'null' ";
var data = db.Query(sql);
Json.Write(data, Response.Output);
}
Add your pinLayer, infobox, and infoboxLayer before calling the AddData function and see if that makes a difference. Also verify that school.SchoolLat and school.SchoolLon are numbers and not a string version of a number. If they are a string, then use parseFloat to turn them into a number. Other than that everything looks fine.

Getting storageVolume to work in JavaScript

In his blog post, Christian Cantrell shows how to use STORAGE_VOLUME_MOUNT in ActionScript.
He has written a Flex app called FileTile.
I would like to see a JavaScript alert box that says “You have inserted “ + e.storageVolume.name, and “You have removed a storage volume”.
<html>
<head>
<title>New Adobe AIR Project</title>
<script type="text/javascript" src="lib/air/AIRAliases.js"></script>
<script type="text/javascript" src="lib/air/AIRIntrospector.js"></script>
<script type="text/javascript" src="lib/jQuery/jquery-1.4.3.min.js"></script>
<script type="text/javascript">
var msg = '<h1>Please insert your SwatchDog (SD) card.</h1>';
function trace() {
var message = 'Hello Max';
air.Introspector.Console.log(message);
}
function readFile(v) {
var myFile = air.File.desktopDirectory.resolvePath("MyFile.txt");
var fileStream = new air.FileStream();
fileStream.open(myFile, air.FileMode.READ);
$('#app').append('<p>' + fileStream.readUTFBytes(fileStream.bytesAvailable) + '</p>');
fileStream.close();
}
function onVolumeMount(e) {
$('#app').html('<h1>Thank you</h1><p>I can see you have multiple devices:</p>');
var volumes = air.StorageVolumeInfo.storageVolumeInfo.getStorageVolumes();
for (var i = 0; i < volumes.length; i++) {
$('#app').append(volumes[i].rootDirectory.nativePath);
}
if (e.storageVolume.isRemovable) {
if (e.storageVolume.name == 'SWATCHDOG') {
$('#app').append('<p>And SwatchDog is drive: ' + e.storageVolume.rootDirectory.nativePath + '</p>');
readFile(e.storageVolume)
} else {
$('#app').append('<p>But the one you just plugged in is not SwatchDog.</p>');
}
}
}
function onVolumeUnmount(e) {
$('#app').html('<h1>Goodbye!</h1>' + msg);
}
jQuery(function($){
var PluggedIn = false;
var volumes = air.StorageVolumeInfo.storageVolumeInfo.getStorageVolumes();
for (var i = 0; i < volumes.length; i++) {
if (volumes[i].isRemovable) {
PluggedIn = true;
if (volumes[i].name == 'SWATCHDOG') {
$('#app').append('I see you already have SwatchDog plugged in!');
readFile(volumes[i])
} else {
$('#app').append('What you have plugged in is not SwatchDog.');
}
}
}
if (!PluggedIn){
$('#app').append(msg);
}
air.StorageVolumeInfo.storageVolumeInfo.addEventListener(air.StorageVolumeChangeEvent.STORAGE_VOLUME_MOUNT, onVolumeMount);
air.StorageVolumeInfo.storageVolumeInfo.addEventListener(air.StorageVolumeChangeEvent.STORAGE_VOLUME_UNMOUNT, onVolumeUnmount);
})
</script>
</head>
<body>
<div id="app">
</div>
<button onclick="trace();">Say Hello Max!</button>
</body>
</html>