Реклама без тормозов, или Еще раз про джаваскрипты
Ранее я уже писал про методику переноса рекламных блоков. Напишу еще раз — с примерами и прочим. Часть текста придется повторить.
Прежде всего, зачем это надо. Все мы знаем, что код большинства систем контекстной (и не очень контекстной) рекламы вставляется посредством джаваскриптов. При этом само тело джаваскрипта хранится не на сайте-площадке, а непосредственно на серверах рекламной сети. Так вот: каким бы хорошим хостингом и скоростными серверами не располагала данная рекламная сеть, все равно невозможно добиться того, чтобы у всех пользователей всегда был хороший коннект к рекламному серверу. А если возникает задержка в выполнении скрипта, то очень часто это приводит к тому, что медленно грузится сама страница-площадка. Поэтому ниже предлагается простенький хак для того, чтобы избежать медленной загрузки. Теоретически он должен подходить к большинству систем рекламы, использующих джаваскриптовые вставки.
Пример такой тормозящей страницы.
В чем заключается проблема: пока не прогрузился и не исполнился джаваскрипт, страница не продолжает отрисовываться браузером.
Решение: грузить джаваскрипты уже после того, как отрисован весь контент.
Что тут неприятно: если всю рекламу запихать в конец кода страницы, и если сайт сайт сверстан не слишком хитроумно, то придется удовлетвориться рекламой в подвале. А это не есть хорошо, потому что денег хочется. 8)
Тогда придется поднапрячься и сделать так, чтобы блоки из «подвала» «переезжали» на нужное место. Как именно это делается, я уже писал. Повторю вкратце.
- В местах, где надо разместить рекламные блоки, пишем простенькие div‘ы-«заглушки» и присваиваем им уникальные id, например,
. На самом деле, вместо div‘ов при необходимости можно использовать любые другие теги, но необходимость такая случается редко.<div id="adv_place_1"></div> - В самом конце страницы вывешиваем все наши рекламные коды внутри других div‘ов. Этим div‘ам мы тоже присваиваем уникальные id, например,
.<div id="adv_block_1"><!-- код вызова рекламы --></div> - Под каждым из блоков дописываем джаваскриптик, который будет заниматься пересадкой каждого div‘а с рекламой в положенный ему div-зуглушку:
<script type="text/javascript">
<!--
document.getElementById('adv_place_1').appendChild(document.getElementById('adv_block_1'));
//-->
</script>
Побочный эффект: при «пересадке» блоков страница заметно дергается. Избежать во всех случаях нельзя. Частично можно — попросту заранее задав высоту div‘а-заглушки через свойство CSS height (код добавить в header страницы или в подключаемый stylesheet):
<style type="text/css">
#adv_place_1, #adv_place_2, #adv_place_3 {height: 3.25em;}
</style>
Это хорошо работает, когда мы заранее хотя бы примерно знаем высоту рекламного блока. Пример. Небольшое подергивание все же есть, но не столь заметное. Обратите внимание, что этот фокус может приводить к некрасивым наложениям блоков друг на друга. В частности — в случае Яндекс-Директа. Об этом — ниже.
Все вышеописанное отлично работает со следующими форматами:
- МиксМаркетовские «Контекстный товар» и «Микс-Объявления» (кстати, новая программа!). Пример.
- Бегун-Автоконтекст. впрочем, для Бегуна есть и другое решение.
- Google-AdSense. Пример для Гугла и Бегуна (если Бегун не покажется — не смертельно: я в другом месте тоже проверял).
- Яндекс-Директ и Яндекс-Маркет — c 11 сентября 2008 года есть официальное решение. Приведенным ниже пользоваться не рекомендую. Я его тут оставляю просто на память. 8)
Тут есть определенная проблема: в Опере напрочь «слетают» стили с объявлений, а в FireFox блоки могут налезать на текст. Посмотрите пример в разных браузерах. Разберем проблемы подробнее.
- Проблема высоты блока решается тремя путями:
- Не задавать высоту div‘ов-заглушек вообще. Пусть у нас все дергается — все равно ведь совсем без дергания не получится.
- Если мы используем фиксированные форматы, то мы заранее знаем высоту блока. Например, в моем примере используется блок высотой 90px (нижний), и выше он ни при каких условниях стать не должен.
- Подшаманить пересаживающий джаваскрипт так, чтобы высота div‘ов-заглушек сбрасывалась при пересаживании (первая строка — как и раньше, вторая — добавлена):
<script type="text/javascript">
<!--
document.getElementById('adv_place_1').appendChild(document.getElementById('adv_block_1'));
document.getElementById('adv_place_1').style.height='auto';
//-->
</script>
- Проблема «слетающих» стилей тоже решается. Но для этого нам потребуется поставить Оперу и добавить к ней плагин Opera Developer Console.
Дальше действуем так:- Открываем нашу страницу с размещенным на ней искореженным Яндекс-Директом. К этому моменту внешний вид Директа должен быть настроен, поскольку поменять его потом будет непросто.
- Запускаем на ней Developer Console и видим примерно то, что показано на левой картинке ниже.
- Последовательно разворачивем узлы, нажимая на плюсик, и добираемся до начала первого блока Директа и находим там узел LINK (см. среднюю картинку).
- Подключаем к нашей странице его атрибут HREF:
<link href="http://an.yandex.ru/resource/context_1x27c.css" type="text/css" rel="stylesheet" /> - Аналогично добираемся до начала блока Директа и находим там узел STYLE (см. правую картинку).
- Копируем содержимое этого узла (в нижней панели) и вставляем в таблицу стилей нашей страницы (в раздел
<style type="text/css">или во внешний stylesheet). - Повторяем пункты 5–6 для каждого блока Директа и наслаждаемся результатом (в этом примере специально «причесан» скорпированный из Developer Console css-код; на самом деле, «причесывать» его не обязательно).
Картинки:

- Добавлено: последнее нововведение Яндекса с учетом только реальных показов не будет корректно работать с «пересаженными» блоками Яндекс.Директа. Пример. Если присмотритесь внимательно к активности браузера (или включите какой-нибудь LiveHTTPHeaders), то увидите, что при пролистывании через объявления ничего не происходит, а вот когда вы доматываете страницу до самого конца (там, где, собственно, «зародились» блоки), происходит обращение к счетчику показов.
Таким образом, велик шанс, что показы наших «пересаженных» блоков просто не будут засчитываться (если пользователь не докрутит страницу до конца), и, следовательно, не будут учтены клики по ним.Решение тривиальное: надо сделать так, чтобы блоки «зарождались» не внизу страницы, а вверху. Для этого оборачиваем все наше шаманство внизу страницы в еще один блок:
<div id="adv_bring_up">...</div>, добавляем строчку в таблицу стилей:#adv_bring_up {position:absolute; top:0;}. Все работает, как и прежде, но (проверьте LiveHTTPHeaders’ом) счетчик срабатывает сразу же после загрузки страницы. Пример.
Теперь осталась мелочь: наш блок некрасиво мигает вверху страницы. Тут можно еще подшаманить с CSS, например, так:#adv_bring_up {position:absolute; top:0; left:-1000px; width:900px;}. Пример.Важно понимать, что, во-первых, если вы хотите поменять внешний вид блоков, то вам, скорее всего, придется повторить все указанные действия еще раз, во-вторых, в любой момент Яндекс может сменить верстку блоков, и вам придется снова все это проделать, и, наконец, что тут мы значительно вмешиваемся в поведение блоков Яндекс-Директа, а, значит, мы никак не можем гарантировать, что указанные выше или аналогичные действия не приведут к блокировке площадки. Короче, действуйте, но на свой страх и риск.
- Проблема высоты блока решается тремя путями:
Эта инструкция написана специально для партнеров MixMarket.BIZ — партнерской сети и центра обслуживания партнеров Рекламной сети Яндекса.
Приходите к нам — мы и не такому научим! 8)
Тормозящая загрузку реклама - это не всегда плохо!
Весь прикол в том, что небольшие 5-10 секундные тормоза не дают посетителю пробежать мимо рекламы - ему приходится остановиться и подождать. Благодаря этому, кликабельность немного увеличивается.
Так что данная проблема решается на стороне юзера. Естественно, ее будут решать только 5-10% юзеров-гиков, остальные никогда не прочитают этот комментарий :)
Суть в расширении “носкрипт” в файрфоксе. Одним ударом убивается вся реклама.
Во-первых, иногда случается, что ждать ее приходится значительно дольше, чем 5-10 секунд.
Во-вторых, многие попросту закроют страницу — поскольку далеко не все рекламные площадки незаменимы для посетителя.
Боюсь, что именно таким методом каши не сваришь. Впрочем, это легко можно проверить.
Гм.
А простым (только оно не фига не простое, конечно) относительным позиционированием сверстать div-блоки нельзя разве, без JS?
Можно, но не всегда. Блоки внутри текста (по этой методике) с помощью CSS расставлять очень непросто.
Да, к нижним слоям лучше приписывать стиль display:none, а то блоки скачут снизу вверх, необычно выглядит :)
Ну это уже как кому захочется. Внизу блок появляется на практически незаметное время, если сразу после вызова блока выполняется «перевешивающий» скрипт.
хз, у меня секунды 3 висели, может из-за неторопливого инета
Скорее, из-за неторопливого браузера. 8)
Для всех:
Сделал по инструкции, все круто работает, никаких тормозов связанных с яваскриптами, вернее с их загрузкой. Но, ИМХО, есть один негативный момент. Теперь страница открывается сначала без рекламы, и к тому моменту когда блоки становятся на свои места, посетитель уже успевает прокрутить страницу вниз. Если блок, например, Директа, находится вверху страницы, то к моменту его прогрузки он окажется не в фокусе внимания пользователя. Может я не прав?
Не знаю, надо бы померить. Собственно, ТЗ для эксперимента:
1. Ставим на сайте систему, которая случайным образом то показывает все по-старому, то по-новому.
2. При показах по-старому отдается код директа со срезом 1, по-новому — со срезом 2.
3. Через несколько дней работы сравниваем результаты.
Если сделаете, результат будет очень интересным.
Кстати, если отвлечься от вопросов «торможения», то Директ вверху страницы — далеко не всегда оптимальное решение.
Если отвлечься от вопросов “торможения”, “Микс-Объявления” вверху страницы оптимальное решение :)? Но здесь надо было не так сказать: не вверху, а в верхней половине (части страницы). Под самым тулбаром браузера не лучшее решение однозначно.
> Не знаю, надо бы померить. Собственно, ТЗ для эксперимента…
Можно попробовать, только придется дополнительный огород сгородить. Как нить на досуге.
Вот еще мысль, перед самым появлением блока сделать так, чтоб на его месте что-то ненавязчиво помигало секунду, максимум две. Реализуется в яваскрипте, когда блок уже прогрузился, подстановкой какого-нибудь анимированного гифчика на место рекламы. Это просто для того, чтобы снова обратить внимание пользователя на эти места в странице, атож просмотрит и уйдет дальше.
Кстати про торможение, как оказалось, внешний http://an.yandex.ru/resource/context_1×27c.css в head страницы не слабо тормозит отрисовку в IE, при недоступности an.yandex.ru (искусственно сымитировано). В лисе, опере и сафари такого не замечено. Так что есть смысл скопировать содержимое этого файла в свой css. Если поменяют содержимое опять же надо менять его и у себя.
Не готов пока сказать. Я бы подумал еще о размещении над «листалкой». Типа когда человек просмотрел листинг товаров, не увидел нужного, он может заинтересоваться брендированным блоком.
Вполне вариант. Можно и без гифа сделать — просто visibility или цвет фона менять. Вот только не знаю, как юзер и Яндекс к этому отнесется. На Микс-Товарах я бы не возражал.
Он кешируется, так что вреда от него на порядок меньше. Можно даже не просто себе скопировать, а поставить на крон простенький скриптик, который будет регулярно граббить эту CSSку с Яндекса и кешировать у себя. Типа:
<?php if($css=file_get_contents('http://an.yandex.ru/resource/context_1×27c.css')) { $handle = fopen('cache_folder/yd.css', 'w'); fwrite($handle, $css); fclose($handle);} ?>Вот пример, в котором перед появлением рекламы, на определенное время появляется баннер загрузки, в соответсвующем месте. Это аналогичным образом уже работает у меня на “боевом” сайте. Как выглядит могу показать, но не здесь, чтобы не палить контору :)
function replaceNode(source, target, call) {
var delay = 2; // время в секундах, в течении которого показываем баннер загрузки
var targetEl = document.getElementById(target);
var sourceEl = document.getElementById(source);
if (call === undefined) {
/* Если блок не отобразил текст рекламы, то баннер загрузки вообще не показываем (чтоб зря не беспокоить юзера).
Так как innerText не работает в файрфоксе, то берем innerHTML и вырезаем из него все скрипты и тэги, то есть оставляем
только "полезный" текст.
Я использую stripScripts, stripTags, и strip яваскриптового фреймворка Prototype, но здесь
достаточно вырезать все скрипты и тег link при помощи регулярных выражений, или просто выкинуть следующие
4 строки кода, если неохота заморачиваться. */
var advTxt = sourceEl.innerHTML;
advTxt = advTxt.stripScripts().stripTags().strip();
if (!advTxt)
return;
targetEl.style.display = 'block';
// функция вызовет себя через время delay секунд
window.setTimeout(function (){replaceNode(source, target, 'true');}, delay*1000);
return;
}
// попадаем сюда при повторном вызове
targetEl.innerHTML = '';
targetEl.appendChild(sourceEl);
sourceEl.style.display = 'block';
}
...
Текст страницы
...
Через пару секунд здесь появится реклама
…
Текст страницы
…
// Перевешиваем рекламу.
// Функцию можно вызывать и для нескольких различных блоков (директ, адсенс итп), указываем соответствующие id источника и приемника.
replaceNode('someAdvSource', 'someAdvTarget');
…
replaceNode('otherAdvSource', 'otherAdvTarget');
Да я уже посмотрел. 8)
Выглядит прекрасно, хотя я бы растянул loading_bar.gif на всю ширину блока.
Было бы лучше примеры без использования фреймворков показывать. Благо что регексп для удаления тегов несложный:
advTxt = advTxt.replace(/(<([^>]+)>)/ig, '');Что-то не смог быстро подобрать подходящий регексп в 4 утра :), поэтому постарался только донести смысл. Надо все что между и выкусить полностью, включая сами теги. Остальные убрать, а то, что внутри них оставить. Не уверен, что /(<([^>]+)>)/ig подойдет.
Я этот регексп тупо нагуглил. 8)
С ним, действительно, могут быть проблемы при js- и css-вставках; их можно отдельно почикать.
2 Evgeny:
А можно увидеть Ваш вариант с “боевого сайта” полностью?
Это он и был полностью
Тужился, тужился, да так и не разобрался, в этой области мои знания довольны скупы. Евгений, а можно глянуть на пример в работе?
С уважением, Александр. [DSVSoft [at] ya.ru]
Попробую разжувать :)
<!--Начало (середина) страницы, место где выводим рекламный блок-->Внимание! Идет загрузка рекламного блока, еще пара секунд и он появится, всем смотреть сюда!!!
<!-- В самом конце html страницы вставляем рекламный код-->
// здесь какой-то код вызова рекламы
function replaceNode(source, target, call) {
var delay = 2;
var targetEl = document.getElementById(target);
var sourceEl = document.getElementById(source);
if (call === undefined) {
var advTxt = sourceEl.innerHTML;
if (!advTxt)
return;
targetEl.style.display = 'block';
window.setTimeout(function (){replaceNode(source, target, 'true');}, delay*1000);
return;
}
targetEl.innerHTML = '';
targetEl.appendChild(sourceEl);
sourceEl.style.display = 'block';
}
// пересаживаем блок рекламы
replaceNode('advSource', 'advTarget');
эх, код скрипта порезался
Починил. 8)
Огромное спасибо! Все таки раскурил javascript :)
Попутно размышляя, у меня появился вопрос: а если сделать загрузку рекламного блока с помощью AJAX? Насколько я знаю, загрузка получиться асинхронной (~многотопоточной). Не спасет ли примение AJAX’а тормоза при загрузке сайта из-за рекламной вставки?
Натыкался на много “за” и “против”, AJAX’а, но пока для себя так и не решил.
[…] Всякие рекламные системы, в частности, РСЯндекса, МиксМаркет (Контекстный товар) и Бегун, предлагают вставлять свой код через джаваскрипт. Неприятно бывает, когда этот джаваскрипт по каким-либо причинам не грузится или грузится слишком медленно. Как с этим бороться — есть решение. Обновленное и расширенное решение […]
а почему бы не просто не пустить js отдельным потоком?
пихаем js в отдельную функцию и выполняем ее при помощи setTimeout с задержкой выполнения 1ms
получается функция, которая не влияет на рендеринг страницы
А в чем смысл? Результат вроде как будет тот же, а код усложняется.
Стоп, вы, наверное, не понимаете, как работает setTimeout.
Тема этого топика: “пока не прогрузился и не исполнился джаваскрипт, страница не продолжает отрисовываться браузером”
Так вот, функция, запущенная через setTimeout, не влияет на рендеринг страницы, т.е. на “отрисовку страницы браузером” (если так понятней)
По той же причине инклудят js следующим образом:
setTimeout(’
e=document.createElement(”script”);
e.setAttribute(”src”,”myscript.js”);
e.setAttribute(”type”,”text/javascript”);
document.getElementsByTagName(”head”)[0].appendChild(e)’,
1);
чтобы браузер отрисовывал контент, а не ждал загрузки js
Джаваскрипт, запущенный в самом конце документа, тоже не влияет на скорость рендеринга основного контента.
Я не против вашего варианта, но считаю его немного избыточным.
Для этого есть комбинированный window.onload, а нет setTImeout каждую мс — вы так машину у пользователя запросто повесить можете. Особенно в каком-нибудь тормознутом IE
http://webo.in/articles/habrahabr/05-delayed-loading/
P.S. В FF3 не отображается файл стилей. Идентифицировать проблему не могу (может, nginx глючит?)
Спасибо за ссылку. Но еще раз повторю, что решений море, но ни одно не настолько просто, как запуск скрипта в самом конце документа. 8)
P.S. — не понял.
Спасибо! Очень полезный сайт.
[…] стоят потерь в скорости загрузки страниц, ведь, как известно, если подвисает загрузка JavaScript-вставки, то подвисает и […]
Неприятные новости: последнее нововведение Яндекса с учетом только реальных показов не будет корректно работать с «пересаженными» блоками Яндекс.Директа.
Появилось решение. Сейчас допишу в конец поста.
[…] недоступности серверов, раздающих рекламные блоки (см. также мой предыдущий пост на эту тему). Собственно, суть этого функционала в том, что […]
Добавить комментарий »