PageSourceSearch

https://kanjidon.com/conversion.js?v=20260908-openai-store-conversion

js kanjidon.com collected 2026-10-02 00:51:27 UTC 6,294 bytes, 126 lines download raw bytes

1(function () {
2    'use strict';
3
4    var GOOGLE_STORE_CONVERSION = 'AW-17488655629/FsszCMPn7_AbEI3qnpNB';
5    var userAgent = navigator.userAgent || '';
6    var isIPadOS = navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1;
7    var isIOS = /iPad|iPhone|iPod/i.test(userAgent) || isIPadOS;
8    var isAndroid = /Android/i.test(userAgent);
9    var platform = isIOS ? 'ios' : (isAndroid ? 'android' : null);
10
11    function placementFor(link) {
12        if (link.dataset.placement) return link.dataset.placement;
13        if (link.closest('.sticky-download-bar')) return 'sticky';
14        if (link.closest('.download, .final-cta')) return 'download';
15        if (link.closest('.hero')) return 'hero';
16        return 'header';
17    }
18
19    // Only campaign metadata, never click IDs, arbitrary query values or user IDs.
20    // Page-local by design: no cookies, storage or attribution across visits.
21    function metaAttribution() {
22        if (window.kanjidonAdvertisingConsentGranted !== true
23            || navigator.globalPrivacyControl === true || navigator.doNotTrack === '1') return null;
24        try {
25            var params = new URL(window.location.href).searchParams;
26            var keys = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term'];
27            if (keys.some(function (key) { return params.getAll(key).length > 1; })) return null;
28            var source = params.get('utm_source');
29            if (['fb', 'ig', 'msg', 'an', 'th', 'facebook', 'instagram', 'messenger', 'threads'].indexOf(source) < 0
30                || params.get('utm_medium') !== 'paid_social'
31                || params.get('utm_campaign') !== 'meta_jlpt_video_6lang') return null;
32            var content = params.get('utm_content') || '';
33            if (!/^(it|fr|de|en|es|pt)_[0-9]{10,20}$/.test(content)) return null;
34            var term = params.get('utm_term') || '';
35            return { source: source, content: content,
36                term: ['feed', 'story', 'stories', 'reels', 'facebook_feed', 'instagram_feed',
37                    'instagram_stories', 'facebook_stories', 'instagram_reels', 'facebook_reels',
38                    'marketplace', 'search', 'video_feeds', 'explore', 'threads_feed'].indexOf(term.toLowerCase()) >= 0 ? term : '' };
39        } catch (_) { return null; }
40    }
41
42    function destinationFor(targetPlatform, placement) {
43        var meta = metaAttribution();
44        if (targetPlatform === 'ios') return 'https://apps.apple.com/app/apple-store/id6747951805?pt=121509463&ct='
45            + (meta ? 'meta_jlpt_video_6lang' : 'website_install') + '&mt=8';
46        var campaign = 'utm_source=kanjidon.com&utm_medium=website&utm_campaign=website_install&utm_content=' + placement;
47        if (meta) {
48            campaign = 'utm_source=' + encodeURIComponent(meta.source)
49                + '&utm_medium=paid_social&utm_campaign=meta_jlpt_video_6lang'
50                + '&utm_content=' + encodeURIComponent(meta.content);
51            if (meta.term) campaign += '&utm_term=' + encodeURIComponent(meta.term);
52        }
53        return 'https://play.google.com/store/apps/details?id=com.davidemoscato.kanjidon' + '&referrer=' + encodeURIComponent(campaign);
54    }
55
56    function recordGoogleStoreConversion() {
57        if (window.kanjidonAdvertisingConsentGranted !== true || typeof window.gtag !== 'function') return;
58        window.gtag('event', 'conversion', {
59            send_to: GOOGLE_STORE_CONVERSION,
60            value: 1.0,
61            currency: 'EUR',
62            event_timeout: 1000
63        });
64    }
65
66    function recordClick(targetPlatform, placement) {
67        recordGoogleStoreConversion();
68        if (typeof window.kanjidonMeasureOpenAI === 'function') {
69            window.kanjidonMeasureOpenAI('store_click_' + targetPlatform, placement);
70        }
71        if (!window.fetch) return;
72        window.fetch('/go/' + targetPlatform + '/' + placement + '/', {
73            method: 'GET',
74            cache: 'no-store',
75            credentials: 'omit',
76            keepalive: true
77        }).catch(function () {});
78    }
79
80    function configureStoreLink(link, targetPlatform) {
81        if (link.dataset.storeRoutingReady === 'true') return;
82        var placement = placementFor(link);
83        function refreshDestination() { link.href = destinationFor(targetPlatform, placement); }
84        refreshDestination();
85        link.dataset.storeRoutingReady = 'true';
86        if (platform) link.removeAttribute('target');
87        // Re-read consent at interaction time, including keyboard, middle-click and copying links.
88        ['pointerdown', 'focus', 'contextmenu', 'auxclick'].forEach(function (type) {
89            link.addEventListener(type, refreshDestination);
90        });
91        link.addEventListener('click', function () {
92            refreshDestination();
93            recordClick(targetPlatform, placement);
94        });
95    }
96
97    document.querySelectorAll('[data-smart-download]').forEach(function (link) {
98        link.addEventListener('click', function () {
99            if (typeof window.kanjidonMeasureOpenAI === 'function') {
100                window.kanjidonMeasureOpenAI('download_click', placementFor(link));
101            }
102        });
103        if (platform) configureStoreLink(link, platform);
104        else link.href = '#download';
105    });
106
107    // Editorial articles also link to third-party apps. Route and measure only Kanjidon.
108    function isKanjidonStoreLink(link, targetPlatform) {
109        try {
110            var url = new URL(link.href, window.location.href);
111            if (targetPlatform === 'ios') {
112                return url.hostname === 'apps.apple.com' && /\/id6747951805(?:\/|$)/.test(url.pathname);
113            }
114            return url.hostname === 'play.google.com' && url.pathname === '/store/apps/details'
115                && url.searchParams.get('id') === 'com.davidemoscato.kanjidon';
116        } catch (_) { return false; }
117    }
118
119    document.querySelectorAll('a[href*="apps.apple.com"]').forEach(function (link) {
120        if (isKanjidonStoreLink(link, 'ios')) configureStoreLink(link, 'ios');
121    });
122
123    document.querySelectorAll('a[href*="play.google.com/store/apps/details"]').forEach(function (link) {
124        if (isKanjidonStoreLink(link, 'android')) configureStoreLink(link, 'android');
125    });
126})();

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.