Что означают gtm.js, gtm.dom, gtm.load в Google Tag Manager?

Что означают три события gtm.js, gtm.dom, gtm.load в dataLayer, которые срабатывают по умолчанию в Google Tag Manager и которые мы видим в режиме предварительного просмотра при загрузке любой страницы?

Каждый раз, когда загружается страница вашего сайта, в уровень данных передается информация о трех событиях: Container Loaded (gtm.js), DOM Ready (gtm.dom) и Window Loaded (gtm.load).

Режим отладки — 3 события по умолчанию

Если мы перейдем в консоль разработчика (клавиша F12 в Google Chrome) на вкладку Console, введем dataLayer и нажмем Enter, то увидим тот же самый результат:

dataLayer в консоли разработчики

Что же означают эти события?

Жизненный цикл HTML-страницы состоит из трех важных событий: DOMContentLoaded, load и beforeunload/unload. Первое отвечает за полную загрузку HTML и построение DOM-дерева, второе за окончательную прогрузку HTML и всех внешних ресурсов (включая картинки, стили и т.д.), а последнее срабатывает, когда пользователь покидает страницу сайта.

Подробнее об этом читайте в документации learn.javascript.ru. Важно отметить, что два из трех вышеперечисленных событий по умолчанию срабатывают и в Google Tag Manager.

1. Container Loaded (gtm.js)

Это первое событие, которое запускает триггер gtm.js, помещается в dataLayer и срабатывает тогда, когда контейнер GTM готов к работе.

Не так давно разработчики Google переименовали данное событие в Container Loaded. Раньше это событие называлось

Page View (Просмотр страницы), что несколько вводило интернет-маркетологов в заблуждение, поскольку в Google Tag Manager по умолчанию существует триггер со схожим названием Page View (All Pages), который используется при настройке отслеживания тегов на всех страницах сайта. Да и Page View меньше охарактеризовало себя как событие, поскольку правильнее было бы говорить именно о загрузке самого контейнера Google Tag Manager, а не о просмотре страницы.

Примечательно, что данное событие содержит в себе отметку времени в gtm.start:

gtm.js с отметкой времени в gtm.start

В дальнейшем мы можем использовать переменную уровня данных gtm.start для своих целей, например, для определения времени начала пользовательской сессии.

Как вы уже знаете, события в режиме отладки отображаются в хронологическом порядке по мере их запуска. Каждое из них имеет свой порядковый номер. Container Loaded — первое событие на представленном примере.

Примечание: некоторые события могут срабатывать ДО загрузки контейнера GTM. В этом случае Container Loaded может иметь другой порядковый номер, отличный от единицы. Например:

Container Loaded загружается вторым по порядку

Здесь Container Loaded загружается вторым по порядку, до загрузки контейнера Google Tag Manager уже доступна информация по userId.

2. DOM Ready (gtm.dom)

Событие, которое запускает триггер gtm.dom, помещается в dataLayer и срабатывает как только браузер загрузит объектную модель документа (Document Object Model). Событие происходит когда весь HTML был полностью загружен и пройден парсером, не дожидаясь окончания загрузки таблиц стилей, изображений и фреймов.

3. Window Loaded (gtm.load)

Событие, которое запускает триггер gtm.load, помещается в dataLayer и срабатывает после завершения загрузки всей страницы и всех связанных ресурсов (загрузки таблиц стилей, изображений, фреймов), когда окно полностью загружено.

Разница в скорости загрузки

Для наглядности сравним время, через которое срабатывает каждое представленное событие. Воспользуемся расширением для браузера Adswerve — dataLayer Inspector+ и вкладкой Console. Обновив страницу, мы увидим переданные события с временной меткой:

Хронология с событиями и таймингом (расширение dataLayer Inspector+)

Примечание: временная метка включается в Google Chrome через Настройки — раздел Console — галочка Show timestamps.

На примере выше у нас событие gtm.js произошло в 11:37:53.901, событие gtm.dom в 11:37:54.198, а последнее событие gtm.load в 11:37:57.690, то есть через 0,790 секунды позже, чем загрузился контейнер GTM, и на 0,492 секунды позже, чем загрузилась объектная модель документа (DOM).

Аналогично можно увидеть различия, если мы перейдем на вкладку Network и обновим страницу:

Консоль разработчика — вкладка Network

Если сайт тяжелый, имеет большое количество неоптимизированных картинок, долго загружаются скрипты, вы зашли на него впервые (страница не закэширована), то разница между DOMContentLoaded

и Load может быть существенной. И вот как раз здесь возможна ситуация, при которой вы будете пытаться прикрепить слушатель к элементу, которого еще не существует. Триггер GTM сработает, но информация через тег в инструменты веб-аналитики не попадет, поскольку не будет еще определена.

