Now we have a feature. Add google advertisement in application. If google ad has been set, then show the div area. Otherwise, remove the div area(not show ad space). But how to know google ad has been set?
We can prepare the google ad script as below:
Header
<script async='async' src='https://www.googletagservices.com/tag/js/gpt.js'></script>
<script>
var googletag = googletag || {};
googletag.cmd = googletag.cmd || [];
googletag.cmd.push(function() {
googletag.defineSlot('/[ID]/[NAME]', [[WIDTH, HEIGHT]], '[CONTAINER]').addService(googletag.pubads());
googletag.pubads().enableSingleRequest();
googletag.pubads().collapseEmptyDivs();
googletag.enableServices();
});
</script>
Body
<div id='[CONTAINER]'>
<script>
googletag.cmd.push(function() { googletag.display('[CONTAINER]'); });
</script>
</div>
How to check the response data?
As I understood google ad has been set means ad slot has been filled by an ad. If not please refine your question.
Answering your question:
Check out googletag.events.SlotRenderEndedEvent
This event is fired when the creative code is injected into a slot.
This event will occur before the creative's resources are fetched, so
the creative may not be visible yet. The event is fired by the service
that rendered the slot
In the callback you'll also have a flag indicating if the slot has been filled or not
isEmpty - true if no ad was returned for the slot, false otherwise.
Although you can do it programmatically, also take a closer look at collapseEmptyDivs(opt_collapseBeforeAdFetch):
Whether to collapse the slots even before the ads are fetched. This
parameter is optional; if not provided, false will be used as the
default value.
Related
I created a new web property in my google analytics account. When I navigate to the Tracking Code of the property, the code looks like this:
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-XXXXXXXXX-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-XXXXXXXXX-1');
</script>
I have multiple clients and each client has their own subdomain on my site. Example:
subdomain1.mysite.com UA-XXXXXXXXX-1
subdomain2.mysite.com UA-XXXXXXXXX-2
subdomain3.mysite.com UA-XXXXXXXXX-3
And in my HTML, I want to load the tracking code that that particular client has given me (identified based on current subdomain).
My question is, is it safe to assume, that the tracking code script will be the same for all the properties (except of course the UA number)?
If so, I can simply change the UA number in the tracking code like so:
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=<%= current_client.google_analytics_code %>"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '<%= current_client.google_analytics_code %>');
</script>
If you haven't made any other changes/additions to the tracking script (like custom dimensions, anonymizers, linkers, etc.) that you don't want pushed to all the clients' subdomains, then it is safe for you to dynamically insert the UA account ID.
Have in mind though, that if you plan to have two UA codes on those subdomains (for ex. your roll-up and theirs for the subdomain), you should rename trackers and cookies to separate the tracking and don't mix the attribution information between the accounts.
I'm writing an app using PhoneGap Build, jQuery Mobile and Energize.js (to speed up clicks)
My wish is to bind an 'event' to the Google Analytics plugin for PhoneGap Build, so that I can track user clicks.
As you can see below, my tracking listener is bound to a 'touchstart' event. At the moment, none of the tracking is working. I am unsure if it is because I have bound to an incorrect action (which Energize.js may have changed) or if there is another issue in my code.
Any help would be appreciated. My account on Google Analytics is set as a 'Webpage' instead of 'Mobile App' as per the plugin guidelines.
$(document).on("touchstart", ".condition-list-item a", function() {
var deviceID = device.platform + '.' + device.uuid;
// Generates unique variable for each device
var conditionVar = $(this).attr("data-condition");
// Pulls ConditionName from list item clicked
PageButtonClicked(conditionVar);
// Fires 'Page' tracking to Google Analytics, with ConditionName as 'Page'
VariableButtonClicked(deviceID, conditionVar)
navigator.geolocation.getCurrentPosition(onSuccess);
// Creates an object 'Position' using Geolocation API
function onSuccess(position) {
var geo = position.coords.latitude + ', ' + position.coords.longitude;
}
});
Try this:
$(document).ready(function(){
$(".condition-list-item a").on("touchstart", function(e){
//your function
});
});
As follow-up, the above code is still not working. Google Analytics is currently attempting to track the information as if it were a website (as recommended by the plugin).
I change the settings on the Google Analytics website to track as if it were a Mobile App. I still think the above code is not working; however, Google Analytics' built in tracking takes care of much the same stuff and is working beautifully.
I'm trying to use the YouTube Data API V2.0 to pull data insights for the videos/channels of our client. I have a developer key and a token that my client generates, and successfully figured out how to retrieve that information. My problem is, when my client uses the app for YouTube token generation, we are asking for an access that means EVERYTHING and to be able to "manage" their accounts.
This is a major concern for the client and they don't want us to have this kind of complete access. Is there a way to get a token generated with only read-only permission?
Thanks very much for any help!
I have successfully used https://googleapis.com/auth/youtube.readonly as a scope; if you ask for just that scope during the initial oAuth flow (and NOT for https://googleapis.com/auth/youtube at the same time, as that is the management scope which will override the readonly scope), then you will get a 403 error whenever attempting an action that requires management permissions (inserting, uploading, updating, deleting).
The google-api clients for v3 handle this quite smoothly, if you're using them. If you have written your own oAuth flow control, just make sure you have the sole readonly scope when requesting the initial token.
EDIT IN RESPONSE TO COMMENT: To view this in action (I'll use javascript to show), you can create a simple demo using the sample code provided by the API docs. Here's the general process:
1) In the Google API console, create a 'project' and authorize the YouTube API for that project (under the Services tab). Additionally,create a client ID for web applications (under the API access tab) and add in your domain as an authorized Javascript domain.
2) On your server, create and HTML file to serve as your interface (in this sample, it is designed to let you create a new playlist and add items to it). Here's the code, straight from the docs:
<!doctype html>
<html>
<head>
<title>Playlist Updates</title>
</head>
<body>
<div id="login-container" class="pre-auth">This application requires access to your YouTube account.
Please authorize to continue.
</div>
<div id="buttons">
<button id="playlist-button" disabled onclick="createPlaylist()">Create a new Private Playlist</button>
<br>
<label>Current Playlist Id: <input id="playlist-id" value='' type="text"/></label>
<br>
<label>Video Id: <input id="video-id" value='GZG9G5txtaE' type="text"/></label><button onclick="addVideoToPlaylist()">Add to current playlist</button>
</div>
<h3>Playlist: <span id="playlist-title"></span></h3>
<p id="playlist-description"></p>
<div id="playlist-container">
<span id="status">No Videos</span>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script src="auth.js"></script>
<script src="playlist_updates.js"></script>
<script src="https://apis.google.com/js/client.js?onload=googleApiClientReady"></script>
</body>
</html>
3) In that same location, create the script "playlist_updates.js" with this code (again, straight from the docs):
// Some variables to remember state.
var playlistId, channelId;
// Once the api loads call a function to get the channel information.
function handleAPILoaded() {
enableForm();
}
// Enable a form to create a playlist.
function enableForm() {
$('#playlist-button').attr('disabled', false);
}
// Create a private playlist.
function createPlaylist() {
var request = gapi.client.youtube.playlists.insert({
part: 'snippet,status',
resource: {
snippet: {
title: 'Test Playlist',
description: 'A private playlist created with the YouTube API'
},
status: {
privacyStatus: 'private'
}
}
});
request.execute(function(response) {
var result = response.result;
if (result) {
playlistId = result.id;
$('#playlist-id').val(playlistId);
$('#playlist-title').html(result.snippet.title);
$('#playlist-description').html(result.snippet.description);
} else {
$('#status').html('Could not create playlist');
}
});
}
// Add a video id from a form to a playlist.
function addVideoToPlaylist() {
addToPlaylist($('#video-id').val());
}
// Add a video to a playlist.
function addToPlaylist(id, startPos, endPos) {
var details = {
videoId: id,
kind: 'youtube#video'
}
if (startPos != undefined) {
details['startAt'] = startPos;
}
if (endPos != undefined) {
details['endAt'] = endPos;
}
var request = gapi.client.youtube.playlistItems.insert({
part: 'snippet',
resource: {
snippet: {
playlistId: playlistId,
resourceId: details
}
}
});
request.execute(function(response) {
$('#status').html('<pre>' + JSON.stringify(response.result) + '</pre>');
});
}
Finally, create the file "auth.js" -- this is the code that actually does the oAuth2 flow:
// The client id is obtained from the Google APIs Console at https://code.google.com/apis/console
// If you run access this code from a server other than http://localhost, you need to register
// your own client id.
var OAUTH2_CLIENT_ID = '__YOUR_CLIENT_ID__';
var OAUTH2_SCOPES = [
'https://www.googleapis.com/auth/youtube'
];
// This callback is invoked by the Google APIs JS client automatically when it is loaded.
googleApiClientReady = function() {
gapi.auth.init(function() {
window.setTimeout(checkAuth, 1);
});
}
// Attempt the immediate OAuth 2 client flow as soon as the page is loaded.
// If the currently logged in Google Account has previously authorized OAUTH2_CLIENT_ID, then
// it will succeed with no user intervention. Otherwise, it will fail and the user interface
// to prompt for authorization needs to be displayed.
function checkAuth() {
gapi.auth.authorize({
client_id: OAUTH2_CLIENT_ID,
scope: OAUTH2_SCOPES,
immediate: true
}, handleAuthResult);
}
// Handles the result of a gapi.auth.authorize() call.
function handleAuthResult(authResult) {
if (authResult) {
// Auth was successful; hide the things related to prompting for auth and show the things
// that should be visible after auth succeeds.
$('.pre-auth').hide();
loadAPIClientInterfaces();
} else {
// Make the #login-link clickable, and attempt a non-immediate OAuth 2 client flow.
// The current function will be called when that flow is complete.
$('#login-link').click(function() {
gapi.auth.authorize({
client_id: OAUTH2_CLIENT_ID,
scope: OAUTH2_SCOPES,
immediate: false
}, handleAuthResult);
});
}
}
// Loads the client interface for the YouTube Analytics and Data APIs.
// This is required before using the Google APIs JS client; more info is available at
// http://code.google.com/p/google-api-javascript-client/wiki/GettingStarted#Loading_the_Client
function loadAPIClientInterfaces() {
gapi.client.load('youtube', 'v3', function() {
handleAPILoaded();
});
}
Note in there the OAUTH2_SCOPES constant. It's set to allow full management access, so if you then visit the html page in your browser and click on the 'authorize' link, you should see the window asking you to grant your domain access to manage your YouTube account. Do this, and then the code becomes functional ... you can add playlists and playlist items to your heart's content.
If you, however, then modify auth.js so that the OAUTH2_SCOPES looks like this:
var OAUTH2_SCOPES = [
'https://www.googleapis.com/auth/youtube.readonly'
];
and clear your cookies (to avoid inheriting the permissions you already granted ... just closing the browser and relaunching ought to be enough), then try again (visit the HTML, click the authorize link), you'll see that this time it's asking you to grant permission only to VIEW the account rather than manage it. If you grant that permission, then when you try to add a playlist through the interface you'll get an error message appearing that says you can't create the playlist.
If you're not using javascript, but instead a server-side language, as I mentioned the gapi clients are quite smooth. However, the handling of oAuth2 scope in these clients is not quite as transparent, and they're by design 'greedy' (in that, as it abstracts a service endpoint to an object, it will request the most thorough scope it needs to do any of the actions at that endpoint ... so even if you only intend to do list calls, if the service has an update action as well the client will request full management privileges). This can be modified, though, if you want to get into the client code -- or you could use it as a model for creating your own simplified client that you can granularly control in terms of scope.
That's about as thorough as I can be without knowing your underlying technologies. Hope the explanation helps!
I'm having an issue using Exoclick adult advertisement to advertise on a mobile website using JQuery UI.
I don't know how much I can disclose here until it goes too far into "adult" that I can't post it here anymore.
The Exoclick banners show, but only once! Navigating inside the site doesn't the same ad again (we have two ads, bottom and top. Each is only loaded ONCE per site traversal). If you refresh using the refresh function of the browser ("F5"), they will load again... But only once.
Alright, Exoclick gives me a snippet like this:
<!-- BEGIN ExoClick.com Ad Code -->
<script type="text/javascript" src="http://syndication.exoclick.com/ads.php?type=300x50&login=<username>&cat=110&search=&ad_title_color=0000cc&bgcolor=FFFFFF&border=0&border_color=000000&font=&block_keywords=&ad_text_color=000000&ad_durl_color=008000&adult=0&sub=&text_only=0&show_thumb=&idzone=<zone id>&idsite=<site id>"></script>
<noscript>Your browser does not support JavaScript. Update it for a better user experience.</noscript>
<!-- END ExoClick.com Ad Code --></div>
The thing is, this works perfectly on static sites, but due to the nature of JQuery Mobile to fetch everything using AJAX, the scripts would be loaded many times over into the browser's execution context (at least this is what I suppose happens!) and in the end... not even execute anymore?
What I already thought of:
Cache the output of the Exoclick ad script (is there something like "outputcache" for JS?)
Deactivate Ajax
I tried deactivating Ajax requests but for some reason this didn't do anything:
<script>
$(document).bind("mobileinit", function(){
$.mobile.ajaxEnabled = false;
});
</script>
Deactivating Ajax should work:
$(document).bind("mobileinit", function () {
$.mobile.addBackBtn = false;
$.mobile.ajaxEnabled = false;
$.mobile.ajaxLinksEnabled = false;
});
On the other hand, you can refresh/reload your script on each ajax success
$('html').ajaxSuccess(function() {
//reload your script using js, plenty of that on google
});
I did it... #bobek indirectly brought me to this answer.
What I did is create an invisible div which contains the ads at first. Then, on pageinit, I steal the div and remove it from DOM. The div will now have an iframe inside made by Exoclick.
Then, without the script by exoclick, I insert it back into the dom on each page init event...
To prevent that the script gets inserted back into the dom, on the server side I check for the X-REQUESTED-WITH header. If it's XMLHttpRquest, I don't send the ads.
This is how it looks in code:
The temporary ad placement, ANYWHERE on the site:
<div id="ads">
<div style="display: none" id="topad">
<?php require("./_topbannerb.php"); ?>
</div>
<div style="display: none" id="bottomad">
<?php require("./_bottombannerb.php"); ?>
</div>
</div>
The two PHP files contain the tags by exoclick. Nothing else.
A script in the head tag:
<script>
ads = "";
first = true;
$(document).bind('pageinit', function() {
if (first) {
ads = $("#ads");
ads.remove();
}
first = false;
$.each($(".adt"), function(i, v) {
$(v).append($(ads).children("#topad").first().children("div").clone())
});
$.each($(".adb"), function(i, v) {
$(v).append($(ads).children("#bottomad").first().children("div").clone())
});
});
</script>
Then, where the ads are supposed to be placed in the end:
<div class="adt"> </div>
The script automatically inserts into each ad placement. Here I have two different ad regions: Top and bottom. Both have no differences except how exoclick handles them in the back.
I have a form that lets users select checks, and when submitted, creates a PDF, which opens in a new browser tab. It doesn't have any branding, and will probably open in a plugin anyway, so I don't want it taking over my site's tab. So I set the form's target to _blank.
But it's possible for the user to submit the form without enough information to create the PDF, in which case I flag the error (server-side) and re-render the form. But because I set the form's target, this re-render opens in a new tab as well, and that's not what I want - in this case, I want it to behave as if target were _top.
So the question is: Can I change the browser's rendering target server-side?
Yes, I know that this can be done with client-side JavaScript, but JS annoys me, and I have to do the validation server-side anyway. I may end up having to use it, but please don't suggest it as an answer - I'm more curious if what I'm attempting can even be done.
PS: I'm on Ruby on Rails 2.3.8, in case anyone knows a framework-specific solution.
A workaround on this problem would be to use the content-disposition header on the pdf, in order to force the file to be downloaded, and avoid the whole "target" approach..
Content-type: application/pdf
Content-Disposition: attachment; filename="downloaded.pdf"
No. This is a purely client-specific feature. As a matter of fact, it's quite possible to get a browser that supports only one window and where the target attribute would have simply no effect. There were even efforts to make this attribute disappear from future HTML standards completely (for instance, the XHTML branch had no such attribute).
The only overlap that I can think of between HTML and HTTP are the <meta http-equiv> tags (where HTML can affect otherwise HTTP-controlled behavior). HTTP is a transfer protocol, designed to work with about just any kind of data. Letting it control presentation would be a pretty terrible mix of concerns.
Fortunately, we live in a JavaScript-enabled world. It is rather easy to validate a form using an AJAX request, especially with libraries like jQuery.
For instance, this script performs a POST request to an URL (in this case, /pdf/validate) and expects the page to send back "ok" (if everything's good) or something else if there was an error.
<form method="post" action="/pdf/send" id="pdf-form">
<!-- form stuff here -->
</form>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
$(document).ready(function()
{
// set to true if we are to bypass the check
// this will happen once we've confirmed the parameters are okay
var programmaticSubmit = false;
// attach an event handler for when the form is submitted
// this allows us to perform our own checks beforehand; we'll do so by
// cancelling the event the user triggered, and do the submit ourselves if
// we detect no error
$('#pdf-form').submit(function(event)
{
if (!programmaticSubmit)
{
// first off, cancel the event
event.preventDefault();
// do an AJAX request to /pdf/validate
$.ajax("/pdf/validate", {
type: "POST",
data: $(this).serialize(), // send the form data as POST data
success: function(result)
{
// this gets called if the HTTP request did not end
// abnormally (i.e. no 4xx or 5xx status);
// you may also want to specify an "error" function to
// handle such cases
if (result == "ok")
{
// since the server says the data is okay, we trigger
// the event again by ourselves, but bypassing the
// checks this time
programmaticSubmit = true;
$(this).submit();
}
else // something went wrong! somehow display the error
alert(result);
}
});
}
});
});
</script>