feat(utm): propagate join focus mode
This commit is contained in:
1 parent
dfbb086e2b
commit
9835bb0ef8
4 files changed
+83
-11
No files matched your search
@@ -18,8 +18,11 @@
|
|||||||
- `rnd` — случайное значение по весам (`weights`), так делится трафик между вариантами;
|
- `rnd` — случайное значение по весам (`weights`), так делится трафик между вариантами;
|
||||||
- неизвестное значение отбрасывается, отсутствующее — заменяется на `default`.
|
- неизвестное значение отбрасывается, отсутствующее — заменяется на `default`.
|
||||||
|
|
||||||
Ненастроенные параметры (`utm_source`, `keyword`, `subid` и любые другие) проходят как есть. Все метки уходят дальше
|
Ненастроенные параметры (`utm_source`, `keyword`, `subid` и любые другие) проходят как есть. Перед переходом
|
||||||
в адрес сайта: сайт сохраняет их на воронку и шлёт в Keitaro.
|
Preland всегда формирует полный resolved-набор своих восьми меток: явное допустимое значение остаётся, `rnd`
|
||||||
|
разрешается по весам, отсутствующее получает `default`. Вместе с внешними рекламными параметрами этот набор
|
||||||
|
уходит в `claim`, а затем сайт переносит его в `upscale`; ни один из восьми параметров не должен пропадать только
|
||||||
|
потому, что был назначен default.
|
||||||
|
|
||||||
| Метка | Что задаёт | Где |
|
| Метка | Что задаёт | Где |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@@ -30,6 +33,7 @@
|
|||||||
| `bchoice` | попап выбора банка (`a` — показать) | сайт, оплата (#44) |
|
| `bchoice` | попап выбора банка (`a` — показать) | сайт, оплата (#44) |
|
||||||
| `chb` | галочки согласия на странице оплаты (`no` — не обязательны) | сайт, оплата |
|
| `chb` | галочки согласия на странице оплаты (`no` — не обязательны) | сайт, оплата |
|
||||||
| `tp` | группа тарифов | сайт, cpanel «Группы тарифов (tp)» |
|
| `tp` | группа тарифов | сайт, cpanel «Группы тарифов (tp)» |
|
||||||
|
| `focus` | первоначальная область лупы Join: `center`/`face` | сайт, cpanel после `tp` |
|
||||||
|
|
||||||
### Загрузка и переход на сайт
|
### Загрузка и переход на сайт
|
||||||
|
|
||||||
@@ -61,7 +65,7 @@
|
|||||||
| `requisites.html` | реквизиты для подвала (HTML), если в `config.json` нет `requisites`. Без обоих — **заглушка «ИП Иванов Иван Иванович»** из `template.php` |
|
| `requisites.html` | реквизиты для подвала (HTML), если в `config.json` нет `requisites`. Без обоих — **заглушка «ИП Иванов Иван Иванович»** из `template.php` |
|
||||||
| `images/`, `fonts/`, `favicon/`, `*.css` | статика; `style.min.css` встраивается в страницу |
|
| `images/`, `fonts/`, `favicon/`, `*.css` | статика; `style.min.css` встраивается в страницу |
|
||||||
| `.htaccess` | только сроки кэширования статики (Apache) |
|
| `.htaccess` | только сроки кэширования статики (Apache) |
|
||||||
| `config.json` | единственный версионируемый рабочий конфиг всех прилендов: точная проверенная конфигурация stage `zoomstage.online`; каждый deploy доставляет его на целевой хост |
|
| `config.json` | зафиксированный Git-снимок актуального stage-конфига; runtime-файл хоста является источником истины и обычным deploy не заменяется |
|
||||||
|
|
||||||
### `config.json`
|
### `config.json`
|
||||||
|
|
||||||
@@ -87,10 +91,10 @@
|
|||||||
git clone http://git.dira89kv.beget.tech:3000/anton/preland.git && cd preland
|
git clone http://git.dira89kv.beget.tech:3000/anton/preland.git && cd preland
|
||||||
# дальше — загрузка на хостинг: rsync/scp по SSH или FTP-клиент
|
# дальше — загрузка на хостинг: rsync/scp по SSH или FTP-клиент
|
||||||
```
|
```
|
||||||
3. **Конфиг и реквизиты.** Рабочий `config.json` уже лежит в репозитории и обязателен к доставке на каждый
|
3. **Конфиг и реквизиты.** Runtime `config.json` создаётся при первичной настройке хоста и не заменяется
|
||||||
приленд. Его не заменяют локальным вариантом и не исключают из синхронизации. Реквизиты задаются ключом
|
обычной синхронизацией. Менять в нём можно только ключи, явно согласованные в задаче; после такого выпуска
|
||||||
`requisites` в нём либо runtime-файлом `requisites.html`. 2026-10-05 конфиг пропал после заливки,
|
актуальный stage-снимок фиксируется в Git. Реквизиты задаются ключом `requisites` либо runtime-файлом
|
||||||
и преленд слал загрузку на собственный домен; это больше не допускается.
|
`requisites.html`.
|
||||||
4. **nginx без Apache** (если хостинг не обрабатывает `.htaccess`):
|
4. **nginx без Apache** (если хостинг не обрабатывает `.htaccess`):
|
||||||
```nginx
|
```nginx
|
||||||
server {
|
server {
|
||||||
@@ -137,12 +141,13 @@
|
|||||||
1. Домен и HTTPS — как в «Деплой на произвольный домен», шаг 1.
|
1. Домен и HTTPS — как в «Деплой на произвольный домен», шаг 1.
|
||||||
2. Секреты `<ПРЕФИКС>_FTP_HOST`, `<ПРЕФИКС>_FTP_USER`, `<ПРЕФИКС>_FTP_PASS` (Gitea → настройки репозитория →
|
2. Секреты `<ПРЕФИКС>_FTP_HOST`, `<ПРЕФИКС>_FTP_USER`, `<ПРЕФИКС>_FTP_PASS` (Gitea → настройки репозитория →
|
||||||
Actions → секреты; порт 21, FTP с TLS). В коде реквизитов нет.
|
Actions → секреты; порт 21, FTP с TLS). В коде реквизитов нет.
|
||||||
3. Никаких ручных конфигов не создавать: единственный `config.json` приезжает вместе с кодом.
|
3. Один раз создать runtime `config.json` с нужными значениями: последующие обычные deploy его не перезапишут.
|
||||||
4. Запись в `matrix` — коммит в `main`, автодеплой выкатит все цели вместе с конфигом.
|
4. Запись в `matrix` — коммит в `main`, автодеплой выкатит код на все цели, сохраняя их конфиги.
|
||||||
|
|
||||||
**Что заливается.** Каждый deploy получает файлы репозитория (`git ls-files`), кроме служебных
|
**Что заливается.** Каждый deploy получает файлы репозитория (`git ls-files`), кроме служебных
|
||||||
(`.gitea/`, `README.md`, `.gitignore`) и живущего на хостинге `requisites.html`. Единственный
|
(`.gitea/`, `README.md`, `.gitignore`), а также живущих на хостинге `requisites.html` и `config.json`.
|
||||||
версионируемый `config.json` всегда доставляется вместе с кодом.
|
Перед разрешённым изменением конкретного конфигурационного ключа workflow считывает текущий host-файл и
|
||||||
|
патчит только этот ключ.
|
||||||
На хостинге ничего не удаляется: файлы, убранные из репозитория, удалять вручную.
|
На хостинге ничего не удаляется: файлы, убранные из репозитория, удалять вручную.
|
||||||
|
|
||||||
**Проверка после заливки.** На странице цели должен быть адрес загрузки на сайте, а не на самом преленде (иначе нет
|
**Проверка после заливки.** На странице цели должен быть адрес загрузки на сайте, а не на самом преленде (иначе нет
|
||||||
|
|||||||
@@ -57,6 +57,13 @@
|
|||||||
"2": 1
|
"2": 1
|
||||||
},
|
},
|
||||||
"default": "1"
|
"default": "1"
|
||||||
|
},
|
||||||
|
"focus": {
|
||||||
|
"weights": {
|
||||||
|
"center": 1,
|
||||||
|
"face": 0
|
||||||
|
},
|
||||||
|
"default": "center"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Контракт Preland → сайт: собственные метки всегда разрешены до перехода,
|
||||||
|
* а внешние рекламные параметры не теряются.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
$_GET = [
|
||||||
|
'utm_source' => 'stage-ad',
|
||||||
|
'subid' => 'click-42',
|
||||||
|
'key' => 'must-not-replace-client-key',
|
||||||
|
];
|
||||||
|
$_SERVER['HTTP_HOST'] = 'zoomstage.online';
|
||||||
|
|
||||||
|
ob_start();
|
||||||
|
require dirname(__DIR__) . '/index.php';
|
||||||
|
$html = (string) ob_get_clean();
|
||||||
|
|
||||||
|
if (!preg_match('/const redirectUrlUtm = (.+);/', $html, $match)) {
|
||||||
|
fwrite(STDERR, "FAIL: Preland не отдал redirectUrlUtm.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$query = json_decode($match[1], true);
|
||||||
|
if (!is_string($query)) {
|
||||||
|
fwrite(STDERR, "FAIL: redirectUrlUtm должен быть JSON-строкой.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_str($query, $params);
|
||||||
|
$expected = [
|
||||||
|
'indpic' => '1',
|
||||||
|
'theme' => 'dark',
|
||||||
|
'degr' => '1',
|
||||||
|
'registration' => 'after',
|
||||||
|
'bchoice' => 'a',
|
||||||
|
'chb' => 'b',
|
||||||
|
'tp' => '1',
|
||||||
|
'focus' => 'center',
|
||||||
|
'utm_source' => 'stage-ad',
|
||||||
|
'subid' => 'click-42',
|
||||||
|
];
|
||||||
|
|
||||||
|
ksort($params);
|
||||||
|
ksort($expected);
|
||||||
|
|
||||||
|
if ($params !== $expected) {
|
||||||
|
fwrite(STDERR, "FAIL: claim URL обязан нести все resolved UTM и внешние параметры.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($params['key'])) {
|
||||||
|
fwrite(STDERR, "FAIL: внешний key не должен подменять одноразовый ключ загрузки.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fwrite(STDOUT, "OK: preland redirects resolved UTM and external parameters\n");
|
||||||
@@ -25,6 +25,7 @@ if (!is_array($config)) {
|
|||||||
'bchoice' => ['a' => 1, 'b' => 0, 'default' => 'a'],
|
'bchoice' => ['a' => 1, 'b' => 0, 'default' => 'a'],
|
||||||
'chb' => ['a' => 1, 'b' => 0, 'default' => 'b'],
|
'chb' => ['a' => 1, 'b' => 0, 'default' => 'b'],
|
||||||
'tp' => ['1' => 0, '2' => 1, 'default' => '1'],
|
'tp' => ['1' => 0, '2' => 1, 'default' => '1'],
|
||||||
|
'focus' => ['center' => 1, 'face' => 0, 'default' => 'center'],
|
||||||
];
|
];
|
||||||
|
|
||||||
if (($config['host'] ?? null) !== $expected['host']) {
|
if (($config['host'] ?? null) !== $expected['host']) {
|
||||||
|
|||||||
Reference in new issue
Block a user