weathervane 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +471 -0
- package/package.json +29 -0
- package/weathervane.js +1026 -0
- package/weathervane.min.js +16 -0
- package/weathervane.min.js.gz +0 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Weathervane v0.1.0
|
|
3
|
+
* A lightweight, zero-backend analytics utility.
|
|
4
|
+
*
|
|
5
|
+
* Weathervane does NOT send data anywhere. It observes user behavior
|
|
6
|
+
* (pageviews, content exposure, clicks, forms, sessions, web vitals)
|
|
7
|
+
* and emits structured browser CustomEvents that you can forward to
|
|
8
|
+
* any destination (GA4, PostHog, Segment, your own API, ...).
|
|
9
|
+
*
|
|
10
|
+
* window.addEventListener('vane:event', function (e) {
|
|
11
|
+
* console.log(e.detail.event_name, e.detail);
|
|
12
|
+
* });
|
|
13
|
+
*
|
|
14
|
+
* License: MIT
|
|
15
|
+
*/
|
|
16
|
+
!function(e,t){"use strict";if(e&&t&&(!e.vane||!e.vane.__loaded)){var n="0.1.0",r=e.vane,i=N({},{eventPrefix:"vane",historySize:100,enableAutoPageview:!0,enableDynamicPageview:!0,enableContentTracking:!0,enableLinkTracking:!0,enableFormTracking:!0,enableWebVitals:!0,trackShadowDom:!0,sessionTimeout:30,contentExposureLimit:1e3,largeContentViewportFill:.65,formAbandonThreshold:3e3,debug:!1}),a=!1,o="0123456789ABCDEFGHJKMNPQRSTVWXYZ",l=[],u={},c="vane_cid",s="vane_sid",f=null,d={id:null,lastActive:0,lastPersist:0},v=null,h=null,m=V(),g={},p=null,_=null,y={first_contentful_paint:null,largest_contentful_paint:null,cumulative_layout_shift:null,first_input_delay:null},b=[],w=0,S=!1,A=[],k=[],E=e.location.href,T=!1,x=new Map,C=null,P=null,M=[],O=new Map,I={__loaded:!0,version:n,init:we,track:function(e,t){return e&&"string"==typeof e?te(e,t):(B("track() requires an event name string"),null)},trackPageView:function(){ne("pageview",{navigation_trigger:"manual"})},on:function(t,n,r){r=r||{};var a=i.eventPrefix+":"+("*"===t?"event":t),o=function(e){n(e.detail,e)};if(e.addEventListener(a,o),r.replay)for(var l=0;l<A.length;l++)"*"!==t&&A[l].event_name!==t||n(A[l],null);return function(){e.removeEventListener(a,o)}},setUserId:function(e){var t=v;(v=e||null)&&v!==t&&te("user_identify",{user_id:v,previous_user_id:t})},getUserId:function(){return v},setContext:function(e,t){null==t?delete g[e]:g[e]=t},getContext:function(){return N({},g)},clearContext:function(){g={}},newSession:function(){Z("manual")},getClientId:function(){return f},getSessionId:function(){return d.id},getPageViewId:function(){return h},getHistory:function(){return A.slice()},getContentState:function(){var e=[];return x.forEach(function(t){e.push({content_name:t.name,content_type:t.type,segment:t.segment,served:t.served,viewed:t.viewed,clicked:t.clicked,exposure_limit:t.exposureLimit})}),e},isReady:function(){return a},destroy:function(){be(),x.forEach(function(e){clearTimeout(e.timer)}),x.clear(),O.clear(),b.forEach(function(e){try{e.disconnect()}catch(e){}}),b=[],l.forEach(function(e){try{e()}catch(e){}}),l=[],M=[],T=!1,a=!1,B("destroyed")}},L=r&&r._queue;if(e.vane=I,L&&L.length)for(var R=0;R<L.length;R++){var D=L[R];"function"==typeof I[D[0]]&&I[D[0]].apply(I,D[1])}var F=t.currentScript;F&&"false"===F.getAttribute("data-vane-auto")||e.vaneConfig&&!1===e.vaneConfig.autoInit||a||we(e.vaneConfig||{}),"undefined"!=typeof module&&module.exports&&(module.exports=I)}function N(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];if(n)for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}function V(){return Date.now()}function q(t){var n=new Uint8Array(t);if(e.crypto&&e.crypto.getRandomValues)e.crypto.getRandomValues(n);else for(var r=0;r<t;r++)n[r]=Math.floor(256*Math.random());return n}function U(){if(e.crypto&&e.crypto.randomUUID)try{return e.crypto.randomUUID()}catch(e){}var t=q(16);t[6]=15&t[6]|64,t[8]=63&t[8]|128;for(var n="",r=0;r<16;r++)n+=(t[r]+256).toString(16).slice(1);return n.slice(0,8)+"-"+n.slice(8,12)+"-"+n.slice(12,16)+"-"+n.slice(16,20)+"-"+n.slice(20)}function H(){for(var e=V(),t="",n=0;n<10;n++)t=o[e%32]+t,e=Math.floor(e/32);for(var r=q(16),i=0;i<16;i++)t+=o[r[i]%32];return t}function z(e,t){return(e=(e||"").replace(/\s+/g," ").trim()).length>t?e.slice(0,t):e}function B(){if(i.debug&&e.console){for(var t=["%c vane ","background:#5b5bd6;color:#fff;border-radius:3px"],n=0;n<arguments.length;n++)t.push(arguments[n]);console.log.apply(console,t)}}function W(e,t,n,r){e.addEventListener(t,n,r),l.push(function(){e.removeEventListener(t,n,r)})}function Y(t){try{var n=e.localStorage.getItem(t);if(null!==n)return n}catch(e){}return Object.prototype.hasOwnProperty.call(u,t)?u[t]:null}function j(t,n){u[t]=n;try{e.localStorage.setItem(t,n)}catch(e){}}function G(){j(s,d.id+"."+d.lastActive),d.lastPersist=V()}function Z(e,t){var n=void 0!==t?t:d.id;d.id=U(),d.lastActive=V(),G(),te("session_start",{reason:e,previous_session_id:n||null})}function J(){var e=V();e-d.lastActive>6e4*i.sessionTimeout?Z("timeout"):(d.lastActive=e,e-d.lastPersist>1e4&&G())}function K(e){return/iPad|Tablet|PlayBook/i.test(e)||/Android/i.test(e)&&!/Mobile/i.test(e)?"tablet":/Mobi|iPhone|iPod|Android/i.test(e)?"mobile":"desktop"}function Q(){if(!p){var t=navigator.userAgent||"",n=function(e){var t;return(t=e.match(/Edg(?:e|A|iOS)?\/([\d.]+)/))?{name:"Edge",version:t[1]}:(t=e.match(/OPR\/([\d.]+)/))?{name:"Opera",version:t[1]}:(t=e.match(/SamsungBrowser\/([\d.]+)/))?{name:"Samsung Internet",version:t[1]}:(t=e.match(/(?:Firefox|FxiOS)\/([\d.]+)/))?{name:"Firefox",version:t[1]}:(t=e.match(/(?:Chrome|CriOS)\/([\d.]+)/))?{name:"Chrome",version:t[1]}:/Safari\//.test(e)&&(t=e.match(/Version\/([\d.]+)/))?{name:"Safari",version:t[1]}:{name:"unknown",version:null}}(t),r=null;try{r=Intl.DateTimeFormat().resolvedOptions().timeZone}catch(e){}p={user_agent:t,browser_name:n.name,browser_version:n.version,language:navigator.language||null,timezone:r,screen_width:e.screen?e.screen.width:null,screen_height:e.screen?e.screen.height:null,device_type:K(t),device_memory:navigator.deviceMemory||null,hardware_concurrency:navigator.hardwareConcurrency||null,cookie_enabled:!!navigator.cookieEnabled}}return N({},p,{viewport_width:e.innerWidth,viewport_height:e.innerHeight,online:!1!==navigator.onLine})}function X(){var t={},n=!1;try{for(var r=new URLSearchParams(e.location.search),i=["source","medium","campaign","term","content"],a=0;a<i.length;a++){var o=r.get("utm_"+i[a]);o&&(t["utm_"+i[a]]=o,n=!0)}}catch(e){}return n?t:null}function $(){S=!1;var n=t.documentElement.scrollHeight-e.innerHeight,r=n>0?Math.min(100,Math.round(e.scrollY/n*100)):100;r>w&&(w=r)}function ee(n,r){var i;try{i=new CustomEvent(n,{detail:r})}catch(e){(i=t.createEvent("CustomEvent")).initCustomEvent(n,!1,!1,r)}e.dispatchEvent(i)}function te(r,o){if(!a)return k.push([r,o]),null;var l=function(r,i){return{event_id:H(),event_name:r,timestamp:(new Date).toISOString(),client_id:f,session_id:d.id,page_view_id:h,user_id:v,properties:i||{},page:(a=e.location,{url:a.href,path:a.pathname,title:t.title||null,referrer:t.referrer||null,search:a.search||null,hash:a.hash||null}),device:Q(),utm:_,performance:N({},y),engagement:{scroll_depth:w,time_on_page:V()-m},context:N({},g),sdk:{name:"weathervane",version:n}};var a}(r,o);return A.push(l),A.length>i.historySize&&A.splice(0,A.length-i.historySize),ee(i.eventPrefix+":event",l),ee(i.eventPrefix+":"+r,l),B(r,l),l}function ne(e,t){h=U(),m=V(),w=0,_=X(),te(e,N({},t))}function re(t){if(e.location.href!==E&&(E=e.location.href,J(),be(),i.enableDynamicPageview)){var n={navigation_trigger:t};"hashchange"===t&&(n.new_hash=e.location.hash||null),ne("pageview_dynamic",n)}}function ie(n){var r=t.documentElement.scrollHeight;if(!r)return 0;var i=n.getBoundingClientRect().top+e.scrollY;return Math.max(0,Math.min(100,Math.round(i/r*100)))}function ae(e,t){return{content_name:t.name,content_type:t.type,segment:t.segment,content_instance:t.instanceId,content_depth:ie(e),exposure_limit:t.exposureLimit}}function oe(e){if(e.composedPath)try{return e.composedPath()}catch(e){}for(var t=[],n=e.target;n;)t.push(n),n=n.parentNode;return t}function le(e,t,n){for(var r=t;r<e.length;r++){var i=e[r];if(i&&1===i.nodeType&&n(i))return{el:i,index:r}}return null}function ue(e){if(i.enableContentTracking&&!x.has(e)){var t=e.getAttribute("data-vane-content");if(t){var n={name:t,type:e.getAttribute("data-vane-type")||null,segment:e.getAttribute("data-vane-segment")||null,exposureLimit:parseInt(e.getAttribute("data-vane-exposure"),10)||i.contentExposureLimit,instanceId:U(),served:!0,viewed:!1,clicked:!1,accumulated:0,visibleSince:null,resumeOnShow:!1,timer:null};x.set(e,n),te("content_serve",ae(e,n)),C&&C.observe(e)}}}function ce(e){if(e||(e=t),1===e.nodeType&&(i.enableContentTracking&&e.hasAttribute("data-vane-content")&&ue(e),i.trackShadowDom&&e.shadowRoot&&se(e.shadowRoot)),e.querySelectorAll){if(i.enableContentTracking)for(var n=e.querySelectorAll("[data-vane-content]"),r=0;r<n.length;r++)ue(n[r]);if(i.trackShadowDom)for(var a=e.querySelectorAll("*"),o=0;o<a.length;o++)a[o].shadowRoot&&se(a[o].shadowRoot)}}function se(e){if(-1===M.indexOf(e)){if(M.push(e),P){var n=e===t?t.body||t.documentElement:e;P.observe(n,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["data-vane-content"]})}e!==t&&i.enableFormTracking&&W(e,"submit",ye,!0),ce(e)}}function fe(e,t){return!!e.isIntersecting&&(e.boundingClientRect.height<=t?e.intersectionRatio>=.98:e.intersectionRect.height>=t*i.largeContentViewportFill)}function de(e,t){var n=Math.max(0,t.exposureLimit-t.accumulated);clearTimeout(t.timer),t.timer=setTimeout(function(){if(!t.viewed&&null!==t.visibleSince){t.viewed=!0;var n=t.accumulated+(V()-t.visibleSince);te("content_view",N(ae(e,t),{exposure_time:Math.round(n)})),C&&C.unobserve(e)}},n)}function ve(e){null!==e.visibleSince&&(e.accumulated+=V()-e.visibleSince,e.visibleSince=null),clearTimeout(e.timer)}function he(t){for(var n=e.innerHeight,r=0;r<t.length;r++){var i=t[r],a=x.get(i.target);if(a&&!a.viewed){var o=fe(i,n);o&&null===a.visibleSince?(a.visibleSince=V(),de(i.target,a)):o||null===a.visibleSince||ve(a)}}}function me(){(i.enableContentTracking||i.trackShadowDom)&&(i.enableContentTracking&&"undefined"!=typeof IntersectionObserver&&(C=new IntersectionObserver(he,{threshold:[0,.25,.5,.65,.75,.9,.98,1]}),l.push(function(){C.disconnect(),C=null})),"undefined"!=typeof MutationObserver&&(P=new MutationObserver(function(e){for(var t=0;t<e.length;t++){var n=e[t];if("attributes"!==n.type){for(var r=0;r<n.addedNodes.length;r++){var a=n.addedNodes[r];1===a.nodeType&&ce(a)}if(i.trackShadowDom)for(var o=0;o<n.removedNodes.length;o++){var l=n.removedNodes[o];1===l.nodeType&&"TEMPLATE"===l.tagName&&(l.hasAttribute("shadowrootmode")||l.hasAttribute("shadowroot"))&&n.target&&1===n.target.nodeType&&n.target.shadowRoot&&se(n.target.shadowRoot)}}else ue(n.target)}}),l.push(function(){P.disconnect(),P=null})),i.trackShadowDom&&function(){if(e.Element&&Element.prototype.attachShadow){var t=Element.prototype.attachShadow;Element.prototype.attachShadow=function(e){var n=t.call(this,e);return e&&"open"===e.mode&&se(n),n},l.push(function(){Element.prototype.attachShadow=t})}}(),se(t),W(t,"visibilitychange",function(){"hidden"===t.visibilityState?x.forEach(function(e){null!==e.visibleSince&&(ve(e),e.resumeOnShow=!0)}):x.forEach(function(e,t){e.resumeOnShow&&!e.viewed&&(e.resumeOnShow=!1,e.visibleSince=V(),de(t,e))})}))}function ge(t){var n=oe(t);if(n.length){if(J(),i.enableContentTracking){var r=le(n,0,function(e){return e.hasAttribute("data-vane-content-click")});if(r){var a=r.el,o=le(n,r.index,function(e){return e.hasAttribute("data-vane-content")}),l=o?o.el:null,u=l?x.get(l):null;u&&(u.clicked=!0);var c={click_id:a.getAttribute("data-vane-content-click"),element_tag:a.tagName.toLowerCase(),element_text:z(a.innerText||a.textContent,100)||null};l&&u&&N(c,ae(l,u)),te("content_click",c)}}if(i.enableLinkTracking){var s=le(n,0,function(e){return"A"===e.tagName&&e.getAttribute("href")});if(s){var f=s.el,d=f.getAttribute("href")||"";te("link_click",{url:f.href,text:z(f.innerText||f.getAttribute("aria-label"),100)||null,target:f.getAttribute("target")||null,href:z(d.split(/[?#]/)[0],200),link_type:(v=d,/^mailto:/i.test(v)?"email":/^tel:/i.test(v)?"phone":"web"),is_external:!!f.host&&f.host!==e.location.host})}}var v}}function pe(t){for(var n=t.querySelectorAll("input, select, textarea"),r=[],i=0,a=0;a<n.length;a++){var o=n[a].type||n[a].tagName.toLowerCase();-1===r.indexOf(o)&&r.push(o),n[a].required&&i++}return{form_name:t.getAttribute("name")||t.id||"unnamed",form_action:t.getAttribute("action")||e.location.pathname,form_method:(t.getAttribute("method")||"GET").toUpperCase(),field_count:n.length,field_types:r,required_fields:i,optional_fields:n.length-i,form_type:t.getAttribute("data-vane-form-type")||null,form_category:t.getAttribute("data-vane-form-category")||null,form_step:t.getAttribute("data-vane-form-step")||null,form_funnel:t.getAttribute("data-vane-form-funnel")||null,form_value:t.getAttribute("data-vane-form-value")||null,form_goal:t.getAttribute("data-vane-form-goal")||null,form_segment:t.getAttribute("data-vane-form-segment")||null}}function _e(e){var t=oe(e)[0];t&&1===t.nodeType&&t.form&&(O.has(t.form)||O.set(t.form,{start:V()}))}function ye(e){var t=e.target;if(t&&"FORM"===t.tagName){var n=pe(t),r=O.get(t);r&&(n.completion_time=V()-r.start,O.delete(t)),te("form_submit",n)}}function be(){i.enableFormTracking&&(O.forEach(function(e,t){var n=V()-e.start;n>=i.formAbandonThreshold&&te("form_abandon",N(pe(t),{engagement_time:n}))}),O.clear())}function we(n){if(a)return B("init() called twice — ignoring"),I;var r;N(i,n||{}),a=!0,(f=Y(c))||(f=U()),j(c,f),_=X(),function(){function e(e,t){try{var n=new PerformanceObserver(function(e){t(e.getEntries())});n.observe({type:e,buffered:!0}),b.push(n)}catch(e){}}i.enableWebVitals&&"undefined"!=typeof PerformanceObserver&&(e("paint",function(e){for(var t=0;t<e.length;t++)"first-contentful-paint"===e[t].name&&(y.first_contentful_paint=Math.round(e[t].startTime))}),e("largest-contentful-paint",function(e){var t=e[e.length-1];t&&(y.largest_contentful_paint=Math.round(t.startTime))}),e("layout-shift",function(e){for(var t=0;t<e.length;t++)e[t].hadRecentInput||(y.cumulative_layout_shift=Math.round(1e4*((y.cumulative_layout_shift||0)+e[t].value))/1e4)}),e("first-input",function(e){var t=e[0];t&&null===y.first_input_delay&&(y.first_input_delay=Math.round(t.processingStart-t.startTime))}))}(),W(e,"scroll",function(){S||(S=!0,e.requestAnimationFrame($))},{passive:!0}),function(){var e=Y(s),t=null,n=0;if(e){var r=e.split(".");t=r[0]||null,n=parseInt(r[1],10)||0}!t||V()-n>6e4*i.sessionTimeout?Z(t?"timeout":"new",t):(d.id=t,d.lastActive=V(),G())}(),i.enableDynamicPageview&&!T&&e.history&&e.history.pushState&&(T=!0,["pushState","replaceState"].forEach(function(t){var n=e.history[t];e.history[t]=function(){var e=n.apply(this,arguments);return re(t),e},l.push(function(){e.history[t]=n})}),W(e,"popstate",function(){re("popstate")}),W(e,"hashchange",function(){re("hashchange")})),W(t,"click",ge,!0),i.enableFormTracking&&(W(t,"focusin",_e,!0),W(t,"submit",ye,!0),W(e,"pagehide",be)),W(t,"keydown",J,{passive:!0}),W(e,"scroll",J,{passive:!0}),W(e,"pagehide",G),r=function(){var e;i.enableAutoPageview?ne("pageview",N({navigation_trigger:"initial"},function(){try{var e=performance.getEntriesByType("navigation")[0];return e?{page_load_time:e.loadEventEnd>0?Math.round(e.loadEventEnd):null,dom_content_loaded_time:e.domContentLoadedEventEnd>0?Math.round(e.domContentLoadedEventEnd):null,navigation_type:e.type||null}:{}}catch(e){return{}}}(),(e=navigator.connection)?{connection_type:e.effectiveType||null,connection_speed:"number"==typeof e.downlink?e.downlink:null}:{})):h=U(),me()},"loading"===t.readyState?W(t,"DOMContentLoaded",r):r();for(var o=k.splice(0),u=0;u<o.length;u++)te(o[u][0],o[u][1]);return B("initialized",i),I}}("undefined"!=typeof window?window:null,"undefined"!=typeof document?document:null);
|
|
Binary file
|