PageSourceSearch

https://www.marshfieldclinic.org/scripts/amplitude/init.js?v=ba2a844199c5c44c

js marshfieldclinic.org collected 2026-10-02 04:03:36 UTC 4,671 bytes, 121 lines download raw bytes

1; (function () {
2    'use strict';
3    const configElement = document.querySelector('script[data-amplitude-api-key]');
4    const apiKey = configElement?.getAttribute('data-amplitude-api-key');
5
6    if (!apiKey) {
7        return;
8    }
9
10    const script = document.createElement('script');
11    script.src = `https://cdn.amplitude.com/script/${encodeURIComponent(apiKey)}.js`;
12    script.onload = function () {
13        const enrichUserAgentPlugin = () => {
14            return {
15                name: 'enrichUserAgentPlugin',
16                execute: async (event) => {
17                    event.event_properties = {
18                        ...event.event_properties,
19                        user_agent: window.navigator.userAgent
20                    };
21                    return event;
22                },
23            };
24        };
25
26        window.amplitude?.add(enrichUserAgentPlugin());
27        window.amplitude?.init(apiKey);
28    };
29
30    document.head.appendChild(script);
31
32    // comma separated list of domains (without scheme or trailing slash)
33    const domainsToDecorate = parseList(configElement.getAttribute('data-amplitude-decorate-domains'))
34        .map(function (domain) {
35            return domain.toLowerCase();
36        });
37    // comma separated list of query parameters to carry over from the current page
38    const queryParams = parseList(configElement.getAttribute('data-amplitude-decorate-params'));
39
40    // nothing to decorate, so do not bother listening for link activation
41    if (!domainsToDecorate.length) {
42        return;
43    }
44
45    function parseList(value) {
46        return (value || '')
47            .split(',')
48            .map(function (item) {
49                return item.trim();
50            })
51            .filter(Boolean);
52    }
53
54    // matches the host itself or any subdomain of it, so a domain name appearing
55    // elsewhere in the URL (path, query) does not trigger decoration
56    function shouldDecorate(url) {
57        return domainsToDecorate.some(function (domain) {
58            return url.hostname === domain || url.hostname.endsWith('.' + domain);
59        });
60    }
61
62    // carries the tracking params over from the current page, leaving any the link
63    // already specifies untouched, then stamps the Amplitude identifiers.
64    // returns false when Amplitude has not produced its identifiers yet.
65    function decorate(url) {
66        const deviceId = window.amplitude?.getDeviceId?.();
67        const sessionId = window.amplitude?.getSessionId?.();
68        if (!deviceId || !sessionId) {
69            return false;
70        }
71
72        const currentParams = new URLSearchParams(window.location.search);
73        queryParams.forEach(function (param) {
74            // a value authored on the link itself wins over the current page's
75            if (url.searchParams.has(param)) {
76                return;
77            }
78
79            const value = currentParams.get(param);
80            if (value !== null) {
81                url.searchParams.set(param, value);
82            }
83        });
84        url.searchParams.set('ampDeviceId', deviceId);
85        url.searchParams.set('ampSessionId', sessionId);
86        url.searchParams.set('ampTimestamp', Date.now() + 5 * 60 * 1000);
87        return true;
88    }
89
90    function decorateLink(event) {
91        // closest('a') also matches SVG anchors, whose href is an SVGAnimatedString
92        // rather than a string. restrict to HTML anchors so the URL parse below
93        // cannot fail on one.
94        const link = event.target?.closest?.('a');
95        if (!(link instanceof HTMLAnchorElement) || !link.href) {
96            return;
97        }
98
99        let url;
100        try {
101            url = new URL(link.href, window.location.href);
102        } catch {
103            return;
104        }
105
106        if (shouldDecorate(url) && decorate(url)) {
107            link.href = url.toString();
108        }
109    }
110
111    // decorate on activation rather than at load time, so links added to the page
112    // after this script runs are covered too. capture phase, so the href is
113    // rewritten before any other handler acts on it.
114    // mousedown precedes click, auxclick and contextmenu for every mouse button,
115    // so it covers primary, middle and right button activation. contextmenu also
116    // fires without a preceding mousedown when the menu is opened from the
117    // keyboard or by long press. click covers keyboard activation via Enter.
118    ['mousedown', 'contextmenu', 'click'].forEach(function (eventName) {
119        document.addEventListener(eventName, decorateLink, true);
120    });
121})();

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.