PageSourceSearch

https://mmix.ua/assets/ks-lead-src.js?v=1

js mmix.ua collected 2026-10-08 17:00:38 UTC 4,299 bytes, 58 lines download raw bytes

1/* ks-lead-src v1.1 (2026-10-06; v1.1 — cookie ks_src и window.ksLeadFields для сайтов на своём коде): откуда пришёл посетитель → скрытые поля ks_* в каждой форме.
2   Текущий визит (sessionStorage): страница входа, реферер, utm, gclid. Первый визит (localStorage, 90 дней).
3   Читает хук ksLeadEnrich на сервере; сам запрос Google сайту не передаёт, его подставляет хук из Search Console. */
4(function () {
5  'use strict';
6  var KEY = 'ks_lead_src', FIRST = 'ks_lead_first', FIRST_TTL = 90 * 864e5;
7  function get(st, k) { try { var v = st.getItem(k); return v ? JSON.parse(v) : null; } catch (e) { return null; } }
8  function put(st, k, v) { try { st.setItem(k, JSON.stringify(v)); } catch (e) {} }
9  function cut(s, n) { s = String(s || ''); return s.length > n ? s.slice(0, n) : s; }
10
11  var loc = window.location, qs = {};
12  try { new URLSearchParams(loc.search).forEach(function (v, k) { qs[k.toLowerCase()] = v; }); } catch (e) {}
13  var ref = document.referrer || '', refHost = '';
14  try { refHost = ref ? new URL(ref).hostname : ''; } catch (e) {}
15  var bare = function (h) { return String(h || '').replace(/^www\./, ''); };
16  var external = refHost && bare(refHost) !== bare(loc.hostname);
17  var hasUtm = !!(qs.utm_source || qs.gclid || qs.gbraid || qs.wbraid || qs.fbclid);
18
19  var now = Date.now(), cur = get(window.sessionStorage, KEY);
20  // Новый источник: первая страница сессии, либо пришли по метке/с внешнего сайта посреди сессии.
21  if (!cur || hasUtm || external) {
22    cur = {
23      ep: cut(loc.origin + loc.pathname + loc.search, 400),
24      rf: cut(external ? ref : (cur ? cur.rf : ''), 400),
25      us: cut(qs.utm_source, 80), um: cut(qs.utm_medium, 80), uc: cut(qs.utm_campaign, 120),
26      ut: cut(qs.utm_term, 160), gc: (qs.gclid || qs.gbraid || qs.wbraid) ? 1 : 0, t: now
27    };
28    put(window.sessionStorage, KEY, cur);
29  }
30  var first = get(window.localStorage, FIRST);
31  if (!first || !first.t || now - first.t > FIRST_TTL) { first = cur; put(window.localStorage, FIRST, first); }
32
33  var fields = {
34    ks_ep: cur.ep, ks_rf: cur.rf, ks_us: cur.us, ks_um: cur.um, ks_uc: cur.uc, ks_ut: cur.ut, ks_gc: cur.gc,
35    ks_fep: first.ep, ks_frf: first.rf, ks_fus: first.us, ks_ft: first.t
36  };
37  function fill(form) {
38    if (!form || form.nodeName !== 'FORM' || form.method.toLowerCase() !== 'post') return;
39    for (var k in fields) {
40      var el = form.querySelector('input[name="' + k + '"]');
41      if (!el) { el = document.createElement('input'); el.type = 'hidden'; el.name = k; form.appendChild(el); }
42      el.value = fields[k] == null ? '' : String(fields[k]);
43    }
44  }
45  // v1.1: те же поля в cookie ks_src (сессионная, только этот сайт) — её получает любой /api/* обработчик
46  // сайтов на своём коде (JSON-формы на React скрытых полей не шлют); и window.ksLeadFields() для кода форм.
47  window.ksLeadFields = function () { var o = {}; for (var k in fields) o[k] = fields[k] == null ? '' : String(fields[k]); return o; };
48  try {
49    var ck = window.ksLeadFields(), enc = encodeURIComponent(JSON.stringify(ck));
50    if (enc.length > 3000) { ck.ks_rf = cut(ck.ks_rf, 150); ck.ks_frf = cut(ck.ks_frf, 150); ck.ks_fep = cut(ck.ks_fep, 200); ck.ks_ep = cut(ck.ks_ep, 300); enc = encodeURIComponent(JSON.stringify(ck)); }
51    if (enc.length <= 3800) document.cookie = 'ks_src=' + enc + '; path=/; SameSite=Lax' + (loc.protocol === 'https:' ? '; Secure' : '');
52  } catch (e) {}
53  function all() { var f = document.forms; for (var i = 0; i < f.length; i++) fill(f[i]); }
54  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', all); else all();
55  // Формы, появившиеся позже (модалки, AJAX): заполнить при первом касании.
56  document.addEventListener('focusin', function (e) { if (e.target && e.target.form) fill(e.target.form); }, true);
57  document.addEventListener('submit', function (e) { fill(e.target); }, true);
58})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.