{"id":18376781,"url":"https://github.com/hcodes/metrika-js-errors","last_synced_at":"2025-08-23T19:36:47.923Z","repository":{"id":66243803,"uuid":"84739198","full_name":"hcodes/metrika-js-errors","owner":"hcodes","description":"Отслеживание js-ошибок с помощью Метрики","archived":false,"fork":false,"pushed_at":"2017-03-23T07:09:48.000Z","size":310,"stargazers_count":34,"open_issues_count":0,"forks_count":6,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-22T06:51:14.295Z","etag":null,"topics":["analytics","error-monitoring","js","vanilla-js","yandex","yandex-metrika"],"latest_commit_sha":null,"homepage":"https://habrahabr.ru/post/324366/","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hcodes.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-03-12T16:13:59.000Z","updated_at":"2024-01-12T20:07:36.000Z","dependencies_parsed_at":null,"dependency_job_id":"c6de29bc-b4dd-4e83-bf33-757f7c589591","html_url":"https://github.com/hcodes/metrika-js-errors","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hcodes%2Fmetrika-js-errors","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hcodes%2Fmetrika-js-errors/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hcodes%2Fmetrika-js-errors/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hcodes%2Fmetrika-js-errors/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hcodes","download_url":"https://codeload.github.com/hcodes/metrika-js-errors/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247547545,"owners_count":20956572,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["analytics","error-monitoring","js","vanilla-js","yandex","yandex-metrika"],"created_at":"2024-11-06T00:24:44.995Z","updated_at":"2025-04-06T20:31:34.997Z","avatar_url":"https://github.com/hcodes.png","language":"HTML","readme":"# Отслеживание js-ошибок с помощью Метрики\nИспользование системы отслеживания js-ошибок трудно переоценить. Даже на покрытом тестами сайте возникают js-ошибки, важно их найти и починить. Расскажу как искал подходящее решение.\n\u003chabracut/\u003e\n\nСуществует три вида систем отслеживания js-ошибок.\n\n### Первый вид\nСамописная система. Добавляем компактный js-код на сайт:\n```js\nwindow.onerror = function(msg, file, line, col) {\n    new Image().src = '/jserrors/?msg=' + msg + ...;\n}\n```\nДелаем «ручку» для сохранения ошибок, парсим логи.\nВ лучшем случае, пишем свой интерфейс для анализа ошибок.\nПотом занимаемся доработкой и поддержкой.\n\n### Второй вид\nПлатный сервис с расширенными возможностями, но с ограничениями, например, на количество js-ошибок в день или месяц. На любой сайт поставить эту систему не получится, придётся каждый раз выбирать какой из ваших сайтов «достоин» платного сервиса. И не забывать оплачивать услуги.\n\nНужно будет добавить на сайт внешний скрипт, который отрицательно повлияет на скорость загрузки вашего сайта.\n\n### Третий вид\nИспользовать для сбора ошибок систему аналитики, для этого необходимо установить на сайт её полноценный код отслеживания.\n\nТак как код отслеживания загружается асинхронно, то отправка ошибок будет доступна только после его загрузки. У данной системы должны быть отчёты, которые можно самостоятельно формировать.\n\n### Решение\nОбъединим первый и третий вид. Ошибки будем вручную отправлять в [Яндекс.Метрику](https://metrika.yandex.ru) с помощью компактного js-кода. В Метрике есть необходимые отчёты и инструменты для анализа данных, нет особых ограничений на количество счётчиков и собираемых данных, и она бесплатна.\n\nДля сбора ошибок подойдёт отчёт «[Параметры визитов](https://yandex.ru/support/metrika/reports/visit-params.xml)».\n\n1. [Заведём](https://metrika.yandex.ru/add) отдельный счётчик.\n\n2. Добавим на страницу **перед всеми скриптами** компактный код:\n```html\n\u003cscript\u003e\n    // Не более 320 байт после минификации.\n    window.onerror = function(msg, file, line, col, err) {\n        // Отсекаем совсем старые браузеры.\n        if (!window.JSON) { return; }\n\n        var counterId = 12345, // Ваш номер счётчика Метрики.\n            siteInfo = {},\n            pointer = siteInfo;\n            // Список параметров визитов.\n            path = [\n                'JS errors', // 1 уровень\n                msg, // 2 уровень\n                err \u0026\u0026 err.stack || (file + ':' + line + ':' + col) // 3 уровень\n                // Не хватает параметров? Добавьте ещё!\n            ];\n\n        // Преобразуем параметры из плоского в древовидный вид для отчёта.\n        for (var i = 0; i \u003c path.length - 1; i++) {\n            var item = path[i];\n            pointer[item] = {};\n            pointer = pointer[item];\n        }\n\n        pointer[path[i]] = 1;\n\n        new Image().src = 'https://mc.yandex.ru/watch/' + counterId +\n            '/?site-info=' + encodeURIComponent(JSON.stringify(siteInfo))\n            '\u0026rn=' + Math.random();\n    };\n\u003c/script\u003e\n```\n\n3. Не забываем указать в коде свой номер счётчика (counterId).\n\n4. Получаем примерно [такой отчёт](https://metrika.yandex.ru/stat/user_vars?group=dekaminute\u0026chart_type=pie\u0026period=2017-03-12%3A2017-03-12\u0026id=43395579):\n\n\u003cimg src=\"https://raw.githubusercontent.com/hcodes/metrika-js-errors/master/screenshots/1.png\" /\u003e\n\nСтруктуру и порядок параметров в отчёте можно менять на лету, а также добавлять новые параметры.\nДавайте с помощью кнопки «Группировки» добавим [браузер и ОС](https://metrika.yandex.ru/stat/user_vars?selected_rows=yZkKR9\u0026chart_type=pie\u0026period=2017-03-12%3A2017-03-12\u0026metrics=ym%3As%3Avisits%2Cym%3As%3AsumParams\u0026dimensions=ym%3As%3AparamsLevel1%2Cym%3As%3AoperatingSystemRoot%2Cym%3As%3Abrowser%2Cym%3As%3AparamsLevel2%2Cym%3As%3AparamsLevel3%2Cym%3As%3AparamsLevel4%2Cym%3As%3AparamsLevel5\u0026id=43395579) в отчёт.\n\u003cimg src=\"https://raw.githubusercontent.com/hcodes/metrika-js-errors/master/screenshots/2.png\" /\u003e\n\n\n\u003cimg src=\"https://raw.githubusercontent.com/hcodes/metrika-js-errors/master/screenshots/3.png\" /\u003e\n\nИ ещё один момент, если скрипты на сайте загружаются с другого домена (CDN), то в отчёте, скорее всего, будут видны сообщения вида «Script error» и без стека. Чтобы вернуть сообщениям нормальный вид, необходимо добавить к скриптам атрибут `crossorigin=\"anonymous\"` и HTTP-заголовок `Access-Control-Allow-Origin:\"*\"`.\n```html\n\u003cscript src=\"https://mycdn.com/folder/file.js\" crossorigin=\"anonymous\"\u003e\u003c/script\u003e\n```\n\nПостепенно в отчёте будут появляться ошибки от расширений браузеров, вирусов и внешних скриптов (рекламных систем, кнопок социальных сетей и пр.). Чтобы отделить эти ошибки, добавим проверку домена у скриптов с помощью регулярного выражения.\n\nДополнительно добавим ограничение на собираемое количество ошибок (не более 5) на странице. Например, однотипные ошибки, возникающие при движении мышки, могут создать сотни запросов в Метрику.\n\nВ современных браузерах данные будем отправлять через `sendBeacon`.\n\n```html\n\u003cscript\u003e\nwindow.onerror = function handler(msg, file, line, col, err) {\n    if (!window.JSON || handler.count \u003e 5) { return; }\n\n    var counterId = 12345, // Ваш номер счётчика Метрики.\n        siteInfo = {},\n        pointer = siteInfo,\n        stack = err \u0026\u0026 err.stack,\n        path = [\n            // Укажите в регулярном выражении домены, с которых загружаются ваши скрипты и сайт.\n            'JS ' + (!file || /mysite\\.ru|cdn\\.com/.test(file) ? 'in' : 'ex') + 'ternal errors',\n            'message: ' + msg,\n            stack ?\n                'stack: ' + stack :\n                (file ? 'file: ' + file + ':' + line + ':' + col : 'nofile'),\n            'href: ' + location.href\n        ];\n\n    for (var i = 0; i \u003c path.length - 1; i++) {\n        var item = path[i];\n        pointer[item] = {};\n        pointer = pointer[item];\n    }\n\n    pointer[path[i]] = 1;\n\n    var url = 'https://mc.yandex.ru/watch/' + counterId + '/' +\n            '?site-info=' + encodeURIComponent(JSON.stringify(siteInfo)) +\n            '\u0026rn=' + Math.random();\n\n    if (typeof navigator.sendBeacon === 'function') {\n        navigator.sendBeacon(url, ' ');\n    } else {\n        new Image().src = url;\n    }\n\n    if (handler.count) {\n        handler.count++;\n    } else {\n        handler.count = 1;\n    }\n};\n\u003c/script\u003e\n```\n\nИ ещё, данные по ошибкам можно получить с помощью [API](https://tech.yandex.ru/metrika/) и сделать с ними всё что угодно.\n\nНе забудьте добавить ссылки на отчёты по ошибкам в свою документацию на видное место.\nИ дать [доступ](https://yandex.ru/support/metrika/general/access.xml) к отчётам остальным разработчикам из группы, чтобы исправление ошибок превратилось в соревнование :)\n\nСсылки:\n- [GitHub](https://github.com/hcodes/metrika-js-errors/)\n- Отчёт «[Параметры визитов](https://yandex.ru/support/metrika/reports/visit-params.xml)»\n- [Пример отчёта](https://metrika.yandex.ru/stat/user_vars?selected_rows=yZkKR9\u0026chart_type=pie\u0026period=2017-03-12%3A2017-03-12\u0026metrics=ym%3As%3Avisits%2Cym%3As%3AsumParams\u0026dimensions=ym%3As%3AparamsLevel1%2Cym%3As%3AoperatingSystemRoot%2Cym%3As%3Abrowser%2Cym%3As%3AparamsLevel2%2Cym%3As%3AparamsLevel3%2Cym%3As%3AparamsLevel4%2Cym%3As%3AparamsLevel5\u0026id=43395579) в Метрике\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhcodes%2Fmetrika-js-errors","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhcodes%2Fmetrika-js-errors","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhcodes%2Fmetrika-js-errors/lists"}