The current GPT JavaScript implementation is not following Google's recommendations, it seems like a mixture of both synchronous and asynchronous code. This page provides examples of both modes. Please note that in asynchronous mode API calls are wrapped in googletag.cmd.push() all the time.
Current implementation has the .enableServices() call outside of that wrapper which may result in firing ads before all the configuration has occurred. When in synchronous mode, there should be no wrapper at all.
Also, the Google examples use an inline snippet for asynchronous loading of gpt.js to maximise comaptibility which could work fine with every browser where the async attribute is not supported.
I suggest to fix the inline code first as per the recommendations and then offer the option to switch between synchronous and asynchronous loading.
Detailed examples of code output
Please study the attached example code files and see how the syntax changes compared to the current implementation (also attached).
Current implementation vs New, synchronous output:
- Final service API call is no longer wrapped in the googletag command queue (i.e
googletag.cmd.push()) - Slot display code is no longer wrapped in the googletag command queue (i.e
googletag.cmd.push())
Current implementation vs New, asynchronous output:
- Loading the library is changed to load asynchronously
- Ad slot definition code is wrapped around the googletag command queue
- Final service API call is wrapped around the googletag command queue, including
googletag.enableServices(); - Slot display code is wrapped around the googletag command queue
| Comment | File | Size | Author |
|---|---|---|---|
| #42 | interdiff-2365665-40-41.txt | 383 bytes | nikolay shapovalov |
| #41 | dfp-allow-asynchronous-loading-2365665-41.patch | 6.81 KB | brunodbo |
| #40 | dfp-allow-asynchronous-loading-2365665-40.patch | 6.76 KB | osopolar |
| #39 | dfp-allow_asynchronous-2365665-39-D7.patch | 6.78 KB | dobrzyns |
| #37 | allow_asynchronous-2365665-37.patch | 6.51 KB | marcelovani |
Comments
Comment #1
melon commentedHere is a patch which allows choosing between synchronous and asynchronous modes. If async mode is enabled, all inline JavaScript statements are wrapped around a
googletag.cmd.push()call.There are three different async options for loading the external gpt.js library:
Please note that the 3rd async option is only available if the advagg module is enabled as this includes the fix to
drupal_add_jssoasync => 'async'can be passed along$optionsin drupal_add_js.Comment #2
melon commentedRefactored the patch and added further fixes:
- Asynchronous loading is now tied to asynchronous rendering as the API docs say
- If asynchronous rendering is enabled then the asynchronous loading method can be selected, with the inline snippet variant as default
- Ad slot code in the template has the
googletag.cmd.push()wrapper if asynchronous mode is enabled- Added support for vertical tabs on the settings page
- Simplified wording on the admin settings page
Please disregard the previous patch and test this one.
Comment #3
bleen commentedI'm trying to get my hands around exactly how this will affect an existing site. In other words, if an existing site changed nothing except updating the module what would happen (assuming they have async checked)? Believe it or not I do not have a DFP account with which to test this, so please be really detailed with what this change looks like to the end user and to the site admin who will be fired if ads stop working the way they used to...
Below are a couple of small things...
What happens if someone turns off advagg in the future?
Can you make "Recommended by google" a link to that page
Comment #4
melon commentedUpdated the issue summary with attached sample code to help elaboration.
To answer your question regarding advagg missing nothing would happen but the async option gets thrown away. We could implement hook_modules_disabled() to set this back to its default and/or display a warning to revisit this setting when advagg gets disabled.
Regarding I will re-roll the patch with the updated description which includes a link to the documentation page.
Comment #5
melon commentedAdded the link to the Google recommendation and fixed the advagg link.
Comment #7
melon commentedNow re-rolled against the most recent version.
Comment #8
chriskinch commentedThis patch is no longer relevant as Google's documentation on what the structure should be has now changed. You can see the current recommendation here:
https://support.google.com/dfp_sb/answer/1651549?hl=en#async
With the current module setup there is no way to have the DFP script loading async and therefore it becomes a render blocking issue for performance. This is something that does need to be addressed.
There is further discussion on how this should be patched for the DFP module in this issue thread:
https://www.drupal.org/node/2629154
Comment #9
alexmoreno commentedHi Chris,
Do I understand that atm the module does not support async loading?
We are having some issues and I've detected that the site takes a lot to load, in part because of the ads being loaded. In an async scenario I would expect tyke site to be loaded, and then the ads in a different thread, not blocking the whole page Load and displaying the loading icon as loaded a lot earlier (although the ads are still being loaded)
Am I wrong?
Thanks
Comment #10
alexmoreno commentedsorry, answering myself, async is provided in gpt module. I agree with https://www.drupal.org/node/1322754#comment-6535548 this should have not be a new module, introduces confusion.
Comment #11
rescandon commentedHello Chris:
Following your suggestion about the current recommendation:
https://support.google.com/dfp_sb/answer/1651549?hl=en#async
We have this patch working in our project.
Best
Comment #12
pribeh commentedI appreciate that the maintainers of this module didn't initially want this in the module but by all current UX standards and even Google's own standards (exemplified by their AMP project) I think this issue should be considered heavily again. @rescandon thank you for taking another stab at this. I'm going to see if I can test this tonight. Could the maintainers please take a look at the patch in #11 to see if it addresses the expressed concerns? Thank you.
Comment #14
bleen commentedI've never been particularly against this feature I just dont want to introduce it if it might screw with someone's existing installation. I asked this question:
And got one response that it shouldn't affect an existing user (see #4). I would love for someone to confirm that.
Comment #15
rwohlebThe patch in #11 looks like it adds async with minimal other changes. However, the default value for the dfp_async_load variable is consistent between the settings page and the rendering code.
Comment #16
rwohlebHere is a version of the patch in #11 with a few minor changes/fixes. The new async loading defaults to off to avoid issues with existing installs.
It's also rooted in the project directory instead of the drupal root so that it's easier to apply.
Comment #17
bleen commentedI think that #16 looks pretty good. I'd like for someone else to RTBC it before I'd commit it though.
Comment #18
benjy commentedI'm not sure how this works, I don't think drupal_add_js() supports it? I made this work with $options['attributes']['async'] = 'async' and the core patch from #1664602: Allow attributes to be passed to drupal_add_[css|js] (SRI)
Comment #19
benjy commentedAh, i see now you were relying on advagg to provide that feature, I also removed the module_exists() check on that as I'm not using advagg.
Comment #20
bleen commentedIf this patch requires advagg or a core patch, thats a whole different animal. In that case I would MUCH prefer that this was implemented in a separate module that depends on advagg rather than add a new dependency here.
Thoughts?
Comment #21
benjy commentedIf it was me, i'd probably postpone this issue on the core one, once the core issue is committed we can safely commit a patch here until that point, others can just use those patches available?
Depending on advagg doesn't seem like a great solution. We could consider depending on https://www.drupal.org/project/async_js if you really want to fix it quicker.
Comment #22
marcelovaniRe-rolled the patch
Comment #23
Peps84 commentedHello all,
Google has updated it's GPT API again which has added an async attribute to the script tag as well as removing enableAsyncRendering() call. I have applied these changes to a fresh version of 7.x-1.x.
Comment #24
marcelovaniRe-rolling the patch written by Peps84
Comment #25
marcelovaniAll right,
Fixed tests and added some extra tests too.
Attaching new patch and interdiff against peps84 patch.
Comment #26
cllamas commentedWorking as expected for me in 7.x-1.x
Comment #27
cllamas commentedComment #28
cllamas commentedThis patch doesn't apply, ignore this attached file.Comment #29
cllamas commentedComment #30
cllamas commentedI've found in the documentation that enableAsyncRendering() doesn't need to be removed as even if it's the default option it can still be used to override previous configs.
https://developers.google.com/doubleclick-gpt/reference#googletag.PubAds...
Comment #37
marcelovaniRe-rolled patch #30
Comment #38
fdverwoerd commentedWe could be loading the `gpt.js` with some javascript like so:
```
$gads_js = << (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);
})();
dfp;
// Include a script tag for the Google Tag Services.
$options['type'] = 'external';
$options['weight']++;
drupal_add_js($gads_js, $options);
```
This way we have async also on the script tag getting gpt.js. What do you think? We wouldn't need the advagg module?
Comment #39
dobrzyns commentedI've re-rolled the patch. I also fixed adding the async attribute per the DFP Documentation Async Example. The async attribute is only necessary for adding the gpt.js script. Additionally, per the example, the gpt.js script should be the first of the DFP scripts, so I added weight and group to accomplish this.
Comment #40
osopolarRe-rolled patch from #39.
Comment #41
brunodboWhen using the AdvAgg Modifier module to group together async loaded JS in the header, the gtp.js script is added after the inline JS. Even though the ads are loaded fine with this order, it might be good to force the gtp.js script to be added before the inline JS, so it can start loading as soon as possible. This patch adds the
'scope_lock' => TRUEoption for the gtp.js script, so it's loaded before the inline JS, even when using AdvAgg Modifier module.Comment #42
nikolay shapovalov commentedInterdiff for #40 and #41
Comment #43
vladimirausThank you for your contributions.
Drupal 7 is no longer supported.
Closing issue as outdated.