I am trying to assign content grouping variable to my Google Analytics code in my AMP markup.
My AMP analytics code:
<amp-analytics type="googleanalytics" id="analyticsgoogle1">
<script type="application/json">
{
"vars": {
"account": "UA-XXXXXXXX-X"
},
"triggers": {
"trackPageview": {
"on": "visible",
"request": "pageview"
}
}
}
</script>
</amp-analytics>
My regular Google analytics code:
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-XXXXXXXX-X', 'auto');
ga('set', 'contentGroup1', 'My Category');
ga('set', 'contentGroup2', 'My Author Type');
ga('set', 'contentGroup3', 'My Author Name');
ga('send', 'pageview');
</script>
I know it isn't listed in the documentation, but I am looking for something like this to possibly work so that my AMP pages can be tracked the same way as my regular pages.
Possible AMP Project Google Analytics Code with Content Grouping:
<amp-analytics type="googleanalytics" id="analyticsgoogle1">
<script type="application/json">
{
"vars": {
"account": "UA-XXXXXXXX-X"
},
"triggers": {
"trackPageview": {
"on": "visible",
"request": "pageview"
"vars": {
"contentGroup1": "My Category",
"contentGroup2": "My Author Type",
"contentGroup3": "My Author Name"
}
}
}
}
</script></amp-analytics>
I do not see the content grouping variables when to look at the documentation for Variables supported in amp-analytics:
https://github.com/ampproject/amphtml/blob/master/extensions/amp-analytics/analytics-vars.md
Here is the documentation on amp-analytics code: https://developers.google.com/analytics/devguides/collection/amp-analytics/
I made a working solution. Actually it's quite simple. Same notes for the code below.
cg1 = contentGroup1, cg2 = contentGroup2
Details about Measurement protocol
IMPORTANT NOTE: Use throttling in your browser if you want to see your real requests to GA. In other case you will see redirect chain from GA instead of your real request. Very annoying.
<amp-analytics type="googleanalytics" id="ga1">
<script type="application/json">
{
"extraUrlParams" : {
"cd4": "AMP"
<?php if($this->tracking_group_config['group'] === 'contentGroup1'):?>
,"cg1": "<?=$this->tracking_group_config['type']?>"
<?php elseif($this->tracking_group_config['group'] === 'contentGroup2'): ?>
,"cg2": "<?=$this->tracking_group_config['type']?>"
<?php endif; ?>
},
"vars": {
"account": "[Your GA account ID here]"
},
"triggers": {
"pageviewCustom": {
"on": "visible",
"request": "pageview"
}
}
}
</script>
</amp-analytics>
Using gtag, this code will work:
<amp-analytics type="gtag" data-credentials="include">
<script type="application/json">
{
"vars": {
"gtag_id": "UA-XXXXXXXX-YY",
"config": {
"UA-XXXXXXXX-YY": {
"groups": "default",
"content_group1": "my value",
"content_group3": "my other value"
}
}
}
}
</script>
</amp-analytics>
Also you can debug it by using Chrome Dev Tools under Network tab:
Hope it helps!
Related
I would like to know, if there is any way to create a calendar with FullCalendar in such format:
I formed resusers in the form of dates. But I see events only in one day. It is possible to correct the events. But maybe there is a way to display all the days in this format.
Thank you in advance!
Temporarily, I solved the problem this way:
<div class="panel-body">
<div id="calendar"></div>
</div>
#section Styles {
<link href="~/lib/fullcalendar/dist/fullcalendar.min.css" rel="stylesheet" />
<link href="~/lib/fullcalendar-scheduler/dist/scheduler.min.css" rel="stylesheet" />
}
#section Scripts {
<script src="~/lib/moment/moment.js"></script>
<script src="~/lib/fullcalendar/dist/fullcalendar.min.js"></script>
<script src="~/lib/fullcalendar/dist/locale/ru.js"></script>
<script src="~/lib/fullcalendar-scheduler/dist/scheduler.min.js"></script>
<script>
$(function () {
$('#calendar').fullCalendar({
defaultView: 'timelineDay',
slotDuration: '00:30',
slotWidth: 5,
height: 'auto',
eventOverlap: false,
nowIndicator: true,
businessHours: true,
defaultDate: "#DateTime.Now.ToString("yyyy-MM")-01",
titleFormat: 'MMMM YYYY',
header: {
left: 'myPrevButton,myNextButton',
center: 'title',
right: ''
},
customButtons: {
myNextButton: {
//text: 'Next',
icon: 'right-single-arrow',
click: function () {
$('#calendar').fullCalendar('incrementDate', {
months: 1,
});
$('#calendar').fullCalendar('refetchResources');
}
},
myPrevButton: {
//text: 'Prev',
icon: 'left-single-arrow',
click: function () {
$('#calendar').fullCalendar('incrementDate', {
months: -1,
});
$('#calendar').fullCalendar('refetchResources');
}
}
},
events: "/api/Sheduling/eventpersonal/#Model.Id",
refetchResourcesOnNavigate: true,
resources: '/api/Sheduling/1'
});
});
</script>
}
This solution works for me. But it requires superfluous operations.
This solution works for me. But it requires superfluous operations. I receive a schedule for one employee in the form of:
Resources:
[{"id":1,"title":"1/8"},{"id":2,"title":"2/8"},{"id":3,"title":"3/8"},{"id":4,"title":"4/8"},{"id":5,"title":"5/8"},{"id":6,"title":"6/8"}, ....
Events (where all start in the end date is the 1st day of the month, and the resourceId is the date of the month):
[{"color":"#006633","id":1,"resourceId":1,"start":"2018-08-01T10:05:00","end":"2018-08-01T10:09:50"},{"color":"#006633","id":1,"resourceId":1,"start":"2018-08-01T10:35:00","end":"2018-08-01T10:39:50"},{"color":"#006633","id":1,"resourceId":1,"start":"2018-08-01T11:05:00","end":"2018-08-01T11:09:50"},{"color":"#006633","id":1,"resourceId":1,"start":"2018-08-01T11:35:00","end":"2018-08-01T11:39:50"},{"color":"#006633","id":1,"resourceId":1,"start":"2018-08-01T12:05:00","end":"2018-08-01T12:09:50"},{"color":"#006633","id":1,"resourceId":1,"start":"2018-08-01T12:35:00","end":"2018-08-01T12:39:50"},{"color":"#006633","id":1,"resourceId":1,"start":"2018-08-01T13:05:00","end":"2018-08-01T13:09:50"},{"color":"#006633","id":1,"resourceId":1,"start":"2018-08-01T13:35:00","end":"2018-08-01T13:39:50"},{"color":"#006633","id":1,"resourceId":1,"start":"2018-08-01T14:05:00","end":"2018-08-01T14:09:50"},{"color":"#006633","id":1,"resourceId":1,"start":"2018-08-01T14:35:00","end":"2018-08-01T14:39:50"}, ....
I'm (trying) to implement Enhanced Analytics on an aspx/mvc website.
First, I set up a UA Tag triggering off the custom event "checkout":
Tag Type: Universal Analytics
Track Type: Event
Event Action: Checkout
Enable Enhanced Ecommerce Features: true
Use Data Layer: true
Then, I created a Custom HTML tag to push the checkout event to the Data Layer; firing off of Window Load of the checkout URL. the custom HTML is:
<script type='text/javascript'>
(function() {
dataLayer.push({
'event': 'checkout',
'ecommerce': {
'checkout': {
'actionField': { 'step': '1' },
'products': [{
'name': 'product1',
'id': '123456',
'price': '500',
'dimension2': 'Acccepted',
'dimension5': '12345'
}]
}
}
});
})
</script>
GTM preview shows the custom html tag firing but the associated UA Event tag does not fire.
Help?
You have a small mistake in your JS. You forgot to call defined function (pay attention at () at the end):
(function() {
dataLayer.push({
'event': 'checkout',
'ecommerce': {
'checkout': {
'actionField': { 'step': '1' },
'products': [{
'name': 'product1',
'id': '123456',
'price': '500',
'dimension2': 'Acccepted',
'dimension5': '12345'
}]
}
}
});
}())
I'm a very experienced C++ and Python programmer but new to the Google Maps API and pretty new to JavaScript. I'm trying to get a simple example working to display part of the path of a train, using the LineString GeoJSON object type, constructed inline. I've tried moving my map dictionary inside a GeoJSON object constructor, modifying the style definition and moving it up and down, etc. But the best I can do is an empty map, I think centered where my overlay should be appearing. Trying this using the current Chrome and jsbin.com in Windows, and Firefox in Centos. Many thanks for any help!
<!DOCTYPE html>
<html>
<head>
<title>Simple Map with StringLine</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<style>
html, body {
height: 100%;
margin: 0;
padding: 0;
}
#map {
height: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lng: -73.945259, lat: 41.133659},
zoom: 15
});
map.data.addGeoJson({
"type": "LineString",
"coordinates": [
[-73.945259094199997, 41.133659362800003],
[-73.945625305199997, 41.178726196299998],
[-73.978820800799994, 41.2158432007],
[-73.978256225600006, 41.249233245799999],
[-73.954887390099998, 41.288650512700002],
[-73.986076354999994, 41.322223663300001],
[-73.965789794900004, 41.352313995400003],
[-73.957283020000006, 41.382507324199999],
[-73.968963622999993, 41.410072326700003],
[-73.989562988299994, 41.439929962199997],
[-74.015953064000001, 41.464096069299998],
[-74.006843566900002, 41.499134063699998],
[-73.999168396000002, 41.5377388],
[-73.9613571167, 41.581764221199997],
[-73.956344604500003, 41.627635955800002],
[-73.948852539100002, 41.678043365500002],
[-73.946556091299996, 41.729282379200001],
[-73.9569854736, 41.7779464722],
[-73.9701004028, 41.828430175800001],
[-73.985443115199999, 41.881973266599999],
[-74.006584167499994, 41.924633026099997],
[-73.991699218799994, 41.975730896000002],
[-73.982696533199999, 42.033111572300001],
[-73.962783813499996, 42.085037231400001]
]
});
map.data.setStyle({
strokeColor: "#FF0000",
strokeOpacity: 0.8,
strokeWeight: 10,
});
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?callback=initMap"
async defer></script>
</body>
</html>
Your GeoJson is not valid for the .addGeoJson method, it throws a javascript error: `Uncaught InvalidValueError: not a Feature or FeatureCollection
(from the javascript console. See Troubleshooting in the documentation)
fiddle
If I make your GeoJson a FeatureCollection it works for me:
updated fiddle
code snippet:
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {
lng: -73.945259,
lat: 41.133659
},
zoom: 15
});
map.data.addGeoJson({
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [102.0, 0.5]
},
"properties": {
"prop0": "value0"
}
}, {
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[-73.945259094199997, 41.133659362800003],
[-73.945625305199997, 41.178726196299998],
[-73.978820800799994, 41.2158432007],
[-73.978256225600006, 41.249233245799999],
[-73.954887390099998, 41.288650512700002],
[-73.986076354999994, 41.322223663300001],
[-73.965789794900004, 41.352313995400003],
[-73.957283020000006, 41.382507324199999],
[-73.968963622999993, 41.410072326700003],
[-73.989562988299994, 41.439929962199997],
[-74.015953064000001, 41.464096069299998],
[-74.006843566900002, 41.499134063699998],
[-73.999168396000002, 41.5377388],
[-73.9613571167, 41.581764221199997],
[-73.956344604500003, 41.627635955800002],
[-73.948852539100002, 41.678043365500002],
[-73.946556091299996, 41.729282379200001],
[-73.9569854736, 41.7779464722],
[-73.9701004028, 41.828430175800001],
[-73.985443115199999, 41.881973266599999],
[-74.006584167499994, 41.924633026099997],
[-73.991699218799994, 41.975730896000002],
[-73.982696533199999, 42.033111572300001],
[-73.962783813499996, 42.085037231400001]
]
}
}]
});
map.data.setStyle({
strokeColor: "#FF0000",
strokeOpacity: 0.8,
strokeWeight: 10,
});
}
google.maps.event.addDomListener(window, "load", initMap);
html,
body,
#map {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}
<!-- added 2/8/2023 to prevent:
Loading the Google Maps JavaScript API without a callback is not supported: https://developers.google.com/maps/documentation/javascript/url-params#required_parameters
-->
<script>
function dummy() {}
window.dummy=dummy;
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=dummy"></script>
<div id="map"></div>
Is there a way to change the <title> element in a Meteor app? Seems templates are only processed in the <body>.
Pretty much anywhere in your client-side JavaScript code:
document.title = "My new title";
You can extend David Wihl's solution:
Deps.autorun(function(){
document.title = Session.get("DocumentTitle");
});
Then You can in any time call:
Session.set("DocumentTitle","New Document Title");
If you use iron:router you can add the package manuelschoebel:ms-seo to handle the title along with meta tags. This is useful for static and dynamic SEO data:
Router.map(function() {
return this.route('blogPost', {
path: '/blog/:slug',
onAfterAction: function() {
var post = this.data().post;
SEO.set({
title: post.title,
meta: {
'description': post.description
},
og: {
'title': post.title,
'description': post.description
}
});
}
});
});
You can create a helper for setting the title (CoffeeScript):
UI.registerHelper "setTitle", ->
title = ""
for i in [0..arguments.length-2]
title += arguments[i]
document.title = title
undefined
or the same in Js:
UI.registerHelper("setTitle", function() {
var title = "";
for (var i = 0; i < arguments.length - 1; ++i) {
title += arguments[i];
}
document.title = title;
});
Then you can use it in complex ways, and it will be reactive:
{{#if book}}
{{setTitle book.title}}
{{else}}
{{setTitle "My books"}}
{{/if}}
I find it more convenient to handle that kind of thing directly in the router with a onBeforeAction:
Router.map(function() {
return this.route('StudioRoot', {
path: '/',
onBeforeAction: function() {
return document.title = "My Awesome Meteor Application";
}
});
});
you can also include in <head> </head> tags which does not reside in a template. try this:
contents of sample.html:
<head>
<title>my title</title>
</head>
<body>
...
</body>
<template name="mytemplate">
...
</template>
What I ended up doing:
in the Meteor.isClient:
Meteor.startup(function() {
Deps.autorun(function() {
document.title = Session.get('documentTitle');
});
});
now that the var is set reactively, go in the router file (if not already done: meteor add iron:router. My router file is both client and server)
Router.route('/', {
name: 'nameOfYourTemplate',
onBeforeAction: function () {
Session.set('documentTitle', 'whateverTitleIWant');
this.next(); //Otherwise I would get no template displayed
}
});
It doesn't matter if you already set a title in the head tag. It will be replaced by this one according to your route.
I had to look for an answer that would work for ui-router. I know that this might not be the answer you were looking for. Since this question was posted about 2 years ago, I figured if someone else was to come here looking for a solution with ui-router, this answer could help them:
myApp.run.js
(function() {
'use strict';
angular
.module('myApp')
.run(run);
run.$inject = ['$rootScope', '$state'];
function run($rootScope, $state) {
$rootScope.$on("$stateChangeSuccess", function(previousRoute, currentRoute){
document.title = 'myApp - ' + currentRoute.data.pageTitle;
});
};
})();
routes.js
(function() {
'use strict';
angular
.module('myApp')
.config(config);
config.$inject =
['$urlRouterProvider', '$stateProvider', '$locationProvider'];
function config($urlRouterProvider, $stateProvider) {
// ...
$stateProvider
.state('home', {
url: '/',
templateUrl: 'client/home/views/home.ng.html',
controller: 'HomeController',
data: {
pageTitle: 'My Dynamic title'
}
})
}
})();
I found this useful codes in the net, but when I run the code and clicked "Published Wall Post" I got this error.
API Error Code: 191 API Error Description: The specified URL is not
owned by the application Error Message: redirect_uri is not owned by
the application.
How to fixed this code?
thanks
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:fb="http://www.facebook.com/2008/fbml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>New Graph api & Javascript Base FBConnect Tutorial | Thinkdiff.net</title>
</head>
<body>
<div id="fb-root"></div>
<script type="text/javascript">
window.fbAsyncInit = function() {
FB.init({appId: '420291518023354', status: true, cookie: true, xfbml: true});
/* All the events registered */
FB.Event.subscribe('auth.login', function(response) {
// do something with response
login();
});
FB.Event.subscribe('auth.logout', function(response) {
// do something with response
logout();
});
FB.getLoginStatus(function(response) {
if (response.session) {
// logged in and connected user, someone you know
login();
}
});
};
(function() {
var e = document.createElement('script');
e.type = 'text/javascript';
e.src = document.location.protocol +
'//connect.facebook.net/en_US/all.js';
e.async = true;
document.getElementById('fb-root').appendChild(e);
}());
function login(){
FB.api('/me', function(response) {
document.getElementById('login').style.display = "block";
document.getElementById('login').innerHTML = response.name + " succsessfully logged in!";
});
}
function logout(){
document.getElementById('login').style.display = "none";
}
//stream publish method
function streamPublish(name, description, hrefTitle, hrefLink, userPrompt){
FB.ui(
{
method: 'stream.publish',
message: '',
attachment: {
name: name,
caption: '',
description: (description),
href: hrefLink
},
action_links: [
{ text: hrefTitle, href: hrefLink }
],
user_prompt_message: userPrompt
},
function(response) {
});
}
function showStream(){
FB.api('/me', function(response) {
//console.log(response.id);
streamPublish(response.name, 'Thinkdiff.net contains geeky stuff', 'hrefTitle', 'http://localhost:3000/', "Share thinkdiff.net");
});
}
function share(){
var share = {
method: 'stream.share',
u: 'http://thinkdiff.net/'
};
FB.ui(share, function(response) { console.log(response); });
}
function graphStreamPublish(){
var body = 'Reading New Graph api & Javascript Base FBConnect Tutorial';
FB.api('/me/feed', 'post', { message: body }, function(response) {
if (!response || response.error) {
alert('Error occured');
} else {
alert('Post ID: ' + response.id);
}
});
}
function fqlQuery(){
FB.api('/me', function(response) {
var query = FB.Data.query('select name, hometown_location, sex, pic_square from user where uid={0}', response.id);
query.wait(function(rows) {
document.getElementById('name').innerHTML =
'Your name: ' + rows[0].name + "<br />" +
'<img src="' + rows[0].pic_square + '" alt="" />' + "<br />";
});
});
}
function setStatus(){
status1 = document.getElementById('status').value;
FB.api(
{
method: 'status.set',
status: status1
},
function(response) {
if (response == 0){
alert('Your facebook status not updated. Give Status Update Permission.');
}
else{
alert('Your facebook status updated');
}
}
);
}
</script>
<h3>New Graph api & Javascript Base FBConnect Tutorial | Thinkdiff.net</h3>
<p><fb:login-button autologoutlink="true" perms="email,user_birthday,status_update,publish_stream"></fb:login-button></p>
<p>
Publish Wall Post |
Share With Your Friends |
Publish Stream Using Graph API |
FQL Query Example
</p>
<textarea id="status" cols="50" rows="5">Write your status here and click 'Status Set Using Legacy Api Call'</textarea>
<br />
Status Set Using Legacy Api Call
<br /><br /><br />
<div id="login" style ="display:none"></div>
<div id="name"></div>
</body>
This is because facebook permissions. When you create a new FB app there is a field named "App Domains" you need to call the FB app only from that address or it won´t work.
For example if you have App Domain http://www.mysite.com and you are trying to access from http://mysite.com (without www), that error apperars.
I recommend you to store in "App Domains" all the possible combinations of your domain name, including alias and subdomains
Hope this help you