Около месяца назад мы рассказывали, как создать собственное расширение для браузера своими руками — и там в качестве примера мы решили выбрать столь раздражающую при копировании инфы штуку, как «Источник: ...». Однако потенциал браузерных расширений не ограничивается борьбой с несанкционированным дополнением буфера информацией об источнике. Посему в этот раз мы решили рассказать, как автоматизировать очистку от UTM при копировании ссылок. А в качестве бонуса еще и как добавить свою UTM.
Спешим узбагоить моралистов — никто и никогда не станет оплачивать переход со стороннего сайта лишь потому, что там ваша UTM. В целом UTM больше нужны маркетологам — и то лишь при наличии нескольких РК. Будьте уверены, даже если 100% трафика рекла будет с сайта Б, который внаглую скопипастил у вас контент и не удалил UTM — вам с этого не перепадет ничего. Ибо в реальности трафик один йух отслеживается не по UTM, а по обращениям на уровне сетевого стека — по фактическим TCP/HTTP-запросам, заголовкам Host и Referer, cookies и сессионным токенам, а не по произвольным UTM-параметрам в URL.
Короче, подлянок этим расширением мы не делаем. А вот жизнь людям — упрощаем. Окда? За сим — идем дальше.
Завяжи шнурки перед бегом!
Сразу уточним — это не ссылка ради ссылки. Просто дублировать одну и ту же инфу из статьи в статью было бы тупо. Поэтому из статьи в статью мы будем дублировать призыв прочесть базу вот здесь :D А конкретно — первые три абзаца раздела «Пара минут ликбеза», где мы на пальцах разбираем «и так очевидное», что обязательно нужно сделать перед тем, как начать создавать расширение.
Для чего разбирать очевидное? Для того, что очевидное очевидно лишь после прочтения. А если рандомного читателя взять и посадить кодить, окажется, что очевидное не очевидно, что он не знает, с чего начать, и что он вообще не прогер, и что все слооожнааа. На деле же все изи-пизи и под силу первокласснику (буквально). Просто нужно сесть и продумать каждый шаг — как это сделать, мы там и рассказали.
Как убрать UTM из ссылки при копировании
По аналогии с тем, как это делалось в предыдущей статье, создаем два файла — manifest.json и background.js. Вообще говоря, любое расширение — это всегда файл манифеста, благодаря которому Хром в принце понимает, что перед ним расширение и JS с кодом. Или несколько JS. Или не только JS, но еще и, например, картинка с лого.
Не в курсе, что такое JS? Значит, так и не перешли по ссылке выше… Иначе знали бы, что это javascript. Ну да не суть. Объяснять, как работает javascript мы не станем — ибо не объяснить это словами… Это нужно чувствовать :D А если серьезно, то в объяснениях просто нет смысла. Вы либо уже в теме и поймете без нас…
… Либо не в теме и все равно ничего не поймете. Ну вот распишем мы, что функция cleanUrl принимает объект String, вызывает метод indexOf для поиска первого вхождения подстроки "?utm", возвращающего числовой индекс первого символа или –1 при отсутствии, после чего использует метод slice(startIndex, endIndex) объекта String для создания нового строкового объекта, содержащего подстроку исходного URL от нулевого индекса до найденного индекса. А зачем?
Посему распишем на «понятном»:
Оно ждет, пока вы жмканите в ПКМ-меню на «Copy Clean URL».
Копирует в буфер ссылку со всеми UTM.
Копирует из буфера ссылку со всеми UTM.
Магически убирает из нее ?utm и все, что идет после.
Перезаписывает результат в буфер.
А как именно оно это делает… Ну… Тут или таки учить JS (ну или хотя бы просто основы алгоритмизации), или… магия! :D Впрочем, создание расширений — это тот редкий случай, где глубоко вникать не обязательно. Работает и ладно. Во всяком случае до тех пор, пока вы не пытаетесь это продавать. Но вернемся к нашим баранам расширениям. Почему «ям», а не «ю»? Скоро поймете.
А пока делай раз:
Создаем папку.
В ней создаем файл manifest.json
В него копируем:
{
"manifest_version": 3,
"name": "Copy Clean URL",
"version": "1.0",
"description": "Копирует ссылки и автоматически удаляет любые ?utm и похожие параметры отслеживания, оставляя чистую ссылку.",
"permissions": [
"contextMenus",
"scripting"
],
"background": {
"service_worker": "background.js"
},
"host_permissions": [
"<all_urls>"
],
"author": "Автор расширения"
}
Делай два:
Сохраняем.
В этой же папке создаем файл background.js
В него копируем:
// Срабатывает при установке расширения
chrome.runtime.onInstalled.addListener(() => {
chrome.contextMenus.create({
id: "copy-clean-url",
title: "Copy clean URL", // Текст пункта контекстного меню
contexts: ["link"] // Пункт появляется только на ссылках
});
});
// Функция очистки URL от UTM-параметров
function cleanUrl(url) {
// Находим индекс начала параметра ?utm
const utmIndex = url.indexOf("?utm");
if (utmIndex === -1) {
return url; // Если UTM не найден — возвращаем оригинальный URL
}
return url.slice(0, utmIndex); // Отрезаем всё начиная с ?utm
}
// Обработчик клика по пункту контекстного меню
chrome.contextMenus.onClicked.addListener((info, tab) => {
if (!info.linkUrl || !tab?.id) return; // Проверка на наличие ссылки и таба
const originalUrl = info.linkUrl; // Сохраняем исходную ссылку
const cleanedUrl = cleanUrl(originalUrl); // Получаем очищенную ссылку
// Копируем очищенную ссылку в буфер обмена на вкладке
chrome.scripting.executeScript({
target: { tabId: tab.id },
func: (textToCopy) => { navigator.clipboard.writeText(textToCopy);
},
args: [cleanedUrl]
});
});
Сохраняем.
Делай три:
Открывает Хром, жамкаем «три точки справа вверху».
Затем жамкаем «Расширения».
После чего «Управления расширениями».
Далее слева вверху находим «Загрузить распакованное расширение».
Жмем и выбираем нашу папку.
Тестим.
И видим, что ссылка стала «немного» короче, чем могла бы быть, — все работает.
Закончили упражнение!
Казалось бы, закончили — ну и ладушки. Да только ладушки-оладушки, а само по себе удаление UTM пригодится разве что братишкам-текстоделам. В рамках задач арбитрана, ну или хотя бы веб-мастера, куда актуальнее будет замена UTM на свои. Штош.. Ни слова больше!
Как заменить UTM на свои
Начало схоже с тем, что было ранее.
Создаем папку ДВА (потом объясним).
В ней создаем файл manifest.json
В него копируем:
{
"manifest_version": 3,
"name": "Copy URL + Custom UTM",
"version": "1.0",
"description": "Позволяет быстро копировать любую ссылку и добавлять к ней кастомные UTM-метки для аналитики, оставляя ссылку чистой и удобной для обмена.",
"permissions": [
"contextMenus",
"scripting",
"storage"
],
"background": {
"service_worker": "background.js"
},
"host_permissions": [
"<all_urls>"
],
"action": {
"default_popup": "popup.html",
"default_title": "Copy URL + Custom UTM"
},
"author": "Автор расширения"
}
Сохраняем.
В этой же папке создаем файл background.js
В него копируем:
// Срабатывает при установке расширения
chrome.runtime.onInstalled.addListener(() => {
chrome.contextMenus.create({
id: "copy-utm-url", // Уникальный идентификатор пункта меню
title: "Copy URL + custom UTM", // Текст пункта контекстного меню
contexts: ["link"] // Появляется только на ссылках
});
});
// Функция очистки URL от стандартных UTM-параметров
function cleanUrl(url) {
const utmIndex = url.indexOf("?utm"); // Находим начало UTM-параметров
return utmIndex === -1 ? url : url.slice(0, utmIndex);
}
// Обработчик клика по пункту контекстного меню
chrome.contextMenus.onClicked.addListener((info, tab) => {
if (!info.linkUrl || !tab?.id) return; // Проверка наличия ссылки и активного таба
// Получаем пользовательский UTM из локального хранилища
chrome.storage.local.get(["customUTM"], (data) => {
const cleanedUrl = cleanUrl(info.linkUrl); // Очищаем ссылку от ?utm
const finalUrl = data.customUTM // Если пользователь добавил кастомный UTM
? cleanedUrl + data.customUTM // добавляем его
: cleanedUrl; // иначе оставляем чистый URL
// Копируем итоговый URL в буфер обмена
chrome.scripting.executeScript({
target: { tabId: tab.id },
func: (textToCopy) => {
navigator.clipboard.writeText(textToCopy);
},
args: [finalUrl]
});
});
});
Сохраняем.
В этой же папке создаем файл popup.html
В него копируем:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Custom UTM</title>
</head>
<body style="width:300px; padding:10px; font-family:sans-serif; box-sizing:border-box;">
<h4 style="margin:0 0 10px 0;">Custom UTM</h4>
<input
id="utm"
type="text"
placeholder="?utm_source=mytest&utm_campaign=article"
autocomplete="off"
spellcheck="false"
style="width:100%; box-sizing:border-box; padding:4px;"
/>
<button
id="save"
type="button"
style="margin-top:5px; width:100%; padding:4px;"
>
Save
</button>
<script src="popup.js"></script>
</body>
</html>
Сохраняем.
В этой же папке создаем файл popup.js
В него копируем:
// Получаем элементы из DOM
const utmInput = document.getElementById("utm");
const saveButton = document.getElementById("save");
// При загрузке попапа подставляем ранее сохранённый UTM, если он есть
chrome.storage.local.get(["customUTM"], (result) => {
if (result.customUTM) {
utmInput.value = result.customUTM;
}
});
// Обработчик клика по кнопке "Save"
saveButton.addEventListener("click", () => {
const trimmedValue = utmInput.value.trim(); // Обрезаем лишние пробелы
chrome.storage.local.set({ customUTM: trimmedValue }, () => {
// Можно добавить уведомление или консоль для отладки
console.log("Custom UTM сохранён:", trimmedValue);
});
});
Сохраняем.
И, разумеется, тестируем! (Предварительно не забыв загрузить расширение в браузер.)
Жамкаем на иконку расширений.
Находим наше.
Вставляем свою UTM. Допустим, мы теперь не trafficcardinal, а google
Сейвим путем жмаканья на Save.
Видим, что теперь там наша UTM.
То бишь — все работает.
Почему папка ДВА?
Патамушта :D Ладно, поясняем. Но сначала «флешбэк» для тех, кто уже и забыл про папку…
Так вот, создание отдельной папки, а соответственно и расширения, обусловлено тем, что Хром группирует кнопки контекстного меню по расширениям. И если бы мы сделали не два расширения, а одно, то было бы не «удобное вот так»:
А «неудобное вот так»:
На самом деле то, какой вариант удобнее, вопрос дискуссионный. Ибо одно дело — две кнопки, а другое — двадцать две. Но в нашем примере их было две, а посему, руководствуясь логикой «меньше кликов — больше профит», автором было принято решение сделать два расширения вместо одного.
По-хорошему же заспамливать контекстное меню не надо, и лучше кнопки таки группировать. Но так как кнопки лишь две, то, как ни крути, удобнее их вынести непосредственно в меню, чтобы не тратить каждый раз время на еще один клик.
Саммари
Как видите, автоматизировать удаление UTM или даже их переподстановку на свои собственные не так уж и сложно. А ведь шалости с буфером обмена — это лишь верхушка айсберга! Впрочем, это уже совсем другая история… Или стории… И мы обязательно их расскажем. Но потом. А пока подписывайтесь на нашу Телегу, чтобы не пропустить новые гайды!