Доброго времени суток. Хочу поделится своим исследованием на тему сабжа.
Пару дней назад возникла необходимость сделать для одного ресурса поддержку хеш-ссылок(так же известны как deep links). То есть ссылок, в которых после символа хеш(#) следует значащая часть ссылки. Такие ссылки используют практически все JavaScript фреймворки(AngujarJS, BackboneJS и т. д.) для идентификации загружаемого контента. Использование таких ссылок позволяет обновлять содержание страницы без перегрузки страницы. В этом случаи, при навигации просто меняется "якорь"(хеш), что не приводит к перегрузки страницы(автоматическому запросу страницы браузером). Таким образом, при изменении хеша, клиентский js код просто запрашивает необходимый контент с сервера(через ajax). Хеш-ссылки же используются для сохранения состояния браузера - их можно использовать как обычные ссылки(отправлять друг другу, добавлять в закладки и т. д.)
Как сделать их поддержку - тема отдельная. В общем, когда хеш-ссылки были уже готовы, возникла проблема. На сайте была реклама от Google AdSense, и, естественно, было желание, чтоб эта реклама обновлялась при переходе по дип линкам. Задача эта, на первый взгляд несложная, оказалась довольно заковыристой. Хотите узнать почему и как это все же сделать? Добро пожаловать под кат.

Как вы, скорее всего, знаете отображать на своем сайте объявления AdSense предельно просто. Необходимо зарегистрироваться в AdSense и разместить в HTML своего сайта их код. Этот код имеет примерно такой вид:
<script type="text/javascript"><!--
google_ad_client = "ca-pub-xxxxxxxxxxxxxxxx";
google_ad_slot = "xxxxxxxxxx";
google_ad_width = 111;
google_ad_height = 222;
//-->
</script>
<script type="text/javascript"
src="//pagead2.googlesyndication.com/pagead/show_ads.js">
</script>

Тут все довольно просто google_ad_client - Ваш индентификатор в AdSense, google_ad_slot - идентификатор вашего слота под объявление, google_ad_width и google_ad_height - соответственно, его высота и ширина.

Дальше запрашивается JavaScript, который вставляет на после себя iframe, в котором отображается объявления(и загружает еще пачку js-файлов).

В целом, тут все понятно. Первое желание, просто заключить весь этот AdSense код в какой-то HTML-элемент, и при "перезагрузке" страницы вначале его удалять, а потом добавлять повторно. Казалось бы, что можно быть проще? Проблема в том, что это не работает, - при загрузке хеш-ссылки, объявление не загружается. Почему? В консоли браузера всего одна ошибка - валится какой-то setTimeout.

Стало ясно, что проблема в том, что при первой загрузке, гугловый скрипт "засоряет" глобальную область видимости, из-за этого, при повторной загрузке скрипт валится. Точнее сказать не могу, поскольку JavaScript у AdSense, конечно же, минифицирован. И хотя я потратил некоторое время на то, чтоб в нем разобраться, ничего явно ошибочного я не нашел(а желания, да и времени, реверс инжинирить его как-то не было).

Следующей мыслью было почистить перед загрузкой скрипта глобальный скоуп(свойства объекта window). Все чистить, конечно, же не хотелось(надо ж чтоб свои скрипты и дальше работали), потому было решено в качестве эксперимента удалять только те поля, которые имеют префикс
"google_"(таких после загрузки AdSense появлялось довольно много). Правда и это не помогло

Слишком долго возится с чисткой глобальной области видимости не хотелось(время поджимало), да и этот вариант как не крути - чистой воды хак. Решено было завернуть код AdSense в iframe(у него свой собственный глобальный скоуп отличный от скоупа окна) и пересоздавать его при переходе на другую хеш-ссылку. Это сработало, объявления стали отображаться.

И все бы было хорошо, если бы на следующий день не выяснилось, что статистика AdSense после этого упала до нуля(и по кликам и по просмотрам). Немного погуглив, я выяснил, что, кроме прочего, правила AdSense запрещают размещение их кода внутри iframe'ов. Больше идей, как это чинить у меня на тот момент не было, и я решил обратится к гуглу.

Как это ни странно, но по этому вопросу оказалось очень мало информации, точнее вообще не оказалось. Все, хоть как-то релевантное, сводилось к тому, что автор просит Google разрешить ему использовать AdSense в iframe(есть там в правилах пункт, о том, что они могут сделать исключение), положительных ответов от Google я, кстати, не видел.

Если, честно, я очень удивился, ведь одностраничные веб-приложения - такой себе современный тренд во фронтенде, да и AdSense'ом пользуется куча народу. Неужели никто не сталкивался? Или я что-то не то ищу? В итоге, я набрел на аналогичный вопрос касательно какого-то JavaScript фреймворка(Ember.js, что ли?), ответ был достаточно краткий и сводился он к тому, что надо использовать async код AdSense. Теперь, уже я знал, что искать. Как выяснилось, есть альтернативный код для "асинхронной" загрузки AdSense объявлений. Выглядит он примерно так:
<script async src="http://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<ins class="adsbygoogle"
style="display:inline-block;width:111px;height:222px"
data-ad-client="ca-pub-xxxxxxxxxxxxxxxx"
data-ad-slot="xxxxxxxxxx"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>

И он отлично работает с повторной ajax "перезагрузкой" страницы(нужно просто удалить из DOM контейнер со "старым кодом" и вставить его повторно).

Надеюсь, эта статья сэкономит вам кучу времени при решении аналогичной проблемы. Если будут вопросы задавайте в комментариях. Удачи.
1

Комментарии

Для того, чтоб оставлять комментарии или зарегистрируйтесь.