Всем привет, меня зовут Вячеслав — я пользователь ispmanager и руководитель отдела маркетинга. Не знаю, зачем вам нужны Google-карты, «Яндекс Музыка» или Spotify прямо в панели — если вы знаете зачем, пишите в комментариях. А я пока расскажу, как затащить iframe в ispmanager. Разберу два варианта, как это сделать, на примере интеграции с «Яндекс Метрикой» — простой и со звездочкой.
Поехали →
Зачем нужен iframe в ispmanager
В ispmanager можно писать модули, но иногда хочется расширить их функциональность или настроить под конкретную задачу. Для этого можно использовать iframe — HTML-элемент, чтобы вставлять один сайт внутрь другого. Способ упрощает разработку и быстро расширяет функциональность, а пользователей не приходится перенаправлять на другие сайты.
Как обычно выглядит iframe:
<iframe src="URL_встраиваемой_страницы"></iframe>
Основные атрибуты:
src: этот атрибут определяет URL веб-страницы или внешнего ресурса, который загружаем внутрь <iframe>.
width и height: определяют ширину и высоту iframe. Можно задать размеры в пикселях (px) или процентах (%).
Например, можно встроить видео с YouTube. Я указал URL видео в атрибуте src и задал размеры iframe в пикселях:
<iframe src="https://www.youtube.com/embed/dQw4w9WgXcQ" width="560" height="315"></iframe>
Сложный путь — ручная установка
Добавляем новый пункт в меню ispmanager.
Интегрируем «Яндекс Метрику» в ispmanager.
Выгружаем готовый отчет из «Яндекс Метрики» с помощью Python.
Запускаем скрипт на Python в ispmanager.
Добавляем новый пункт в меню ispmanager
Этот блок — подготовка к интеграции с «Яндекс Метрикой». Чтобы в меню появился кастомный раздел, добавляем несколько файлов в разные директории — здесь опираюсь на документацию продукта.
Как добавить новый пункт в меню ispmanager:
В папке
/usr/local/mgr5/etc/xml
создаем файлispmgr_mod_testframe.xml
с содержимым:
<?xml version="1.0" encoding="UTF-8"?>
<mgrdata>
<mainmenu level="admin+">
<modernmenu>
<node name="my_group">
<node name="testframe" />
</node>
</modernmenu>
</mainmenu>
<handler name="testframe.sh" type="xml">
<func name="testframe" />
</handler>
<lang name="ru">
<messages name="desktop">
<msg name="modernmenu_my_group">Test</msg>
<msg name="modernmenu_testframe">Test Form Frame</msg>
</messages>
</lang>
</mgrdata>
Если вам нужны пункты на нескольких языках, блок <lang name="ru">
нужно продублировать. Для этого поменяйте ru
на нужную локаль.
В папке
/usr/local/mgr5/addon/
создаем файлtestframe.sh
. Это простейший обработчик, он возвращает статичное содержимое следующего файла, который мы создадим.
Добавляем в него код:
#!/bin/bash
cat /usr/local/mgr5/addon/testframe.xml
-
Выдаем файлу права для обработчиков плагинов с помощью команды в shell-клиенте:
chmod 755 /usr/local/mgr5/addon/testframe.sh
В папке
/usr/local/mgr5/addon/
создаем файлtestframe.xml
В этом файле будет содержаться самое важное — информация о том, что будет показываться во фрейме.
Добавляем код:
<?xml version="1.0" encoding="UTF-8"?>
<doc lang="ru" func="testframe" binary="/ispmgr">
<metadata name="testframe" type="form" mgr="ispmgr">
<form>
<field name="frame" fullwidth="yes">
<frame name="roundcubeframe" forcetheme="yes" fullpage="yes" keepalive="yes" />
</field>
</form>
</metadata>
<messages name="testframe" checked="6b49a92f5cc5153c76b78446d0d74eb4">
<msg name="title">Test Form Frame</msg>
<msg name="frame">Frame</msg>
</messages>
<roundcubeframe>https://x.x.x.x:1501/roundcube/?_task=mail&_mbox=INBOX</roundcubeframe>
</doc>
Теперь можно подтянуть сюда нужный вам адрес вместо roundcubeframe. Для примера я возьму «Яндекс».
Перезагружаем панель командой
killall core
в shell-клиенте или с помощью контекстной кнопки на дашборде. Так я получил карту прямо в ispmanager и теперь могу узнать, где пробки прямо сейчас =)
Интегрируем «Яндекс Метрику» в ispmanager
Интегрируем «Яндекс Метрику» по API через Google Sheets. Вставка метрики через iframe технически запрещена. Поэтому мы выгрузим данные по API и протолкнем их в продукт через Google Sheets: таблицы без проблем можно вставить через iframe.
Как интегрировать «Яндекс Метрику» через Google Sheets:
Формируем графики в Google Sheets. Можно вставлять их отдельно, без остальной таблицы. Для этого в настройках публикации выберите «График».
Встраиваем Google Sheets через URL: «Файл» → «Поделиться» → «Опубликовать в сети» → «Link».
Google-файлы, встроенные через iframe, не индексируются поисковиками, потому что доступ к файлу классическими методами закрыт. |
Вставляем полученный адрес в файле testframe.xml
<roundcubeframe>https://docs.google.com/spreadsheets/d/e/УНИКАЛЬНЫЙБЛОК/pubchart?oid=&format=interactive</roundcubeframe>
Выгружаем готовый отчет из «Яндекс Метрики» с помощью Python
Получаем OAuth-токен в «Яндексе». Вот последовательность действий:
Переходим на страницу создания внешних приложений.
Заполняем «Название», если авторизация будет только по API.
Пропускаем раздел «Иконка».
Указываем «web-сервисы» в разделе «Платформа приложения».
Прописываем адрес https://oauth.yandex.ru/verification_code в поле «redirect url».
Указываем metrika:read и metrika:write в поле «Доступ к данным» для простейшей работы со счетчиками. Эти параметры позволяют делать всё, кроме загрузки расходов в счетчики, передачи пользовательских параметров и загрузки офлайн-данных. Как включить эти возможности — в документации.
Нажимаем «Создать приложение». Откроется экран — находим поле «ClientID» и копируем его.
Вставляем «ClientID» в ссылку вида:
https://oauth.yandex.ru/authorize?response_type=token&client_id=<ВАШ ID>
Получаем токен.
Как он выглядит:
Для дальнейшей работы нам понадобятся библиотеки Python: ▫ requests, ▫ datetime, ▫ time, ▫ gspread. |
Приведу пример одного из запросов. Допустим, нужна сводка источников за последний день, и токен мы уже получили.
Передаем запрос в счетчик метрики с нужными параметрами:
API_token = 'OAuth {Токен}'
counter_id = '{ID счетчика метрики}'
api_metrika_url = 'https://api-metrika.yandex.net/stat/v1/data/bytime'
params = {
'date1': {Дата от},
'date2': {Дата до},
'group' : 'day', #Группировка по дням
'dimensions' : 'ym:s:lastsignTrafficSource', #Атрибуция по последнему значимому источнику
'ids' : counter_id,
'metrics': 'ym:s:visits', #выгружаем визиты
}
res = requests.get(api_metrika_url, params = params, headers={'Authorization': API_token})
В ответе получаем последовательность, в которой скрываются нужные данные:
{
"query":
{
"ids":[IDсчетчика],
"dimensions":["ym:s:lastsignTrafficSource"],
"metrics":["ym:s:visits"],
"sort":["-ym:s:visits"],
"date1":"2024-03-03","date2":"2024-03-03",
"group":"day",
"auto_group_size":"1",
"attr_name":"",
"quantile":"50",
"offline_window":"21",
"attribution":"LastSign",
"currency":"RUB",
"adfox_event_id":"0",
"auto_group_type":"day"
},
"Data":
[
{"dimensions":[{"icon_id":"2","icon_type":"traffic-source","name":"Search engine traffic","id":"organic"}],"metrics":[[ЗНАЧЕНИЕ.0]]},
{"dimensions":[{"icon_id":"0","icon_type":"traffic-source","name":"Direct traffic","id":"direct"}],"metrics":[[ЗНАЧЕНИЕ.0]]},
{"dimensions":[{"icon_id":"1","icon_type":"traffic-source","name":"Link traffic","id":"referral"}],"metrics":[[ЗНАЧЕНИЕ.0]]},
{"dimensions":[{"icon_id":"3","icon_type":"traffic-source","name":"Ad traffic","id":"ad"}],"metrics":[[ЗНАЧЕНИЕ.0]]},
{"dimensions":[{"icon_id":"-1","icon_type":"traffic-source","name":"Internal traffic","id":"internal"}],"metrics":[[25.0]]},
{"dimensions":[{"icon_id":"7","icon_type":"traffic-source","name":"Mailing traffic","id":"email"}],"metrics":[[ЗНАЧЕНИЕ.0]]},
{"dimensions":[{"icon_id":"8","icon_type":"traffic-source","name":"Social network traffic","id":"social"}],"metrics":[[ЗНАЧЕНИЕ.0]]}
],
"total_rows":1,
"total_rows_rounded":false,
"sampled":false,
"contains_sensitive_data":false,
"sample_share":1.0,
"sample_size":ЗНАЧЕНИЕ,
"sample_space":ЗНАЧЕНИЕ,
"data_lag":0,
"totals":[[ЗНАЧЕНИЕ.0]],
"time_intervals":[["2024-03-03","2024-03-03"]]
}
Чтобы с ней дальше работать, нужно превратить последовательность в словарь и выделить только нужную информацию: это все, что находится в квадратных скобках после «Data».
json_res = res.json()
data = json_res["data"]
Далее нужно обработать полученную информацию и передать в таблицу.
Нюансы:
Сопоставить источник и объем у меня сразу не получилось, поэтому пришлось сделать техническую страницу, где будут сверяться данные. В моем случае — tech.
Судя по запросу, в начале всегда идет источник с наибольшим объемом трафика, а значит, если один из источников вырастет, его порядковый номер в полученном ответе изменится. Если не предусмотреть обработку этого случая, мы можем получить данные из одного источника в другом, и в результате информация будет дублироваться.
Авторизуемся для работы с Google Sheets. Мне потребуются параметры gspread.service_account и gs.open_by_key. В статье «Как настроить сбор статистики и автоматическое отключение пользователей WireGuard» даю подробную инструкцию, как получить эти параметры в Google cloud console.
gs = gspread.service_account(filename='ПУТЬ ДО ФАЙЛА/yandex-ispmgr.json')
sh = gs.open_by_key('КЛЮЧ')
Обрабатываем полученную информацию — обращаемся к словарям dimensions и metrics:
a = 2 #строчка
b = 1 #столбик
for metrics in data:
dimensions = metrics["dimensions"]
for id in dimensions:
name = id["name"]
worksheet = sh.worksheet("tech")#подключаемся к технической таблице
worksheet = worksheet.update_cell(a, b, name)
a += 1
Вот так я добавил в техническую страницу информацию об источниках трафика в порядке их получения в запросе.
a = 2
for dimensions in data:
metrics = dimensions["metrics"]
for id in metrics:
b = current_date.day+1
for key in id:
worksheet = sh.worksheet("tech")
worksheet = worksheet.update_cell(a, b, key)
b += 1
a += 1
Эта часть кода помогла нам передать информацию об объеме трафика в порядке его получения в запросе. А значит, теперь у нас готовы строчки для сопоставления. Получаю данные из текущей таблицы и технической, сравниваю, добавляю новые данные в пункты в актуальной таблице. В моем случае актуальная — current
.
worksheet = sh.worksheet("current")
gs_val_current = worksheet.col_values(1)
gs_val_current.remove("Current month")
i2 = 0
a = 2
for word in gs_val_current:
worksheet = sh.worksheet("tech")
gs_val_tech = worksheet.col_values(1)
i = 0
for word in gs_val_tech:
if gs_val_tech[i] == gs_val_current[i2]:
a = i+1
gs_val_transfer = worksheet.cell(a, 2).value
worksheet = sh.worksheet("current")
b = current_date.day
a = i2+2
worksheet = worksheet.update_cell(a, b, gs_val_transfer)
i += 1
i2 += 1
На практике можно брать разные периоды, но в рамках статьи я использовал информацию за предыдущий месяц.
Запускаем скрипт на Python в ispmanager
Загружаем файл скрипта и yandex-ispmgr.json через файловый менеджер, yandex-ispmgr.json помогает подключиться к Google Sheets.
Заходим в «Конфигурацию ПО» → выделяем Python → «Установить».
-
Переходим в shell-клиент и прописываем команды:
/opt/ispmanager/python3.11/bin/python3.11 -m venv <имя-вашего-окружения>
-
Активируем окружение:
source <имя-вашего-окружения>/bin/activate
-
Устанавливаем библиотеки через pip или pip3 на выбор:
<имя-вашего-окружения>/bin/python3.11 pip3 install <Имя-вашей-библиотеки>
Загружаем файл скрипта на сервер.
-
Тестово активируем скрипт:
<имя-вашего-окружения>/bin/python3.11 <путь до файла>
Если сделали всё правильно, запуск пройдет удачно: в таблице появится статистика, а в ispmanager — графики.
-
Переходим в cron. Вводим команду в формате:
<имя-вашего-окружения>/bin/python3.11 <путь до файла>
Теперь каждый день добавляется информация за прошедший.
Простая установка — используем скрипт
Я написал скрипт установки iframe в ispmanager — подойдет тем, кому лень писать код руками или хочется поставить iframe для интеграции с другими сайтами. С помощью этого файла вы сможете установить модуль «Яндекс Метрики» без знания кода — работать он будет через iframe.
После установки нужно только добавить токен из Яндекса, id вашего счетчика в файл скрипта, загрузить файл для работы с Google Sheets и создать там таблицу.
Как использовать скрипт:
Заходим в «Конфигурацию ПО» → выделяем «Python» → «Установить».
-
Переходим в shell-клиент и прописываем команды:
/opt/ispmanager/python3.11/bin/python3.11 -m venv <имя-вашего-окружения>
-
Активируем окружение:
source <имя-вашего-окружения>/bin/activate
-
Скачиваем лаунчер с помощью команды:
wget https://raw.githubusercontent.com/AveTavern/ispmanager-iframe-launcher/Production/launcher.py
5. Запускаем скрипт с помощью команды <имя_вашего_окружения>/bin/python3.11 /USERNAME/launcher.py
и следуем инструкциям на экране.
Если хотите изучить вопрос подробнее — держите ссылку на репозиторий.
Как работает интеграция «Яндекс Метрики» и ispmanager
Скрипт по cron авторизуется в «Яндекс Метрике» и скачивает оттуда данные.
Данные фильтруются и передаются в Google Sheets, где сопоставляются источники, отрисовываются графики и складируется информация.
Iframe, полученный из Google Sheets, подтягивается в ispmanager.
Пока я не придумал, что еще можно затащить в iframe. Если у вас есть мысли, как можно доработать модуль или идеи, где еще пригодится iframe, — пишите, обсудим в комментариях.