PageSourceSearch

https://graincheck.app/install-tracking.js

js graincheck.app collected 2026-10-02 00:42:24 UTC 4,115 bytes, 83 lines download raw bytes

1/*
2 * GrainCheck — universal web→app install attribution (Tenjin custom "web" channel).
3 *
4 * Every "Install" / store button is routed THROUGH a Tenjin click tracking link,
5 * which records the click (with the inbound source) and redirects to the store.
6 * Works for ANY channel — Meta, Google, TikTok, email, Telegram, referral, organic
7 * — the source is read from UTM tags / click-ids and passed to Tenjin.
8 *
9 * Links come from Tenjin → CONFIGURE → Campaigns (custom channel "web"), per platform.
10 * Meta needs no link here (it's a self-attributing network: S2S callbacks + site pixel).
11 */
12(function (w, d) {
13  // ===== Tenjin custom "web" channel click links (per platform) + store fallbacks =====
14  var WEB_LINK = {
15    ios:     'https://track.tenjin.com/v0/click/dtcsfr8fPIbvngpSTvAzZ',
16    android: 'https://track.tenjin.com/v0/click/fOrJP5JZPJ1iow8xWRkc8j'
17  };
18  var STORE_URL = {
19    ios:     'https://apps.apple.com/app/graincheck/id6761753467',
20    android: 'https://play.google.com/store/apps/details?id=com.graincheck.app'
21  };
22  var META_PIXEL_ID = '1115565107707861';
23  // ====================================================================================
24
25  var q = new URLSearchParams(w.location.search);
26  var get = function (k) { return q.get(k) || ''; };
27  var SRC = {
28    utm_source: get('utm_source'), utm_medium: get('utm_medium'),
29    utm_campaign: get('utm_campaign'), utm_content: get('utm_content'), utm_term: get('utm_term'),
30    fbclid: get('fbclid'), gclid: get('gclid'), ttclid: get('ttclid')
31  };
32  function cookie(n) { var m = d.cookie.match('(^|;)\\s*' + n + '\\s*=\\s*([^;]+)'); return m ? m.pop() : ''; }
33
34  // Readable source label so Tenjin groups installs by where they came from.
35  function sourceLabel() {
36    var s = SRC.utm_source ||
37            (SRC.fbclid ? 'meta' : SRC.gclid ? 'google' : SRC.ttclid ? 'tiktok' : 'organic');
38    return SRC.utm_campaign ? s + '_' + SRC.utm_campaign : s;
39  }
40
41  // Full Tenjin click URL for a platform → records click, then redirects to the store.
42  function GC_tenjinClickURL(platform) {
43    var base = WEB_LINK[platform];
44    if (!base) return STORE_URL[platform] || null; // no tenjin link → go straight to store
45    var sep = base.indexOf('?') === -1 ? '?' : '&';
46    return base + sep + [
47      'campaign_name='      + encodeURIComponent(sourceLabel()),
48      'creative_name='      + encodeURIComponent(SRC.utm_content || SRC.utm_medium),
49      'tenjin_parameter_0=' + encodeURIComponent(SRC.fbclid || cookie('_fbc')),
50      'tenjin_parameter_1=' + encodeURIComponent(cookie('_fbp')),
51      'tenjin_parameter_2=' + encodeURIComponent(SRC.utm_source),
52      'tenjin_parameter_3=' + encodeURIComponent(SRC.gclid || SRC.ttclid),
53      'redirect_url='       + encodeURIComponent(STORE_URL[platform])
54    ].join('&');
55  }
56  w.GC_tenjinClickURL = GC_tenjinClickURL; // install.html builds its redirect from this
57
58  // Side pings for Meta optimisation + GA (Tenjin attribution is the redirect itself).
59  function GC_fireInstallTracking() {
60    if (META_PIXEL_ID && w.fbq) { try { w.fbq('trackCustom', 'InstallClick', { source: SRC.utm_source || 'web' }); } catch (e) {} }
61    if (w.gtag) { try { w.gtag('event', 'install_click', { source: SRC.utm_source || 'direct', campaign: SRC.utm_campaign }); } catch (e) {} }
62  }
63  w.GC_fireInstallTracking = GC_fireInstallTracking;
64
65  function platformOf(href) {
66    return /apps\.apple\.com/.test(href) ? 'ios' : /play\.google\.com/.test(href) ? 'android' : null;
67  }
68
69  // Point every store button at its Tenjin click link (which redirects to the store).
70  function wire() {
71    var links = d.querySelectorAll('a[href*="play.google.com/store/apps"], a[href*="apps.apple.com"]');
72    Array.prototype.forEach.call(links, function (a) {
73      var plat = platformOf(a.href);
74      if (!plat) return;
75      a.href = GC_tenjinClickURL(plat);
76      a.addEventListener('click', GC_fireInstallTracking, { passive: true });
77    });
78  }
79
80  if (w.GC_NO_AUTOWIRE) return;
81  if (d.readyState !== 'loading') wire();
82  else d.addEventListener('DOMContentLoaded', wire);
83})(window, document);

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.