How to pass dynamic values to <amp-analytics> var - google-tag-manager

I need to pass the pagePath value dynamically into my amp-analytics tag's var value. Can you please advise how i can achieve this. For example, In the below code snippet , I need to replace the pagePath with different values based on the current page path.
<amp-analytics config="https://www.googletagmanager.com/amp.json?id=xxxxxxxxx&gtm.url=SOURCE_URL" data-credentials="include"
<script type="application/json">
{
"vars" : {
"pagePath" : { Needs to be passed dynamically }
}
}
</script>
<amp-analytics>

You would use variable substitution (https://github.com/ampproject/amphtml/blob/master/spec/amp-var-substitutions.md).
The variable you're interested in is "Canonical Path" (https://github.com/ampproject/amphtml/blob/master/spec/amp-var-substitutions.md#canonical-path).
You would insert the string ${canonicalPath} wherever you want it to be templated in before the analytics request is sent. For example:
<amp-analytics config="https://www.googletagmanager.com/amp.json?id=xxxxxxxxx&gtm.url=SOURCE_URL" data-credentials="include"
<script type="application/json">
{
"vars" : {
"pagePath" : "${canonicalPath}"
}
}
</script>
<amp-analytics>

Related

Pull URL parameters into a WordPress "Raw HTML" content element

I'm using the URL Params plugin to pull parameters into regular content using a short code. But I have to use a Raw HTML block to insert Typeform code into the page and I want to be able to pass a URL parameter into the Typeform code to track the source of the form submission.
I can't figure out how to do it. The form is working fine at: https://HelloExit.com/instant-valuation
But I want to be able to send people to https://HelloExit.com/instant-valuation/?source=XXXX and pull the XXXX into the Typeform code as the "source" value in the "data-url"
Here's what I tried:
<script>
function getUrlVars() {
var vars = {};
var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) {
vars[key] = value;
});
return vars;
}
var source = getUrlVars()["source"];
</script>
<div
class="typeform-widget"
data-url="https://xgenius.typeform.com/to/zZHPPk?source=<script>document.write(source)</script>"
data-transparency="100"
data-hide-headers=true
data-hide-footer=true
style="width: 100%; height: 500px;">
</div>
<!-- Typeform embed code -->
<script>(function() { var qs,js,q,s,d=document, gi=d.getElementById,
ce=d.createElement, gt=d.getElementsByTagName, id="typef_orm",
b="https://embed.typeform.com/"; if(!gi.call(d,id)) { js=ce.call(d,"script"); js.id=id;
js.src=b+"embed.js"; q=gt.call(d,"script")[0]; q.parentNode.insertBefore(js,q) } })()
</script><div style="font-family: Sans-Serif;font-size: 12px;color: #999;opacity: 0.5;padding-top: 5px;"> powered by Typeform</div>
Any assistance would be greatly appreciated!
You're close, but you'll need to use Javascript to alter the data-url attribute of your div.
// ...
var source = getUrlVars()["source"];
// concatenate the url with your source variable
var newUrl = `https://xgenius.typeform.com/to/zZHPPk?source=${source}`;
// get the element whose attributes you want to dynamically set
// https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector
var widgetElement = document.querySelector('.typeform-widget');
// set the source attribute
// https://developer.mozilla.org/en-US/docs/Web/API/Element/setAttribute
widgetElement.setAttribute('data-url', newUrl);
Test this carefully, as it might still end up with a race condition (that is, the Typeform embed code might start running before you've updated the data-url attribute that it references).

Loading Google Places Autocomplete Async Angular 2

I am trying to instantiate a Google Places Autocomplete input within an Angular 2 component. I use this code to do it:
loadGoogle() {
let autocomplete = new google.maps.places.Autocomplete((this.ref.nativeElement), { types: ['geocode'] });
let that = this
//add event listener to google autocomplete and capture address input
google.maps.event.addListener(autocomplete, 'place_changed', function() {
let place = autocomplete.getPlace();
that.place = place;
that.placesearch = jQuery('#pac-input').val();
});
autocomplete.addListener()
}
Normally, I believe, I would use the callback function provided by the Google API to ensure that it is loaded before this function runs, but I do not have access to it within a component's scope. I am able to load the autocomplete input 90% of the time, but on slower connections I sometimes error out with
google is not defined
Has anyone figured out how to ensure the Google API is loaded within a component before instantiating.
Not sure whether this will help, but I just use a simple script tag in my index.html to load Google API and I never get any error. I believe you do the same as well. I post my codes here, hope it helps.
Note: I use Webpack to load other scripts, except for Google Map API.
<html>
<head>
<base href="/">
<title>Let's Go Holiday</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Google Map -->
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=<your-key>&libraries=places"></script>
</head>
<body>
<my-app>Loading...</my-app>
</body>
</html>
And then in your component:
...
declare var google: any;
export class SearchBoxComponent implements OnInit {
ngOnInit() {
// Initialize the search box and autocomplete
let searchBox: any = document.getElementById('search-box');
let options = {
types: [
// return only geocoding results, rather than business results.
'geocode',
],
componentRestrictions: { country: 'my' }
};
var autocomplete = new google.maps.places.Autocomplete(searchBox, options);
// Add listener to the place changed event
autocomplete.addListener('place_changed', () => {
let place = autocomplete.getPlace();
let lat = place.geometry.location.lat();
let lng = place.geometry.location.lng();
let address = place.formatted_address;
this.placeChanged(lat, lng, address);
});
}
...
}
I used it the same way as explained above but as per google page speed i was getting this suggestion,
Remove render-blocking JavaScript:
http://maps.googleapis.com/…es=geometry,places&region=IN&language=en
So i changed my implementation,
<body>
<app-root></app-root>
<script src="http://maps.googleapis.com/maps/api/js?client=xxxxx2&libraries=geometry,places&region=IN&language=en" async></script>
</body>
/* Now in my component.ts */
triggerGoogleBasedFn(){
let _this = this;
let interval = setInterval(() => {
if(window['google']){
_this.getPlaces();
clearInterval(interval);
}
},300)
}
You can do one more thing, emit events once the value(google) is received,& trigger your google task
inside them.

How to dynamically create properties in polymer as needed

I have a use case where I have a component (like a database) that I would like to expose all the information as bindable properties. However, only a few of those properties will be need by any particular client who uses it. There could be 1000's of entries in the database. How can I figure out which ones are actually needed by the client.
For example:
Polymer('database,
{
observer : {
name : function(oldVal, newVal) { onDataChanged('name', newVal);},
addr : function(oldVal, newVal) { onDataChanged('addr', newVal);},
tel.main : function(oldVal, newVal) { onDataChanged('tel.main',
etc....
}
});
In this case I would like to dynamically create observe handlers only for the data bindings that are actually needed on the fly.
If you are willing to have your clients extend your component to specify the desired database fields then you can dynamically create observers only for the fields they specify.
Example
Component
<link rel="import" href="../../webcomponents/bower_components/polymer/polymer.html">
<polymer-element name=demo-dynamicproperties >
<template>
<h2>dynamic properties</h2>
See the console for changes
</template>
<script>
Polymer({
// Validate that it is an attribute that is allowed
// For the example we will allow anything starting with validitem
isValidAttribute: function(name) {
return (name.match('^validitem'));
},
// Get attributes
created: function() {
for (name in this.publish) {
console.log("Trying: "+name);
// Verify that it is one of the dynamic attributes
if (this.isValidAttribute(name)) {
console.log("Accepting: "+name);
this[name]="Pull from DB";
// References:
// https://www.polymer-project.org/0.5/docs/polymer/node_bind.html
// https://github.com/Polymer/NodeBind/blob/master/tests/tests.js
// https://github.com/polymer/observe-js
var observer = new PathObserver(this,name);
observer.open(makeHandler(this,name));
}
}
/************* TEST **********************************/
// Verify that dynamic updates worked by updating
this.job('update_validitem1', function() {
this.validitem1="Updated after 10 seconds";
}, 10000);
/************ End Test ******************************/
}
});
// Ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
function makeHandler(element, property) {
function handler(newval,oldval) {
console.log("element" + element,"property:" + property,"from:"+oldval,"to:"+newval);
}
return handler;
}
</script>
</polymer-element>
Usage
<!DOCTYPE HTML>
<html lang="en">
<head>
<script src="../../webcomponents/bower_components/webcomponentsjs/webcomponents.min.js"></script>
<link rel="import" href="../../webcomponents/bower_components/polymer/polymer.html">
<link rel="import" href="demo-dynamicproperties.html">
<title>demo-dynamicproperties test page</title>
</head>
<body>
<polymer-element name=demo-usedb extends="demo-dynamicproperties" attributes="validitem1 validitem2 invaliditem" noscript>
</polymer-element>
<h1>Demo</h1>
<template is="auto-binding">
<h2>Dynamic tag</h2>
<demo-usedb validitem1="{{item1choice2}}" item2="setthis"></demo-usedb>
<h2>Input</h2>
<input type="text" value="{{item1choice2}}">
<h3>Produces</h3>
{{item1choice2}}
</template>
</body>
</html>
It looks like the answer to the questions is that it cannot be done. There does not appear to be any hooks or events that a component can use to get notified when properties are bound (or attempted to be bound) to it. I filed a bug/enhancement request here
https://github.com/Polymer/polymer/issues/1303
to request that this feature be supported in the future.

How to set an API key when using Google's script loader?

I registered my project and generated a browser key at https://code.google.com/apis/console/.
Now how do I use that key when using the Google Script Loader?
I've been doing this, which works (with or without the key parameter), but even after several weeks the API console shows no requests:
<script src=//www.google.com/jsapi?key=my_key"></script>
<script>
google.load('maps', '3.10', { other_params : 'libraries=places&sensor=false', callback : ... })
</script>
The key is useless for the jsapi, you must append it to other_params:
<script>
google.load('maps', '3', {
other_params: 'key=my_key',
callback: function(){}
});
</script>
When using charts/loader you have to do something like this:
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load('current', {
'packages':['geochart'],
// Note: you will need to get a mapsApiKey for your project.
// See: https://developers.google.com/chart/interactive/docs/basic_load_libs#load-settings
'mapsApiKey': 'AIzaSyD-9tSrke72PouQMnMX-a7eZSW0jkFMBWY'
});
google.charts.setOnLoadCallback(drawRegionsMap);
...
</script>
Note the mapsApiKey property.
As described in https://developers.google.com/chart/interactive/docs/gallery/geochart

How to get element content by id from HTML object by JavaScript ( JQuery )

i write the following code to access page "JQueryPage.aspx" and get data from it using jQuery
<script type="text/javascript">
$.get
(
"JQueryPage.aspx",
function(data) {
alert("Data Loaded: " + data);
}
);
</script>
"JQueryPage.aspx" is just a page that contain DIV called 'resultsDIV' that contain the data that i want to return
the above code return data variable that contain "JQueryPage.aspx" html and i want to get DIV content from it ..
i have 2 questions:
1- how can i extract DIV content from data object
2- is this way is th best to get that data ?
Try using something like this:
<script type="text/javascript">
$.get
(
"JQueryPage.aspx", function(html) {
var page = $(html);
var div = $('#div1', page);
}
);
</script>
you can also look into the $.load function
Jsut wrap the data in a call to jquery and you can use it like you would normally:
$.get
(
"JQueryPage.aspx",
function(data) {
var dataDom = $(data);
$(someSelector, dataDom).each(function(){
alert($(this).html());
});
}
);
If the html markup of JQueryPage.aspx is valid xml, you can use dom parser to get the required div.
It depends - if all you want is to add the retrieved html to the existing DOM using a call to document.appendChild, yes. But if you need to parse and read values from the retrieved data, no, this is not. Pass data as a JSON string or xml.

Resources