Какое из трех событий выбрать в качестве триггера?

Триггеры «Просмотр страницы»

Зависит от конкретной задачи и от момента, когда ваши данные будут готовы к отправке в инструменты аналитики:

  • если информация доступна до загрузки контейнера Google Tag Manager, и вы хотите, чтобы ваши теги срабатывали в самый ранний момент, вы можете отправлять данные сразу же, используя триггеры
    Пользовательское событие
    с именем gtm.js или Просмотр страницы (Page View).
  • если  вы хотите, чтобы ваши теги запускались после загрузки объектной модели документа, вы можете использовать триггеры Пользовательское событие с именем gtm.dom или Модель DOM готова (DOM Ready).
  • если вы не знаете, когда точно точно появляется доступ к элементу на странице, вы можете использовать триггеры Пользовательское событие с именем gtm.load
    или Window Loaded (Окно загружено).

События для одностраничных сайтов (SPA)

Одностраничное приложение (SPA, Single Page Application) — это веб-сайт / веб-приложение, основанное на JavaScript-фреймворках, которое загружает весь контент, необходимый для навигации по сайту, при загрузке первой страницы. А когда пользователь взаимодействует со страницей, контент динамически подается через JavaScript вместо отправки запроса на сервер.

Поэтому, когда вы устанавливаете Google Tag Manager на своем SPA-сайте, первая загрузка запустит все три события

gtm.js, gtm.dom, gtm.load. Но вы не увидите других таких событий, поскольку страница не перезагружается. Чтобы отслеживать последующие страницы в одностраничных приложениях, вам нужно использовать виртуальные страницы, а само отслеживание можно на основе триггера типа Изменение в истории (gtm.historyChange).

Как ускорить загрузку JavaScript

Введение

Когда разработчики создают приложения, в какой-то момент они могут столкнуться с проблемами загрузки контента. Они также могут наследовать кодовую базу, производительность которой никогда не проверялась.

К счастью, есть много способов сделать это быстрее, и они не обязательно требуют слишком много времени.

Мы не будем рассматривать здесь простые приемы, такие как удаление неиспользуемого, но все же загруженного контента, так как это очевидно.

Как все начиналось

Перед нашей командой в Brainhub была поставлена ​​задача, которая казалась тривиальной: мы должны были создать несколько умеренно больших компонентов React.js, которые можно было бы вставить в работающий сайт, работающий по традиционному подходу PHP + jQuery.

Когда мы собирались закончить нашу первую крупную итерацию, мы с нашим клиентом заметили, что сайту потребовалось не менее 12 секунд , чтобы стать интерактивным. React.js работает очень быстро, так что с этим проблем возникнуть не должно, но мы все равно его проверили. Весь пакет JS скачался и проанализировался быстро, поэтому, как мы подозревали, проблема должна заключаться в чем-то другом.

Когда мы начали углубляться в существующий код, мы обнаружили множество причуд, хаков и оптимизаций.

В итоге наше приложение заняло меньше, чем 3 секунды с момента загрузки документа. Эта статья является результатом нашей работы.

Современные инструменты сборки, такие как Webpack

Webpack предоставляет нам множество встроенных функций, таких как удаление мертвого кода. Он импортирует только необходимый код и игнорирует все остальное. Чем меньше размер кода, тем лучше.

Рендеринг и гидратация на стороне сервера

React.js, Angular, Vue и т. д. — это фреймворки на стороне клиента; это означает, что весь контент будет генерироваться в браузере, а не получать простой объект документа с сервера. В этом нет ничего плохого, так как движки современных браузеров очень производительны, но это создает проблемы в некоторых областях:

  • Правительственные компьютеры, которые часто поставляются с отключенным JavaScript.
  • Людям с ограниченными возможностями, которые полагаются на программы чтения с экрана, намного удобнее работать со статическим содержимым.
  • Поисковые системы; хотя мы знаем, что Google анализирует код JavaScript, мы практически не представляем, как работают другие поисковые системы.
  • Легкие устройства с коротким временем автономной работы.
  • Люди, которые хотели бы проанализировать ваш HTML-контент. В Python это заняло бы несколько строк, когда дело доходит до статического HTML, но с основным JavaScript потребовалось бы несколько мегабайт движка JavaScript для возврата контента для анализа.
  • Люди с интернет-соединением, которое в какой-то момент может замедлиться (например, поезд, въезжающий в туннель).

Это место, где вступает в действие рендеринг на стороне сервера. Это прекрасный компромисс между сайтами, отображаемыми на JavaScript, и статическими веб-страницами. SSR позволяет вам предварительно визуализировать ваш JavaScript-контент на сервере , отправить его пользователю, чтобы он мог его увидеть, а когда JavaScript загружается, он повторно использует уже сгенерированную разметку , так как нет необходимости рендерить все заново ( этот процесс называется «гидратацией»). Кроме того, ваши пользователи увидят контент быстрее.

SSR иногда приводит к неожиданным результатам, если ваши интерфейсные алгоритмы полагаются на манипуляции с DOM, поэтому будьте готовы к имитированию некоторых результатов.

Если ваш сервер использует Node.js, все готово. Если это не так, это все еще возможно, хотя иногда это может быть сложно.

Ленивая загрузка изображений

Если вы загружаете много изображений на страницу, загрузка вашего скрипта может быть отложена. Подумайте об отложенной загрузке изображений, чтобы ваш скрипт мог загружаться быстрее. Кроме того, вы можете вставлять низкокачественные версии тех же изображений аналогично Medium.

Переместите тег «сценарий» выше в документе

Может быть, тег «сценарий» с вашим комплектом находится слишком низко в DOM? Перемещение его настолько высоко, насколько это необходимо, иногда может иметь решающее значение.

Отправка чистого кода ES6+ в производство

Современные браузеры поддерживают все спецификации ES6 (возможно, за исключением модульности, которую в любом случае можно легко реализовать). Мы можем создать две конфигурации сборки для сборок ES5 и ES6 соответственно. Сборка ES6 может быть отправлена ​​для выбранных браузеров, а ES5 — для всех остальных. Ваш внутренний сервер может отправить первый или второй пакет в зависимости от пользовательского агента.

Как мы все знаем, наш код ES6 вабелифицирован, чтобы старые браузеры могли его понять, но это не бесплатно. Стоимость транспиляции в ES5 связана с большим количеством полифилов, поэтому простая функция «асинхронного ожидания» требует в 4 раза больше кода после транспиляции.

Тем не менее, часто ваши node_modules занимают большую часть вашего пакета (и вы должны и, вероятно, будете вынуждены в любом случае исключить node_modules из транспиляции), так что, в конце концов, это может не стоить усилий, но это определенно то, что нужно исследовать в ваш случай.

Разделение кода

Разделение кода — один из самых мощных инструментов Webpack. Это позволяет вам определить более одной точки входа для вашего приложения. Есть много случаев, когда это может быть полезно. Например, вам может понадобиться только небольшая часть кода JavaScript для нескольких страниц, которые доступны только незарегистрированным пользователям. Им не нужно будет загружать весь код, так как он вообще не будет использоваться.

Фрагменты интеллектуального кода, сгенерированные Webpack

Если вы полагаетесь на разбиение кода (а часто вы должны это делать) и генерируете фрагменты, иногда вы можете получить слишком много фрагментов в килобайтах, что приведет только к блокировке загрузки. Вы должны указать минимальный размер блока в конфигурации Webpack.

Если у вас много чанков, вы, вероятно, получили повторяющиеся элементы в этих чанках. Чтобы отключить такое поведение, вы должны добавить следующую опцию в конфигурацию Webpack:

оптимизация: {
splitChunks: {
cacheGroups: {
поставщики: ложь,
по умолчанию: ложь,
}
}
}

Кроме того, вы можете решить, что должно попасть в ваши фрагменты. Все, что вам нужно сделать, это добавить
`/* webpackChunkName: “chunkName” */` в ваш динамический импорт, как показано здесь.

Сжимайте файлы .js, если вы еще этого не сделали.

«Gzip» давно поддерживается всеми браузерами. Экономия на размере пакета как можно больше — огромная победа. Это очень простой способ уменьшить размер ваших JS-файлов. Как упоминалось здесь, все это может быть скомпрометировано следующим разговором:

Браузер: Эй, могу я ПОЛУЧИТЬ index.js? Я возьму сжатую версию, если она у вас есть.

Сервер: Позвольте мне найти файл… да, он здесь. А сжатую версию возьмешь? Потрясающий.

Сервер: Хорошо, я нашел index.js (200 OK), архивирую и отправляю.

Браузер: Отлично! Всего 10кб. Разархивирую и покажу пользователю.

Чтобы убедиться, что ваш сервер отправляет файлы «gzip», проверьте заголовок «content-encoding» в файлах, загруженных вашим клиентом.

Оптимизируйте свои пакеты

Мы все любим JavaScript. Тем не менее, это самый требовательный ресурс в Интернете. Часто мы полагаемся на сторонние библиотеки, чтобы ускорить разработку и не изобретать велосипед.
Но иногда мы преувеличиваем количество библиотек.

