Доброго времени суток всем!
Будучи любознательным от природы пытаюсь сейчас освоить JavaScript в различных, прикладных областях применения.
В частности, заинтересовался, как именно работает код Яндекс-метрики, который устанавливается на страницы сайтов для подсчета количества посетителей и другой статистики.
На сайте яндекса подробной информации по работе кода не нашел, поиск по ключевым словам счетчика на этом форуме тоже результатов не дал. Поэтому, посмел создать новую тему - может она будет интересна не только мне, но и другим начинающим посетителям, кто интересуется данной тематикой.
Ниже код счетчика яндекс метрики созданный под выдуманный аккаунт с id=12345678. Если не возражаете, я попробую самостоятельно изложить то, что я на данный момент могу сказать о его работе, приводя фрагменты кода и описывая их работу. в ходе рассуждения буду отмечать возникающие вопросы при помощи фразы "_НЕ_ПОНЯТНО_".
Начну с самого легкого - с раздела <noscript> в конце кода, а именно:
<noscript><div><img src="//mc.yandex.ru/watch/12345678" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
как я понимаю, этот кусок кода срабатывает, если в браузере заблокирован обработчик JS и, в этом случае, просто происходит вызов именной страницы счетчика на сайте яндекса по адресу //mc.yandex.ru/watch/12345678 что, по-видимому, вызывает инкремент счетчика на стороне сервера яндекса.
Далее, по структуре я могу сказать, что оставшийся код в рамках <script> </script> представляет из себя описание и вызов на месте функции (function (d, w, c) { ...}) которой в качестве параметров передаются глобальные document, window и параметр "yandex_metrika_callbacks" представляющий из себя свойство объекта window (или w внутри самой функции) для доступа в формате w[c].
_НЕ_ПОНЯТНО_, что делает вот этот кусок строки: " w[c] = w[c] || [] "?
Теперь вот это:
(w[c] = w[c] || []).push(function() {
try {
w.yaCounter12345678 = new Ya.Metrika({id:12345678,
clickmap:true,
trackLinks:true,
accurateTrackBounce:true});
} catch(e) { }
});
Про приведенный выше кусок кода могу сказать следующее:
в конец массива объектов w.yandex_metrika_callbacks при помощи функции push добавляется новый объект w.yaCounter12345678 cо значениями свойст передаваемыми при создании объекта типа Ya.Metrika при помощи оператора new. При этом используется конструкция try {...} catch(e) для отлова ошибки. Верно?
_НЕ ПОНЯТНО_, для чего создается этот новый объект? Как сервер яндекса получает к нему доступ? И что происходит с этим объектом далее?
Идем далее:
var n = d.getElementsByTagName("script")[0],
s = d.createElement("script"),
f = function () { n.parentNode.insertBefore(s, n); };
s.type = "text/javascript";
s.async = true;
s.src = (d.location.protocol == "https:" ? "https:" : "http:") + "//mc.yandex.ru/metrika/watch.js";
if (w.opera == "[object Opera]") {
d.addEventListener("DOMContentLoaded", f, false);
} else { f(); }
Тут вроде более-менее ясночто происходит: в html коде страницы ищется первый элемент с тегом script и присваевается в переменную n. Затем создается новый элемент того же типа в переменной s, у которого среди прочих аттрибутов (после некоторых пассов) задается источник с адресом "http://mc.yandex/metrik/watch.js". Далее идет проверка на "оперность" ,браузера и при ее отсутствии запускается функция f, которая просто вставляет тег s в начала всего блока тегов типа script.
_НЕ_ПОНЯТНО_, почему нельзя было сразу в html код включить код с вызовом адреса
http://mc.yandex.ru/metrika/watch.js? Для чего все эти усилия по поиску массива тегов типа script и вставке туда этого адреса?
Неужели это для того, чтобы выяснить какой используется протокол (http или https)? Ведь, в итоге все равно в "живом" html коде странице банально появляется вызов JS-скрипта со страницы яндекса (.../watch.js), который наверное и осуществляет увеличение счетчика?
Вот такие мысли роятся в голове любознательного ламера
.
Если лень будет комментировать мои наивные вопросы, просьба просто дать свое видение работы кода счетчика приведенного для удобства полностью ниже.
с уважением, Дмитрий
<!-- Yandex.Metrika counter -->
<script type="text/javascript">
(function (d, w, c) {
(w[c] = w[c] || []).push(function() {
try {
w.yaCounter12345678 = new Ya.Metrika({id:12345678,
clickmap:true,
trackLinks:true,
accurateTrackBounce:true});
} catch(e) { }
});
var n = d.getElementsByTagName("script")[0],
s = d.createElement("script"),
f = function () { n.parentNode.insertBefore(s, n); };
s.type = "text/javascript";
s.async = true;
s.src = (d.location.protocol == "https:" ? "https:" : "http:") + "//mc.yandex.ru/metrika/watch.js";
if (w.opera == "[object Opera]") {
d.addEventListener("DOMContentLoaded", f, false);
} else { f(); }
})(document, window, "yandex_metrika_callbacks");
</script>
<noscript><div><img src="//mc.yandex.ru/watch/12345678" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter -->