I'm facing a little challenge here.
I'm trying to implement ads in my blazor server solution, and i cannot get it to work. So i've come up with a small MVC app where it works.
I must say that the blazor app is for a client i'm working for, and I don't know who supplies these adds. They send the code that i must implement for it to work.
Here is the stuff that they have asked me to implement in the head of the webpage
<script type="text/javascript">
var utag_data = {
}
</script>
<!-- Loading script asynchronously -->
<script type="text/javascript">
(function(a,b,c,d){
a='//partnerurl';
b=document;c='script';d=b.createElement(c);d.src=a;d.type='text/java'+c;d.async=true;
a=b.getElementsByTagName(c)[0];a.parentNode.insertBefore(d,a);
})();
</script>
<script async='async' src='https://macro.adnami.io/macro/spec/adsm.macro.someId.js'></script>
<script>
var adsmtag = adsmtag || {};
adsmtag.cmd = adsmtag.cmd || [];
</script>
<link rel="preconnect" href="https://cdn.cookielaw.org">
<link rel="preload" href="https://cdn.cookielaw.org/consent/tcf.stub.js" as="script"/>
<script src="https://cdn.cookielaw.org/consent/tcf.stub.js" type="text/javascript" charset="UTF-8"></script>
<link rel="preconnect" href="https://securepubads.g.doubleclick.net">
<script async src="https://securepubads.g.doubleclick.net/tag/js/gpt.js"></script>
<script>
var googletag = window.googletag || {};
googletag.cmd = googletag.cmd || [];
window.yb_configuration = {"domain":"clientdomain"};
(function (y, i, e, l, d, b, I, R, D) {
d.Yieldbird = d.Yieldbird || {};
d.Yieldbird.cmd = d.Yieldbird.cmd || [];
l.cmd.push(function () {l.pubads().disableInitialLoad();});
b = i.createElement('script'); b.async = true;
b.src = (e === 'https:' ? 'https:' : 'http:') + '//jscdn.yieldbird.com/' + y + '/yb.js';
I = i.getElementsByTagName('script')[0];
(I.parentNode || i.head).insertBefore(b, I);
})('950dff97-bb8d-4667-952b-d72ce8bbe88b', document, document.location.protocol, googletag, window);
</script>
<script>
googletag.cmd.push(function () {
googletag.pubads().enableLazyLoad({
fetchMarginPercent: 150,
renderMarginPercent: 75,
mobileScaling: 1.5
});
});
</script>
And for each add placement i've received some html/javascript i must place at the location.
Heres an example:
<!-- /x,y/domain/domain.dk/billboard_1 -->
<script async="async" src="https://securepubads.g.doubleclick.net/tag/js/gpt.js">
</script>
<script>
var googletag = googletag || {};googletag.cmd = googletag.cmd || [];
</script>
<script>
googletag.cmd.push(
function() {
var YBmapping = googletag.sizeMapping().addSize([931,0],[[930,180]]).addSize([0,0],[]).build();
googletag.defineSlot('/x,y/domain/domain.dk/billboard_1', [[930, 180]], 'div-gpt-ad-billboard_1').defineSizeMapping(YBmapping).addService(googletag.pubads());
googletag.enableServices();
});
</script>
<div id='div-gpt-ad-billboard_1'>
<script>
googletag.cmd.push(function() {
googletag.display('div-gpt-ad-billboard_1');});
</script>
</div>
I've obfuscted some variables. But i guess you get the hang of it..
This is from the MVC app, and it works. It places extra html inside my div with the div-gpt-ad-billboard_1 id. So on the website the HTML would look like this:
<div id="div-gpt-ad-billboard_1">
<script>
googletag.cmd.push(function() {
googletag.display('div-gpt-ad-billboard_1');});
</script>
<div id="google_ads_iframe_/x,y/domain/domain.dk/billboard_1_0__container__" style="border: 0pt none; width: 930px; height: 0px;"></div></div>
And if i deploy my MVC app to the live endpoint we have, an iFrame is inserted into the div with the google_ads_iframe Id, where the add is displayed.
Now on my blazor app, this doesn't happen.
I've created a blazor component which contains the ad i want to place. It looks like this:
<script async="async" suppress-error="BL9992" src="https://securepubads.g.doubleclick.net/tag/js/gpt.js">
</script>
<script suppress-error="BL9992">
var googletag = googletag || {};googletag.cmd = googletag.cmd || [];
</script>
<script suppress-error="BL9992">
googletag.cmd.push(
function() {
var YBmapping = googletag.sizeMapping().addSize([931,0],[[930,180]]).addSize([0,0],[]).build();
googletag.defineSlot('x,y/domain/domain.dk/billboard_1', [[930, 180]], 'div-gpt-ad-billboard_1').defineSizeMapping(YBmapping).addService(googletag.pubads());
googletag.enableServices();
console.log(googletag);
});
</script>
<div id='div-gpt-ad-billboard_1'>
<script suppress-error="BL9992">
googletag.cmd.push(function() {
googletag.display('div-gpt-ad-billboard_1');});
</script>
</div>
As i understand it you cannot directly call script tags in blazor components, but they work if you add the suppress-error, and i can atleast get it to console log from them.
The head is the same in the blazor app as in the MVC app, as script tag works fine in _Host.cshtml in blazor.
The issue is that for my blazor app the ad component looks like this on the live endpoint:
<div id="div-gpt-ad-billboard_1"><script><!--!-->
googletag.cmd.push(function() { googletag.display('div-gpt-ad-billboard_1');});
</script></div>
Notice that the entire div with the google iframe ID is missing. It's as if it doesn't update anything. I've tried to call statehaschanged from OnInitializedAsync. Nothing happens, and i guess it makes sense, since nothing is probably added to the render tree that statehaschanged activates the rerendering of.
Does anyone have any idea, how i can get it to work like the MVC app ?
Related
I like to add Media.Net Network via JavaScript to MoPub. The team from Media.Net send me javascript I shoudl add to MoPub Network tab. So far so good.
They send me exactly this code:
//Add this code in head section
<script type="text/javascript">
window._mNHandle = window._mNHandle || {};
window._mNHandle.queue = window._mNHandle.queue || [];
medianet_versionId = "3121199";
</script>
<script src="//contextual.media.net/dmedianet.js?cid=MYCUSTOMERKEY" async="async"></script>
//Add this code in body section
<div id="BANNERKEY">
<script type="text/javascript">
try {
window._mNHandle.queue.push(function () {
window._mNDetails.loadTag("BANNERKEY", "320x50", "BANNERKEY");
});
}
catch (error) {
}
</script>
</div>
I believe both tags should go to the network tab of MoPub like this:
But here comes the question. MoPub highly recommends to add a failover tag in case the network responds with a no fill or any other error. But my knowledge is limited to add this failover tag to the Media.Net javascript code.
<script type="text/javascript" charset="utf-8"> loaded=true; window.location="mopub://failLoad"; </script>
I added the failover tag to the catch block and it seems to work.
<script type="text/javascript">
window._mNHandle = window._mNHandle || {};
window._mNHandle.queue = window._mNHandle.queue || [];
medianet_versionId = "3121199";
</script>
<script src="//contextual.media.net/dmedianet.js?cid=MYCUSTOMERKEY" async="async">
</script>
<div id="BANNERKEY">
<script type="text/javascript">
try {
window._mNHandle.queue.push(function () {
window._mNDetails.loadTag("BANNERKEY", "320x50", "BANNERKEY");
});
}
catch (error) {
loaded= true;
window.location="mopub://failLoad";
}
</script>
</div>
I'm trying to add a JustGiving widget to my website but it doesn't display at all. I had other scripts in the file which I thought might be interfering so I ended up testing in a new plain html file and it still wouldn't work.
Interestingly enough if I copy/paste it into a W3 schools code editor it works! It's the same exact code and I cannot work out why it doesn't load in an html file.
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div id="jg-charity-events-board" data-config="id=45107">123</div>
<script>
(function(d) {
var jg = d.createElement('script');
jg.type = 'text/javascript';
jg.async = true;
jg.src = (d.location.protocol == 'https:' ? 'https://widgets.justgiving.com/charity-events-board/host.js' : 'http://widgets.justgiving.com/charity-events-board/host.js');
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(jg, s);
})(document);
</script>
</body>
</html>
Why do you just not use something like this? Didn't test but I assume it works.
<div id="scripts"></div>
<script>
var url = document.location.protocol + '//widgets.justgiving.com/charity-events-board/host.js';
var script = '<script type="text/javascript" src="${url}"></script>';
document.getElementById("scripts").innerHTML = script;
</script>
And jQuery has html and append functions for this.
I'm trying to convert a project to use requirejs instead of the solution I have below. Currently I have a layout page that contains all of the scripts at the bottom of the page (except modernizr) before the tag like this:
<head>
<script src="#Links.Assets.Scripts.Libraries.modernizr_2_6_2_js"></script>
</head>
<body>
<!-- Page content goes here -->
#RenderSection("PreScripts", false)
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="#Links.Assets.Scripts.Libraries.jquery_1_9_1_min_js"><\/script>')</script>
<script src="#Links.Assets.Scripts.Libraries.jquery_namespace_js"></script>
<script src="#Links.Assets.Scripts.Libraries.jquery_unobtrusive_ajax_js"></script>
<script src="#Links.Assets.Scripts.Libraries.jquery_validate_js"></script>
<script src="#Links.Assets.Scripts.Libraries.jquery_validate_unobtrusive_js"></script>
<script src="#Links.Assets.Scripts.Libraries.jquery_timeago_js"></script>
<script src="#Links.Assets.Scripts.Libraries.toastr_js"></script>
<script src="#Links.Assets.Scripts.Views.Shared._master_js"></script>
#RenderSection("PostScripts", false)
#{
var errorMessage = TempData[TempDataConstants.ErrorMessage] as string;
var infoMessage = TempData[TempDataConstants.InfoMessage] as string;
var successMessage = TempData[TempDataConstants.SuccessMessage] as string;
if (!string.IsNullOrEmpty(errorMessage)) {
<script>
var origTimeOut = toastr.options.timeOut;
toastr.options.timeOut = 0;
toastr.error(#Html.Raw(Json.Encode(errorMessage)));
toastr.options.timeOut = origTimeOut;
</script>
}
if (!string.IsNullOrEmpty(successMessage)) {
<script>
var origTimeOut = toastr.options.timeOut;
toastr.options.timeOut = 0;
toastr.success(#Html.Raw(Json.Encode(successMessage)));
toastr.options.timeOut = origTimeOut;
</script>
}
if (!string.IsNullOrEmpty(infoMessage)) {
<script>
var origTimeOut = toastr.options.timeOut;
toastr.options.timeOut = 0;
toastr.info(#Html.Raw(Json.Encode(infoMessage)));
toastr.options.timeOut = origTimeOut;
</script>
}
}
</body>
In the individual pages that use this layout page I then populate the PostScripts section:
#section PostScripts {
// Javascript that belongs to a single page goes here.
}
Problems
I've followed this example but as you can see where I'm checking TempData on the server to see if its not null to popup a toastr message on the client. I"m not really sure the best way to go about doing this and have tried many things. Any ideas?
I'm having trouble displaying Google DFP ads inside of jQuery-UI tabs (loaded via ajax). I have an example here:
http://www.anecka.com/google_dfp/
As you can see, initial page load and refresh works fine, when the user switches between tabs the Google DFP ads disappear. Google Console shows my tagging is correct, and no javascript errors in the console.
I've got a method that pushes the ads:
function pushVerticalGoogleAd(slot, div_id) {
googletag.cmd.push(function() {
googletag.defineSlot('/7085388/' + slot, [950, 80], div_id).addService(googletag.pubads());
googletag.enableServices();
googletag.display(div_id);
});
}
Each tab contains a call to this method like so:
pushVerticalGoogleAd('homepage_top_950x80', 'ad1');
Now before you say that it's because I'm reusing the same div-id and I'm declaring duplicate slots, well I agree but whenever I randomize the ad div_ids on the server, it's still presenting this problem.
I know I'm probably pounding a nail with a shoe here, so anybody with Google DFP experience know where I can get a hammer? :)
Thanks
I think you should try using the refresh method... without knowing exactly what you are trying to do its hard to know if this will work for you but the below code does at least allow the ads to display with multiple clicks...
Try this:
<html>
<head>
<title>Test</title>
<link rel="stylesheet" href="css/ui-lightness/jquery-ui-1.8.24.custom.css" />
<script type="text/javascript" src="js/jquery-1.7.1.js"></script>
<script type="text/javascript" src="js/jquery.ui.core.js"></script>
<script type="text/javascript" src="js/jquery.ui.widget.js"></script>
<script type="text/javascript" src="js/tabs.js"></script>
<script type='text/javascript'>
var googletag = googletag || {};
googletag.cmd = googletag.cmd || [];
(function() {
var gads = document.createElement('script');
gads.async = true;
gads.type = 'text/javascript';
var useSSL = 'https:' == document.location.protocol;
gads.src = (useSSL ? 'https:' : 'http:') +
'//www.googletagservices.com/tag/js/gpt.js';
var node = document.getElementsByTagName('script')[0];
node.parentNode.insertBefore(gads, node);
})();
</script>
<script type="text/javascript">
var divs = {};
function pushVerticalGoogleAd(slot, div_id) {
if(div_id in divs) {
googletag.cmd.push(function() {
googletag.pubads().refresh([divs[div_id]]);
});
} else {
googletag.cmd.push(function() {
divs[div_id] = googletag.defineSlot('/7085388/' + slot, [950, 80], div_id).addService(googletag.pubads());
googletag.enableServices();
googletag.display(div_id);
});
}
}
</script>
</head>
<body>
<script type="text/javascript">
$(document).ready(function() {
$('#tabs-contain').tabs();
});
</script>
<div id="tabs-contain">
<ul id="tabs">
<li><span>Tab 1</span></li>
<li><span>Tab 2</span></li>
</ul>
</div>
</body>
</html>
We're currently kicking off our first Backbone.js project here at work. In fact it's our first major JavaScript project apart from the odd jQuery stuff.
Anyway, we struggle with the architecture for our stuff. What is the best way to sort stuff out?
We've started with having everything in separate files broken up in folders for; views, models, collections and routers and then we include everything in our index.html. The issue, though, is that this leaves us with having to check for the document ready event in every file. Is this the best way to do it?
Here's an example:
This is the file called PageModel, the first line seems wrong...
$(function(){
app.models.Page = Backbone.Model.extend({
//stuff
});
});
Then in our index.html we have:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title></title>
<link href="assets/css/style.css" rel="stylesheet" type="text/css" />
<script type="text/javascript">
var app = app || {};
app.models = app.models || {};
app.collections = app.collections || {};
app.views = app.views || {};
app.routers = app.collections || {};
app.templates = app.templates || {};
app.models.griditems = app.models.griditems || {};
app.views.griditems = app.views.griditems || {};
</script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js" type="text/javascript"></script>
<script src="assets/js/libs/json2.js" type="text/javascript"></script>
<script src="assets/js/libs/underscore-1.1.7.min.js" type="text/javascript"></script>
<script src="assets/js/libs/backbone-0.5.3.min.js" type="text/javascript"></script>
<script src="assets/js/models/GridItemModel.js" type="text/javascript"></script>
<script src="assets/js/models/GalleryGridItemModel.js" type="text/javascript"></script>
<script src="assets/js/models/NewsGridItemModel.js" type="text/javascript"></script>
<script src="assets/js/models/VideoGridItemModel.js" type="text/javascript"></script>
<script src="assets/js/collections/GridCollection.js" type="text/javascript"></script>
<script src="assets/js/templates/Submenu.js" type="text/javascript"></script>
<script src="assets/js/templates/GalleryGridItemTemplate.js" type="text/javascript"></script>
<script src="assets/js/views/GridView.js" type="text/javascript"></script>
<script src="assets/js/views/GridItemView.js" type="text/javascript"></script>
<script src="assets/js/views/GalleryGridItemView.js" type="text/javascript"></script>
<script src="assets/js/views/VideoGridItemView.js" type="text/javascript"></script>
<script src="assets/js/routers/Router.js" type="text/javascript"></script>
<script src="assets/js/Application.js" type="text/javascript"></script>
</head>
<body>
</body>
</html>
This is structure we use in our Backbone projects
<!-- Libs Section -->
<script type="text/javascript" src="#Url.Content("~/Content/static/js/libs/jquery-1.5.2.min.js")"></script>
<script type="text/javascript" src="#Url.Content("~/Content/static/js/libs/jquery.validate.min.js")"></script>
<script type="text/javascript" src="#Url.Content("~/Content/static/js/libs/jquery.maskedinput-1.3.js")"></script>
<script type="text/javascript" src="#Url.Content("~/Content/static/js/libs/jquery.mousewheel.js")"></script>
<script type="text/javascript" src="#Url.Content("~/Content/static/js/libs/jquery.scrollpane.js")"></script>
<script type="text/javascript" src="#Url.Content("~/Content/static/js/libs/fileuploader.js")"></script>
<script type="text/javascript" src="#Url.Content("~/Content/static/js/libs/modernizr.min.js")"></script>
<script type="text/javascript" src="#Url.Content("~/Content/static/js/libs/json2.js")"></script>
<script type="text/javascript" src="#Url.Content("~/Content/static/js/libs/underscore-min.js")"></script>
<script type="text/javascript" src="#Url.Content("~/Content/static/js/libs/backbone-min.js")"></script>
<!-- Libs Section -->
<!-- Core Section -->
<script type="text/javascript" src="#Url.Content("~/Content/static/js/config.js")"></script> <!-- Global configs -->
<script type="text/javascript" src="#Url.Content("~/Content/static/js/core.js")"></script> <!-- Core methods for easier working with views, models and collections + additional useful utils -->
<script type="text/javascript" src="#Url.Content("~/Content/static/js/app.js")"></script> <!-- Application object inherites core.js as prototype -->
<script type="text/javascript" src="#Url.Content("~/Content/static/js/renisans.js")"></script> <!-- Project Object. Creates Namespace and Extends it with project specific methods -->
<!-- Core Section -->
<!-- Routers Section -->
<script type="text/javascript" src="#Url.Content("~/Content/static/js/routers/workspace.js")"></script>
<!-- Routers Section -->
<!-- Models Section -->
<script type="text/javascript" src="#Url.Content("~/Content/static/js/models/profile.js")"></script>
...
<!-- Models Section -->
<!-- Collections Section -->
<script type="text/javascript" src="#Url.Content("~/Content/static/js/collections/messages.js")"></script>
...
<!-- Collections Section -->
<!-- Views Section -->
<script type="text/javascript" src="#Url.Content("~/Content/static/js/views/workspace.js")"></script>
...
<!-- Views Section -->
<!-- Localization Section -->
<script type="text/javascript" src="#Url.Content("~/Content/static/js/localizations/ru_RU.js")"></script>
<!-- Localization Section -->
<!-- Init Section -->
<script type="text/javascript">
$(function() {
Rens.container = $('.l-wrapper'); // Some parameters
Rens.init({
Localization: LocalizationStrings || {}, // Object with localization strings
Profile: {
// Bootstraping initial data to Profile model
}
});
});
</script>
<!-- Init Section -->
content of app.js
var App = function() {
this.Views = {};
this.Routers = {};
this.Models = {};
this.Collections = {};
this.User = {};
this.router = null;
this.view = null;
this.baseLocation = null;
this.beforeInit = function() {};
this.afterInit = function() {};
this.init = function(initData) {
if (typeof(this.beforeInit) === 'function') {
this.beforeInit.apply(this, arguments);
}
if (this.Views.Workspace) {
this.view = new this.Views.Workspace();
}
this.baseLocation = window.location.href.replace(/[?#].*/, '') == Config.web.host;
if (this.Routers.Workspace) {
this.router = new this.Routers.Workspace(initData);
}
this.view && this.view.setListeners && this.view.setListeners();
Backbone.history.start();
if (typeof(this.afterInit) === 'function') {
this.afterInit.apply(this, arguments);
}
}.bind(this);
};
App.prototype = Core;
and content of renisans.js
var Rens = new App();
$.extend(Rens, {
container: null,
Error: function(data) {
// Handling error
},
Localization: function(dictionary) {
return {
get: function(name) {
var argumentsList = Array.prototype.slice.call(arguments),
strings = argumentsList.slice(1),
text = this[name];
if (text && strings.length) {
$(strings).each(function(i, string) {
var reg = new RegExp('\\$' + i, 'go');
text = text.replace(reg, string);
});
}
return text || 'SLB.Localization.' + name + ' not found!';
}.bind(dictionary)
}
},
formatDate: function(rawDate) {
var timestamp = /\d+/.exec(rawDate)[0],
date = Rens.DateUTC(timestamp),
months = Rens.Localization.get('months');
return {
date: date,
fullDate: [date.dd, months[date.mm], date.hh].join(' '),
shortDate: [date.dd, date.MM, date.hh].join('.')
};
},
beforeInit: function(initData) {
this.Localization = new this.Localization(initData.Localization);
}
});
also simplified content of models/profile.js
Rens.Models.Profile = Backbone.Model.extend({
...
});
If you are creating an application of this shape, i strongly suggest to use dynamic loading of your assets, like javascript and more.
you have several options for this:
Require.js
LABjs
...
i myself have no experience with LABjs, but i've been using Require.js in smaller projects for myself. But have yet to use it in a major project.
the advantages of such a system:
you can work with dependancies, and your models or views will only be loaded when they are requested by another part of your code. not all at the beginning.
require.js also provides features for minifying and agregating your code based on the dependancies you specified.
require.js has a few small plugins for loading in text files (if you use a templating system this could be useful, or a plugin to define the order in which files need to be loaded.
and require.js also has a special version for working together with jquery and its modules. (but you are not required to use this one, you can load in jquery trough manually as well)
you will need to wrap your models / views / ... in modules so require.js can load them dynamically. I asked about this here on stack overflow last week... you can find the info on how to do that here
I suggest you read the 'getting started with require.js' and see if you feel like using it.
because working with all models / views / ... in separate files is quite handy in development fase, but is defenately not recommended when going into production. the fewer requests have to be sent by the browser to the server the better.