Установите Webpack Bundle Analyzer и отслеживайте самые тяжелые части вашего приложения. Чтобы привести вам пример, Moment.js весит 65 КБ в минимизированном и сжатом виде, и 75% его веса вызвано огромным количеством локалей, которые он предоставляет. Рассмотрите возможность удаления некоторых (или большинства) локалей из вашей сборки или используйте облегченную альтернативу, такую ​​как «date-fns» или «dayjs».

Заключение

Помните, что если пользователь быстро просматривает ваш контент, он, скорее всего, останется на вашем сайте. В конце концов, всегда полезно использовать такой инструмент, как Lighthouse, чтобы найти другие проблемы, от которых может страдать ваше веб-приложение.

Динамическая загрузка внешнего файла JavaScript или CSS

Динамическая загрузка внешнего Файл JavaScript или CSS

Обычный способ загрузки внешнего JavaScript (например: .js ) и CSS (например: .css ) файлов на странице — вставить ссылку на них в секцию HEAD вашей страницы, например:

   
 

Файлы, названные таким образом, добавляются на страницу по мере их встречаются в источнике страницы или синхронно. По большей части, эта установка прекрасно отвечает нашим потребностям, хотя в мире синхронных Шаблоны проектирования Ajax, возможность также запускать JavaScript/CSS по требованию. становится все более и более удобным. В этом уроке давайте посмотрим, как это делается.

Динамическая загрузка внешних Файлы JavaScript и CSS

Динамическая загрузка файла .

js или .css, в двух словах, означает использование методы DOM, чтобы сначала создать шикарный новый « СЦЕНАРИЙ » или « LINK «, присвойте ему соответствующие атрибуты и, наконец, используйте element.appendChild() , чтобы добавить элемент в нужное место внутри дерево документов. Звучит намного фантастичнее, чем есть на самом деле. Давайте посмотри как все это совпало:

 функция loadjscssfile(имя файла, тип файла){
if (filetype=="js"){ //если имя файла является внешним файлом JavaScript
var fileref=document.createElement('сценарий')
fileref.setAttribute("тип","текст/javascript")
fileref.setAttribute("источник", имя файла)
}
else if (filetype=="css"){ //если имя файла является внешним файлом CSS
var fileref=document.createElement("ссылка")
fileref.setAttribute("отн.", "таблица стилей")
fileref.setAttribute("тип", "текст/css")
fileref.setAttribute("href", имя файла)
}
если (typeof fileref! = "undefined")
document.getElementsByTagName("head")[0].
appendChild(fileref) } loadjscssfile("myscript.js", "js") //динамически загружаем и добавляем этот файл .js loadjscssfile("javascript.php", "js") //динамически загружаем "javascript.php" как файл JavaScript loadjscssfile("mystyle.css", "css") ////динамически загружаем и добавляем этот файл .css
Демо:
  • Загрузить «myscript.js»
  • Загрузить «mystyle.css»
Источник «myscript.js»:

var petname=»Spotty»
alert(«Имя питомца: » + petname)

«mystyle.css» источник:

#demotable td{
цвет фона: светло-желтый;
}

#demotable b{
цвет: синий;
}

Поскольку внешние файлы JavaScript и CSS технически могут заканчиваться любым пользовательское расширение файла (например: « javascript.php «), параметр функции « тип файла » позволяет указать сценарию, какой тип файла следует ожидать перед загрузкой. После что функция предназначена для создания элемент, используя соответствующий DOM-методы, присвойте ему правильные атрибуты и, наконец, добавьте его в конец HEAD раздел. Теперь стоит уточнить, куда добавляется созданный файл:

 document.getElementsByTagName("head")[0].appendChild(fileref) 

Ссылаясь на HEAD элемент страницы сначала, а затем вызов appendChild() , это означает, что вновь созданный элемент добавлен в самый конец тега HEAD. Кроме того, вы должны быть зная, что ни один существующий элемент не пострадает при добавлении нового элемента- то есть, если вы вызовете loadjscssfile("myscript.js", "js") дважды, теперь у вас есть два новых элемента » SCRIPT » оба указывая на тот же файл JavaScript. Это проблематично только с точки зрения эффективности, поскольку вы будете добавлять лишние элементы на странице и использование ненужной памяти браузера в процесс. Простой способ предотвратить добавление одного и того же файла более чем один раз, чтобы отслеживать файлы добавлено loadjscssfile() и загружать файл, только если он новый:

 var filesadded="" // список уже добавленных файлов
функция checkloadjscssfile (имя файла, тип файла) {
если (filesadded.