universal-ad-loader 0.1.1 → 0.1.2
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/CHANGELOG.md +5 -0
- package/README.md +22 -0
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/ual.js +1 -1
- package/dist/ual.min.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -16,6 +16,28 @@ One tag per site. It handles slots, centralized configuration, TCF consent, lazy
|
|
|
16
16
|
- `data-ad-params` (optional) overrides the provider's `params` for that instance.
|
|
17
17
|
- Divs added later (SPA, infinite scroll) are detected automatically. On a route change, call `ual.pageView()`.
|
|
18
18
|
|
|
19
|
+
**Inline configuration (no JSON file).** Instead of `data-config`, the configuration can be passed as an object in the page. The `cmd.push` block can go before or after the loader tag:
|
|
20
|
+
|
|
21
|
+
```html
|
|
22
|
+
<script>
|
|
23
|
+
window.ual = window.ual || { cmd: [] };
|
|
24
|
+
ual.cmd.push(function (u) {
|
|
25
|
+
u.init({
|
|
26
|
+
site: 'site_123',
|
|
27
|
+
providers: { main: { adapter: 'json', endpoint: 'https://ads.yourdomain.net/v1/decide' } },
|
|
28
|
+
slots: { top: { sizes: [[728, 90]], providers: ['main'] } }
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
</script>
|
|
32
|
+
<script async src="https://adcdn.yourdomain.net/ual.min.js"></script>
|
|
33
|
+
|
|
34
|
+
<div data-ad-slot="top"></div>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
- Use either `data-config` or `init(...)`, not both: a second `init` is ignored with a warning.
|
|
38
|
+
- The configuration lives in the page HTML, so changing it means redeploying the page (with a JSON on the CDN you just replace the file). `u.init('https://.../site_123.json')` also works if you want to choose the URL at runtime.
|
|
39
|
+
- An inline script needs `'unsafe-inline'` or a nonce in the page's CSP; with a strict CSP prefer the external JSON.
|
|
40
|
+
|
|
19
41
|
> **What to upload to the CDN:** the loader (`dist/ual.min.js`) and one configuration JSON per site, with the right headers: see `docs/cdn.md`.
|
|
20
42
|
|
|
21
43
|
## Configuration (JSON served from the CDN)
|
package/dist/index.cjs
CHANGED
package/dist/index.mjs
CHANGED
package/dist/ual.js
CHANGED
package/dist/ual.min.js
CHANGED
|
@@ -9,4 +9,4 @@ window.UALExt={
|
|
|
9
9
|
close:function(){s({cmd:'close'});},
|
|
10
10
|
click:function(){s({cmd:'click'});if(window.clickTag)window.open(window.clickTag,'_blank');}
|
|
11
11
|
};
|
|
12
|
-
})();<\/script>`}function ee(e){return String(e).replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">")}function st(e,r){let t='<!doctype html><html><head><meta charset="utf-8"><base target="_blank"><style>html,body{margin:0;padding:0;overflow:hidden;background:transparent}img{display:block;border:0;max-width:100%}</style>'+ot(r,e.clickUrl)+"</head><body>",o="";if(e.type==="image"){let i=`<img src="${ee(e.src)}" width="${e.width}" height="${e.height}" alt="${ee(e.alt||"Advertisement")}">`;o=e.clickUrl?`<a href="${ee(e.clickUrl)}" rel="noopener sponsored" onclick="parent.postMessage({ual:'${r}',cmd:'click'},'*')">${i}</a>`:i}else o=e.html||"";return t+o+"</body></html>"}function Ce(e,r,{slotId:t,onClick:o,onClose:i}={}){at();let a="ual"+ ++rt,c=document.createElement("iframe");c.title="Advertisement",c.setAttribute("scrolling","no"),c.setAttribute("frameborder","0"),c.setAttribute("loading","eager"),c.setAttribute("referrerpolicy","strict-origin-when-cross-origin"),c.style.cssText=`border:0;display:block;margin:0 auto;width:${r.width}px;height:${r.height}px;max-width:100%`,c.width=r.width,c.height=r.height;let l=it(r);return l!==null&&c.setAttribute("sandbox",l),r.type==="url"?c.src=r.url:c.srcdoc=st(r,a),te.set(a,{iframe:c,slotId:t,ad:r,original:{w:r.width,h:r.height},onClick:()=>{q(r.trackers&&r.trackers.click),o&&o()},onClose:i}),e.innerHTML="",e.appendChild(c),{iframe:c,channel:a,destroy:()=>te.delete(a)}}var Me=!1;function at(){Me||(Me=!0,window.addEventListener("message",lt))}function lt(e){let r=e.data;if(!r||typeof r!="object"||!r.ual)return;let t=te.get(r.ual);if(!(!t||e.source!==t.iframe.contentWindow))switch(r.cmd){case"resize":{let o=Math.min(+r.w||t.original.w,B),i=Math.min(+r.h||t.original.h,B);t.iframe.style.width=o+"px",t.iframe.style.height=i+"px";break}case"collapse":t.iframe.style.width=t.original.w+"px",t.iframe.style.height=t.original.h+"px";break;case"close":t.onClose&&t.onClose();break;case"click":t.onClick();break;default:}}function Oe(e,{threshold:r=.5,durationMs:t=1e3}={},o){if(!("IntersectionObserver"in window))return()=>{};let i=null,a=!1,c=!1,l=()=>{a||i||document.visibilityState!=="visible"||(i=setTimeout(()=>{a=!0,E(),o()},t))},u=()=>{clearTimeout(i),i=null},f=new IntersectionObserver(A=>{A.forEach(p=>{c=p.intersectionRatio>=r,c?l():u()})},{threshold:[0,r,1]}),y=()=>document.visibilityState==="visible"&&c?l():u();document.addEventListener("visibilitychange",y),f.observe(e);function E(){u(),f.disconnect(),document.removeEventListener("visibilitychange",y)}return E}var ct=new Set(["unconfigured","disabled","closed"]),dt=242500;function $e(e){let r=ce(),t=null,o=null,i={},a={gdprApplies:void 0,tcString:"",purposes:{},granted:!1,source:"pending"},c=Promise.resolve(a),l=!1,u=null,f=new Map,y=new Map,E=0,A=null,p=null,v=new Set,M=null;function z(){return{site:t.site,page:{url:location.href,path:location.pathname,ref:document.referrer,title:document.title},device:pe(),viewport:{w:window.innerWidth,h:window.innerHeight},targeting:{...t.targeting},consent:a,debug:ue()}}function k(){let n=ye(o);return Object.assign(n.targeting,i),n}function _(n){let s=a;if(!(s.granted===n.granted&&s.tcString===n.tcString&&s.source===n.source)&&(a=n,r.emit("consent",a),!s.granted&&n.granted))for(let d of[...f.values()])d.consentSkipped&&U(d)}function U(n,s=20){if(f.get(n.instanceId)===n){if(n.status==="loading"||n.status==="queued"){s>0&&setTimeout(()=>U(n,s-1),250);return}K(n)}}function We(n){return u?(S("init gi\xE0 eseguito"),u):(u=He(n).catch(s=>{throw u=null,s}),u)}async function He(n){o=await ge(n),o.debug&&Y(!0),he(o,e),t=k(),I("Config",t),c=Ae(t.consent,_).then(s=>(_(s),s)),document.readyState==="loading"&&await new Promise(s=>document.addEventListener("DOMContentLoaded",s,{once:!0})),l=!0,Xe(),V(document),Je(),r.emit("ready",{site:t.site})}function V(n){let s=[];n.nodeType===1&&n.matches&&n.matches("[data-ad-slot]")&&s.push(n),n.querySelectorAll&&n.querySelectorAll("[data-ad-slot]").forEach(d=>s.push(d)),s.forEach(Be)}function Be(n){let s=n.dataset.ualId;if(!s)return oe(n);f.has(s)||ct.has(n.dataset.ualStatus)||(ie(n),oe(n))}function ie(n){delete n.dataset.ualId,delete n.dataset.ualStatus,n.querySelectorAll(":scope > .ual-label, :scope > .ual-creative").forEach(s=>s.remove()),n.classList.remove("ual-slot","ual-filled"),n.style.display="",n.style.minHeight=""}function oe(n){let s=n.getAttribute("data-ad-slot"),d=t.slots[s];if(n.dataset.ualId=s+"#"+ ++E,!d){I("Slot non configurato, ignorato:",s),n.dataset.ualStatus="unconfigured";return}if(d.enabled===!1){I("Slot disabilitato:",s),n.dataset.ualStatus="disabled",X(n,d);return}let w={};try{w=n.dataset.adParams?JSON.parse(n.dataset.adParams):{}}catch(T){S("data-ad-params non \xE8 JSON valido",n)}let h={instanceId:n.dataset.ualId,name:s,el:n,cfg:d,params:w,status:"idle",cleanup:[],tries:0,consentSkipped:!1};f.set(h.instanceId,h),Ve(h),r.emit("slotRegistered",C(h)),(d.lazy!==void 0?d.lazy:t.lazy.enabled)&&A?A.observe(n):J(h)}function Ve(n){let{el:s,cfg:d}=n;if(d.minHeight&&(s.style.minHeight=d.minHeight+"px"),s.classList.add("ual-slot"),d.label){let h=document.createElement("div");h.className="ual-label",h.textContent=d.label,h.style.cssText="font:10px/1.4 sans-serif;color:#888;text-align:center;text-transform:uppercase;letter-spacing:.05em",s.appendChild(h)}let w=document.createElement("div");w.className="ual-creative",s.appendChild(w),n.box=w}function Je(){"MutationObserver"in window&&(p=new MutationObserver(n=>{for(let s of n)s.removedNodes.forEach(d=>{if(d.nodeType===1)for(let w of[...f.values()])(d===w.el||d.contains(w.el))&&G(w)}),s.addedNodes.forEach(d=>{d.nodeType===1&&V(d)})}),p.observe(document.body||document.documentElement,{childList:!0,subtree:!0}))}function Xe(){"IntersectionObserver"in window&&(A=new IntersectionObserver(n=>{n.forEach(s=>{if(!s.isIntersecting)return;A.unobserve(s.target);let d=f.get(s.target.dataset.ualId);d&&J(d)})},{rootMargin:t.lazy.fetchMargin}))}function J(n){n.status!=="loading"&&(n.status="queued",v.add(n),clearTimeout(M),M=setTimeout(Ke,30))}function Ke(){let n=[...v];v=new Set,n.length&&se(n,0)}async function se(n,s){let d=new Map,w=[];for(let h of n){let b=(h.cfg.providers||[])[s];if(!b){w.push(h);continue}let T=typeof b=="string"?b:b.id;d.has(T)||d.set(T,[]),d.get(T).push(h)}w.forEach(Ye),await Promise.all([...d.entries()].map(async([h,b])=>{let T=await Qe(h,b,s);T.length&&await se(T,s+1)}))}async function Ge(n){let s=t.providers[n];if(!s)throw new Error("Provider non definito: "+n);let d=e.get(s.adapter);if(!d)throw new Error("Adapter non registrato: "+s.adapter);return y.has(n)||y.set(n,Promise.resolve(d.init?d.init(s,z()):null)),await y.get(n),{adapter:d,pcfg:s}}async function Qe(n,s,d){let w=t.providers[n];if((!w||w.consent!=="contextual")&&await c,s=s.filter(m=>f.get(m.instanceId)===m),!s.length)return[];let h,b;try{({adapter:h,pcfg:b}=await Ge(n))}catch(m){return S(m.message),r.emit("error",{provider:n,error:m}),s}if(b.consent==="required"&&!a.granted)return I(`Provider ${n} saltato: consenso non concesso`),s.forEach(m=>{m.consentSkipped=!0}),s;let T=z(),O=s.map(m=>{m.status="loading",m.provider=n;let g=m.cfg.providers[d];return{id:m.instanceId,name:m.name,el:m.box,sizes:ve(m.cfg),params:{...typeof g=="object"?g.params:{},...m.params},cfg:m.cfg}});O.forEach(m=>r.emit("slotRequested",{slot:m.name,id:m.id,provider:n})),I(`Richiesta a ${n} (${b.adapter})`,O.map(m=>m.name));let le=b.timeoutMs||t.providerTimeoutMs,L=[];try{if(h.fill){let m=await R(h.fill(O,b,T),le+2e3,{});s.forEach((g,Q)=>{let x=m[O[Q].id];x&&x.filled?ae(g,{width:x.width,height:x.height,selfRendered:!0,meta:x.meta}):(N(g),P(g),L.push(g))})}else{let m=await R(h.request(O,b,T),le,{});s.forEach((g,Q)=>{let x=m[O[Q].id];if(!x||!x.html&&!x.src&&!x.url){L.push(g);return}let D=ze(x);if(!D.ok){S(`Annuncio scartato (${n}, slot ${g.name}): ${D.reason}`),r.emit("error",{provider:n,slot:g.name,error:new Error(D.reason)}),L.push(g);return}let j=D.ad,et=Ce(g.box,j,{slotId:g.instanceId,onClick:()=>r.emit("slotClick",C(g)),onClose:()=>{G(g),g.el.dataset.ualStatus="closed",X(g.el,g.cfg,!0)}});g.cleanup.push(et.destroy),q(j.trackers.impression),ae(g,{width:j.width,height:j.height,ad:j})})}}catch(m){S(`Errore provider ${n}`,m),r.emit("error",{provider:n,error:m}),s.forEach(g=>{g.status==="loading"&&(N(g),P(g),L.push(g))})}return L}function ae(n,s){n.status="filled",n.el.dataset.ualStatus="filled",n.el.classList.add("ual-filled"),n.el.style.display="",r.emit("slotRendered",{...C(n),width:s.width,height:s.height,meta:s.meta});let d={...t.viewability,...n.cfg.viewability};(s.width||0)*(s.height||0)>dt&&!(n.cfg.viewability&&n.cfg.viewability.threshold!==void 0)&&(d.threshold=Math.min(d.threshold,.3));let h=n.box.firstElementChild||n.box,b=Oe(h,d,()=>{s.ad&&q(s.ad.trackers.viewable),r.emit("slotViewable",C(n)),Ze(n)});n.cleanup.push(b)}function Ye(n){n.status="empty",n.el.dataset.ualStatus="empty",P(n),X(n.el,n.cfg),r.emit("slotEmpty",C(n))}function X(n,s,d){(d||(s.collapseEmpty!==void 0?s.collapseEmpty:t&&t.collapseEmpty))&&(n.style.display="none",n.style.minHeight="")}function P(n){n.cleanup.forEach(s=>{try{s()}catch(d){}}),n.cleanup=[],n.box&&(n.box.innerHTML="")}function N(n){let s=n.provider&&t.providers[n.provider],d=s&&e.get(s.adapter);if(d&&d.destroy)try{d.destroy({id:n.instanceId,el:n.box},s)}catch(w){}}function Ze(n){let s=n.cfg.refreshSec;if(!s||n.cfg.maxRefresh&&n.tries>=n.cfg.maxRefresh)return;let d=()=>{n.refreshTimer=setTimeout(()=>{if(!f.has(n.instanceId))return;let w=n.el.getBoundingClientRect();w.bottom>0&&w.top<window.innerHeight&&document.visibilityState==="visible"?(n.tries++,K(n)):d()},s*1e3)};d(),n.cleanup.push(()=>clearTimeout(n.refreshTimer))}function K(n){n.status==="loading"||n.status==="queued"||(N(n),P(n),n.status="idle",n.consentSkipped=!1,J(n))}function G(n){N(n),P(n),A&&A.unobserve(n.el),f.delete(n.instanceId)}function C(n){return{slot:n.name,id:n.instanceId,provider:n.provider,status:n.status,el:n.el}}return{init:We,isInitialized:()=>u!==null,whenReady:()=>u,on:r.on.bind(r),off:r.off.bind(r),registerAdapter:(n,s)=>e.set(n,s),setTargeting(n){Object.entries(n||{}).forEach(([s,d])=>{d==null?(delete i[s],t&&delete t.targeting[s]):(i[s]=d,t&&(t.targeting[s]=d))})},refresh(n){for(let s of f.values())(!n||n.includes(s.name))&&K(s)},pageView(){if(l){for(let n of[...f.values()])G(n);document.querySelectorAll("[data-ual-id]").forEach(ie),t=k(),V(document)}},getSlots:()=>[...f.values()].map(C),getConsent:()=>a,debug:Y}}var Pe={name:"json",async request(e,r,t){let o={site:t.site,page:t.page,device:t.device,viewport:t.viewport,targeting:t.targeting,consent:{gdprApplies:t.consent.gdprApplies,tcString:t.consent.tcString,granted:t.consent.granted},slots:e.map(l=>({id:l.id,name:l.name,sizes:l.sizes,params:l.params}))},i=await fetch(r.endpoint,{method:"POST",headers:{"Content-Type":"application/json",...r.headers},body:JSON.stringify(o),credentials:r.withCredentials&&t.consent.granted?"include":"omit",keepalive:!1});if(i.status===204)return{};if(!i.ok)throw new Error("decide HTTP "+i.status);let a=await i.json();r.map&&typeof window[r.map]=="function"&&(a=window[r.map](a,e));let c={};return(a.ads||[]).forEach(l=>{l&&l.slotId&&(c[l.slotId]=l)}),c}};var Le={name:"iframe",async request(e,r,t){let o={};return e.forEach(i=>{let[a,c]=i.sizes&&i.sizes[0]||[i.params.width||300,i.params.height||250],l=fe(r.url,{params:i.params,width:a,height:c,site:t.site,slot:i.name,device:t.device,cb:W(),page:t.page,consent:{tcString:t.consent.tcString,gdpr:t.consent.gdprApplies?1:0}});o[i.id]={type:"url",url:l,width:a,height:c,sandbox:r.sandbox||void 0}}),o}};function je(e){return e.server.replace(/\/$/,"")+(e.deliveryPath||"/www/delivery")}var qe={name:"revive",async request(e,r,t){let o={};return e.forEach(i=>{if(i.params.zoneid==null){S(`revive: zoneid mancante per lo slot "${i.name}", slot saltato`);return}let[a,c]=i.sizes&&i.sizes[0]||[300,250],l=new URLSearchParams({zoneid:i.params.zoneid,cb:W()});t.page.ref&&l.set("referer",t.page.ref),Object.entries(i.params.vars||{}).forEach(([u,f])=>l.set(u,f)),o[i.id]={type:"url",url:`${je(r)}/afr.php?${l}`,width:a,height:c}}),o}},Re={name:"revive-async",async fill(e,r){let t={},o=`${je(r)}/asyncjs.php`,i=e.filter(l=>l.params.zoneid!=null?!0:(S(`revive-async: zoneid mancante per lo slot "${l.name}", slot saltato`),t[l.id]={filled:!1},!1));if(!i.length)return t;let a=i.map(l=>{let u=document.createElement("ins");return u.setAttribute("data-revive-zoneid",l.params.zoneid),u.setAttribute("data-revive-id",r.reviveId),Object.entries(l.params.vars||{}).forEach(([f,y])=>u.setAttribute("data-revive-"+f,y)),l.el.appendChild(u),new Promise(f=>{let y=p=>{E.disconnect(),clearTimeout(A);let v=u.getBoundingClientRect();t[l.id]={filled:p,width:Math.round(v.width),height:Math.round(v.height)},f()},E=new MutationObserver(()=>{u.querySelector("img,iframe,a,div,embed")&&y(!0)});E.observe(u,{childList:!0,subtree:!0});let A=setTimeout(()=>y(u.children.length>0),r.fillTimeoutMs||2500)})}),c=window.reviveAsync&&window.reviveAsync[r.reviveId];return c&&typeof c.refresh=="function"?c.refresh():await $(o),await Promise.all(a),t}};var ut=0,ne=new Map;function ft(e,r){return e.replace(/\{([\w.]+)\}/g,(t,o)=>{let i=o.split(".").reduce((a,c)=>a==null?void 0:a[c],r);return i==null?"":String(i)})}var re=new Set;function pt(e,r){let t=r||{};re.forEach(o=>{if(!(o in t)){try{e.clearTargeting(o)}catch(i){}re.delete(o)}}),Object.entries(t).forEach(([o,i])=>{e.setTargeting(o,i),re.add(o)})}var _e={name:"gpt",async init(e,r){window.googletag=window.googletag||{cmd:[]};let t=window.googletag;t.cmd.push(()=>{let o=t.pubads();e.singleRequest!==!1&&o.enableSingleRequest(),o.disableInitialLoad(),o.collapseEmptyDivs(!1),e.nonPersonalizedWithoutConsent&&r.consent&&!r.consent.granted&&o.setPrivacySettings&&o.setPrivacySettings({nonPersonalizedAds:!0}),t.enableServices()}),await $(e.src||"https://securepubads.g.doubleclick.net/tag/js/gpt.js",{crossorigin:"anonymous"})},fill(e,r,t){return new Promise(o=>{let i=window.googletag,a={},c=e.length;i.cmd.push(()=>{let l=i.pubads();pt(l,t.targeting);let u=[],f={};if(e.forEach(p=>{let v=document.createElement("div");v.id="ual-gpt-"+ ++ut,p.el.appendChild(v);let M=p.params.adUnitPath||ft(r.adUnitPath,{network:r.network,site:t.site,slot:p.name,section:p.params.section,params:p.params}),z=p.sizes.length?p.sizes:["fluid"],k=i.defineSlot(M,z,v.id);if(!k){a[p.id]={filled:!1},c--;return}k.addService(l),Object.entries(p.params.targeting||{}).forEach(([_,U])=>k.setTargeting(_,U)),ne.set(p.id,k),f[v.id]=p.id,u.push(k),i.display(v.id)}),!c)return o(a);let y,E=()=>{clearTimeout(y),l.removeEventListener("slotRenderEnded",A),Object.values(f).forEach(p=>{a[p]||(a[p]={filled:!1})}),o(a)},A=p=>{let v=f[p.slot.getSlotElementId()];if(!v||a[v])return;let[M,z]=Array.isArray(p.size)?p.size:[0,0];a[v]={filled:!p.isEmpty,width:M,height:z,meta:{advertiserId:p.advertiserId,lineItemId:p.lineItemId,creativeId:p.creativeId}},--c===0&&E()};l.addEventListener("slotRenderEnded",A),y=setTimeout(E,r.fillTimeoutMs||4e3),l.refresh(u)})})},destroy(e){let r=ne.get(e.id);r&&window.googletag&&window.googletag.destroySlots&&(window.googletag.destroySlots([r]),ne.delete(e.id))}};var Ue={name:"adsense",async init(e){await $(`https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=${encodeURIComponent(e.client)}`,{crossorigin:"anonymous"})},fill(e,r){return Promise.all(e.map(t=>new Promise(o=>{let i=document.createElement("ins");i.className="adsbygoogle",i.setAttribute("data-ad-client",r.client),i.setAttribute("data-ad-slot",t.params.slot);let[a,c]=t.sizes[0]||[];t.params.format||!a?(i.style.display="block",i.setAttribute("data-ad-format",t.params.format||"auto"),t.params.responsive!==!1&&i.setAttribute("data-full-width-responsive","true")):i.style.cssText=`display:inline-block;width:${a}px;height:${c}px`,r.test&&i.setAttribute("data-adtest","on"),t.el.appendChild(i);let l=y=>{u.disconnect(),clearTimeout(f);let E=i.getBoundingClientRect();o([t.id,{filled:y,width:Math.round(E.width),height:Math.round(E.height)}])},u=new MutationObserver(()=>{let y=i.getAttribute("data-ad-status");y==="filled"?l(!0):y==="unfilled"&&l(!1)});u.observe(i,{attributes:!0,attributeFilter:["data-ad-status"]});let f=setTimeout(()=>l(!!i.querySelector("iframe")),r.fillTimeoutMs||4e3);try{(window.adsbygoogle=window.adsbygoogle||[]).push({})}catch(y){l(!1)}}))).then(t=>Object.fromEntries(t))}};function mt(e){let r=e.reduce((o,i)=>o+(i.weight||1),0),t=Math.random()*r;for(let o of e)if(t-=o.weight||1,t<=0)return o;return e[e.length-1]}var Ne={name:"house",async request(e,r,t){let o=Date.now(),i={};return e.forEach(a=>{let c=(r.creatives||[]).filter(l=>!(l.slots&&!l.slots.includes(a.name)||l.devices&&!l.devices.includes(t.device)||l.from&&o<Date.parse(l.from)||l.to&&o>Date.parse(l.to)+864e5||a.sizes.length&&!a.sizes.some(([u,f])=>u===l.width&&f===l.height)));if(c.length){let l=mt(c);i[a.id]={...l,type:l.type||(l.html?"html":"image")}}}),i}};var gt="0.1.1";function De(){let e=new Map(Object.entries({json:Pe,iframe:Le,revive:qe,"revive-async":Re,gpt:_e,adsense:Ue,house:Ne}));return{...$e(e),version:gt}}var Fe="ual";(function(){let r=window[Fe]||{};if(r.version)return;let o={...De(),cmd:{push:u=>i(u)}};function i(u){try{u(o)}catch(f){S("Errore in comando cmd",f)}}let a=Array.isArray(r.cmd)?r.cmd:[];window[Fe]=o;let c=document.currentScript||document.querySelector('script[data-ual-config],script[data-config][src*="ual"]'),l=c&&(c.getAttribute("data-ual-config")||c.getAttribute("data-config"));if(a.forEach(i),l){let u=()=>o.init(l).catch(f=>S("Init fallito",f));document.readyState==="loading"?document.addEventListener("DOMContentLoaded",u):u()}})();})();
|
|
12
|
+
})();<\/script>`}function ee(e){return String(e).replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">")}function st(e,r){let t='<!doctype html><html><head><meta charset="utf-8"><base target="_blank"><style>html,body{margin:0;padding:0;overflow:hidden;background:transparent}img{display:block;border:0;max-width:100%}</style>'+ot(r,e.clickUrl)+"</head><body>",o="";if(e.type==="image"){let i=`<img src="${ee(e.src)}" width="${e.width}" height="${e.height}" alt="${ee(e.alt||"Advertisement")}">`;o=e.clickUrl?`<a href="${ee(e.clickUrl)}" rel="noopener sponsored" onclick="parent.postMessage({ual:'${r}',cmd:'click'},'*')">${i}</a>`:i}else o=e.html||"";return t+o+"</body></html>"}function Ce(e,r,{slotId:t,onClick:o,onClose:i}={}){at();let a="ual"+ ++rt,c=document.createElement("iframe");c.title="Advertisement",c.setAttribute("scrolling","no"),c.setAttribute("frameborder","0"),c.setAttribute("loading","eager"),c.setAttribute("referrerpolicy","strict-origin-when-cross-origin"),c.style.cssText=`border:0;display:block;margin:0 auto;width:${r.width}px;height:${r.height}px;max-width:100%`,c.width=r.width,c.height=r.height;let l=it(r);return l!==null&&c.setAttribute("sandbox",l),r.type==="url"?c.src=r.url:c.srcdoc=st(r,a),te.set(a,{iframe:c,slotId:t,ad:r,original:{w:r.width,h:r.height},onClick:()=>{q(r.trackers&&r.trackers.click),o&&o()},onClose:i}),e.innerHTML="",e.appendChild(c),{iframe:c,channel:a,destroy:()=>te.delete(a)}}var Me=!1;function at(){Me||(Me=!0,window.addEventListener("message",lt))}function lt(e){let r=e.data;if(!r||typeof r!="object"||!r.ual)return;let t=te.get(r.ual);if(!(!t||e.source!==t.iframe.contentWindow))switch(r.cmd){case"resize":{let o=Math.min(+r.w||t.original.w,B),i=Math.min(+r.h||t.original.h,B);t.iframe.style.width=o+"px",t.iframe.style.height=i+"px";break}case"collapse":t.iframe.style.width=t.original.w+"px",t.iframe.style.height=t.original.h+"px";break;case"close":t.onClose&&t.onClose();break;case"click":t.onClick();break;default:}}function Oe(e,{threshold:r=.5,durationMs:t=1e3}={},o){if(!("IntersectionObserver"in window))return()=>{};let i=null,a=!1,c=!1,l=()=>{a||i||document.visibilityState!=="visible"||(i=setTimeout(()=>{a=!0,E(),o()},t))},u=()=>{clearTimeout(i),i=null},f=new IntersectionObserver(A=>{A.forEach(p=>{c=p.intersectionRatio>=r,c?l():u()})},{threshold:[0,r,1]}),y=()=>document.visibilityState==="visible"&&c?l():u();document.addEventListener("visibilitychange",y),f.observe(e);function E(){u(),f.disconnect(),document.removeEventListener("visibilitychange",y)}return E}var ct=new Set(["unconfigured","disabled","closed"]),dt=242500;function $e(e){let r=ce(),t=null,o=null,i={},a={gdprApplies:void 0,tcString:"",purposes:{},granted:!1,source:"pending"},c=Promise.resolve(a),l=!1,u=null,f=new Map,y=new Map,E=0,A=null,p=null,v=new Set,M=null;function z(){return{site:t.site,page:{url:location.href,path:location.pathname,ref:document.referrer,title:document.title},device:pe(),viewport:{w:window.innerWidth,h:window.innerHeight},targeting:{...t.targeting},consent:a,debug:ue()}}function k(){let n=ye(o);return Object.assign(n.targeting,i),n}function _(n){let s=a;if(!(s.granted===n.granted&&s.tcString===n.tcString&&s.source===n.source)&&(a=n,r.emit("consent",a),!s.granted&&n.granted))for(let d of[...f.values()])d.consentSkipped&&U(d)}function U(n,s=20){if(f.get(n.instanceId)===n){if(n.status==="loading"||n.status==="queued"){s>0&&setTimeout(()=>U(n,s-1),250);return}K(n)}}function We(n){return u?(S("init gi\xE0 eseguito"),u):(u=He(n).catch(s=>{throw u=null,s}),u)}async function He(n){o=await ge(n),o.debug&&Y(!0),he(o,e),t=k(),I("Config",t),c=Ae(t.consent,_).then(s=>(_(s),s)),document.readyState==="loading"&&await new Promise(s=>document.addEventListener("DOMContentLoaded",s,{once:!0})),l=!0,Xe(),V(document),Je(),r.emit("ready",{site:t.site})}function V(n){let s=[];n.nodeType===1&&n.matches&&n.matches("[data-ad-slot]")&&s.push(n),n.querySelectorAll&&n.querySelectorAll("[data-ad-slot]").forEach(d=>s.push(d)),s.forEach(Be)}function Be(n){let s=n.dataset.ualId;if(!s)return oe(n);f.has(s)||ct.has(n.dataset.ualStatus)||(ie(n),oe(n))}function ie(n){delete n.dataset.ualId,delete n.dataset.ualStatus,n.querySelectorAll(":scope > .ual-label, :scope > .ual-creative").forEach(s=>s.remove()),n.classList.remove("ual-slot","ual-filled"),n.style.display="",n.style.minHeight=""}function oe(n){let s=n.getAttribute("data-ad-slot"),d=t.slots[s];if(n.dataset.ualId=s+"#"+ ++E,!d){I("Slot non configurato, ignorato:",s),n.dataset.ualStatus="unconfigured";return}if(d.enabled===!1){I("Slot disabilitato:",s),n.dataset.ualStatus="disabled",X(n,d);return}let w={};try{w=n.dataset.adParams?JSON.parse(n.dataset.adParams):{}}catch(T){S("data-ad-params non \xE8 JSON valido",n)}let h={instanceId:n.dataset.ualId,name:s,el:n,cfg:d,params:w,status:"idle",cleanup:[],tries:0,consentSkipped:!1};f.set(h.instanceId,h),Ve(h),r.emit("slotRegistered",C(h)),(d.lazy!==void 0?d.lazy:t.lazy.enabled)&&A?A.observe(n):J(h)}function Ve(n){let{el:s,cfg:d}=n;if(d.minHeight&&(s.style.minHeight=d.minHeight+"px"),s.classList.add("ual-slot"),d.label){let h=document.createElement("div");h.className="ual-label",h.textContent=d.label,h.style.cssText="font:10px/1.4 sans-serif;color:#888;text-align:center;text-transform:uppercase;letter-spacing:.05em",s.appendChild(h)}let w=document.createElement("div");w.className="ual-creative",s.appendChild(w),n.box=w}function Je(){"MutationObserver"in window&&(p=new MutationObserver(n=>{for(let s of n)s.removedNodes.forEach(d=>{if(d.nodeType===1)for(let w of[...f.values()])(d===w.el||d.contains(w.el))&&G(w)}),s.addedNodes.forEach(d=>{d.nodeType===1&&V(d)})}),p.observe(document.body||document.documentElement,{childList:!0,subtree:!0}))}function Xe(){"IntersectionObserver"in window&&(A=new IntersectionObserver(n=>{n.forEach(s=>{if(!s.isIntersecting)return;A.unobserve(s.target);let d=f.get(s.target.dataset.ualId);d&&J(d)})},{rootMargin:t.lazy.fetchMargin}))}function J(n){n.status!=="loading"&&(n.status="queued",v.add(n),clearTimeout(M),M=setTimeout(Ke,30))}function Ke(){let n=[...v];v=new Set,n.length&&se(n,0)}async function se(n,s){let d=new Map,w=[];for(let h of n){let b=(h.cfg.providers||[])[s];if(!b){w.push(h);continue}let T=typeof b=="string"?b:b.id;d.has(T)||d.set(T,[]),d.get(T).push(h)}w.forEach(Ye),await Promise.all([...d.entries()].map(async([h,b])=>{let T=await Qe(h,b,s);T.length&&await se(T,s+1)}))}async function Ge(n){let s=t.providers[n];if(!s)throw new Error("Provider non definito: "+n);let d=e.get(s.adapter);if(!d)throw new Error("Adapter non registrato: "+s.adapter);return y.has(n)||y.set(n,Promise.resolve(d.init?d.init(s,z()):null)),await y.get(n),{adapter:d,pcfg:s}}async function Qe(n,s,d){let w=t.providers[n];if((!w||w.consent!=="contextual")&&await c,s=s.filter(m=>f.get(m.instanceId)===m),!s.length)return[];let h,b;try{({adapter:h,pcfg:b}=await Ge(n))}catch(m){return S(m.message),r.emit("error",{provider:n,error:m}),s}if(b.consent==="required"&&!a.granted)return I(`Provider ${n} saltato: consenso non concesso`),s.forEach(m=>{m.consentSkipped=!0}),s;let T=z(),O=s.map(m=>{m.status="loading",m.provider=n;let g=m.cfg.providers[d];return{id:m.instanceId,name:m.name,el:m.box,sizes:ve(m.cfg),params:{...typeof g=="object"?g.params:{},...m.params},cfg:m.cfg}});O.forEach(m=>r.emit("slotRequested",{slot:m.name,id:m.id,provider:n})),I(`Richiesta a ${n} (${b.adapter})`,O.map(m=>m.name));let le=b.timeoutMs||t.providerTimeoutMs,L=[];try{if(h.fill){let m=await R(h.fill(O,b,T),le+2e3,{});s.forEach((g,Q)=>{let x=m[O[Q].id];x&&x.filled?ae(g,{width:x.width,height:x.height,selfRendered:!0,meta:x.meta}):(N(g),P(g),L.push(g))})}else{let m=await R(h.request(O,b,T),le,{});s.forEach((g,Q)=>{let x=m[O[Q].id];if(!x||!x.html&&!x.src&&!x.url){L.push(g);return}let D=ze(x);if(!D.ok){S(`Annuncio scartato (${n}, slot ${g.name}): ${D.reason}`),r.emit("error",{provider:n,slot:g.name,error:new Error(D.reason)}),L.push(g);return}let j=D.ad,et=Ce(g.box,j,{slotId:g.instanceId,onClick:()=>r.emit("slotClick",C(g)),onClose:()=>{G(g),g.el.dataset.ualStatus="closed",X(g.el,g.cfg,!0)}});g.cleanup.push(et.destroy),q(j.trackers.impression),ae(g,{width:j.width,height:j.height,ad:j})})}}catch(m){S(`Errore provider ${n}`,m),r.emit("error",{provider:n,error:m}),s.forEach(g=>{g.status==="loading"&&(N(g),P(g),L.push(g))})}return L}function ae(n,s){n.status="filled",n.el.dataset.ualStatus="filled",n.el.classList.add("ual-filled"),n.el.style.display="",r.emit("slotRendered",{...C(n),width:s.width,height:s.height,meta:s.meta});let d={...t.viewability,...n.cfg.viewability};(s.width||0)*(s.height||0)>dt&&!(n.cfg.viewability&&n.cfg.viewability.threshold!==void 0)&&(d.threshold=Math.min(d.threshold,.3));let h=n.box.firstElementChild||n.box,b=Oe(h,d,()=>{s.ad&&q(s.ad.trackers.viewable),r.emit("slotViewable",C(n)),Ze(n)});n.cleanup.push(b)}function Ye(n){n.status="empty",n.el.dataset.ualStatus="empty",P(n),X(n.el,n.cfg),r.emit("slotEmpty",C(n))}function X(n,s,d){(d||(s.collapseEmpty!==void 0?s.collapseEmpty:t&&t.collapseEmpty))&&(n.style.display="none",n.style.minHeight="")}function P(n){n.cleanup.forEach(s=>{try{s()}catch(d){}}),n.cleanup=[],n.box&&(n.box.innerHTML="")}function N(n){let s=n.provider&&t.providers[n.provider],d=s&&e.get(s.adapter);if(d&&d.destroy)try{d.destroy({id:n.instanceId,el:n.box},s)}catch(w){}}function Ze(n){let s=n.cfg.refreshSec;if(!s||n.cfg.maxRefresh&&n.tries>=n.cfg.maxRefresh)return;let d=()=>{n.refreshTimer=setTimeout(()=>{if(!f.has(n.instanceId))return;let w=n.el.getBoundingClientRect();w.bottom>0&&w.top<window.innerHeight&&document.visibilityState==="visible"?(n.tries++,K(n)):d()},s*1e3)};d(),n.cleanup.push(()=>clearTimeout(n.refreshTimer))}function K(n){n.status==="loading"||n.status==="queued"||(N(n),P(n),n.status="idle",n.consentSkipped=!1,J(n))}function G(n){N(n),P(n),A&&A.unobserve(n.el),f.delete(n.instanceId)}function C(n){return{slot:n.name,id:n.instanceId,provider:n.provider,status:n.status,el:n.el}}return{init:We,isInitialized:()=>u!==null,whenReady:()=>u,on:r.on.bind(r),off:r.off.bind(r),registerAdapter:(n,s)=>e.set(n,s),setTargeting(n){Object.entries(n||{}).forEach(([s,d])=>{d==null?(delete i[s],t&&delete t.targeting[s]):(i[s]=d,t&&(t.targeting[s]=d))})},refresh(n){for(let s of f.values())(!n||n.includes(s.name))&&K(s)},pageView(){if(l){for(let n of[...f.values()])G(n);document.querySelectorAll("[data-ual-id]").forEach(ie),t=k(),V(document)}},getSlots:()=>[...f.values()].map(C),getConsent:()=>a,debug:Y}}var Pe={name:"json",async request(e,r,t){let o={site:t.site,page:t.page,device:t.device,viewport:t.viewport,targeting:t.targeting,consent:{gdprApplies:t.consent.gdprApplies,tcString:t.consent.tcString,granted:t.consent.granted},slots:e.map(l=>({id:l.id,name:l.name,sizes:l.sizes,params:l.params}))},i=await fetch(r.endpoint,{method:"POST",headers:{"Content-Type":"application/json",...r.headers},body:JSON.stringify(o),credentials:r.withCredentials&&t.consent.granted?"include":"omit",keepalive:!1});if(i.status===204)return{};if(!i.ok)throw new Error("decide HTTP "+i.status);let a=await i.json();r.map&&typeof window[r.map]=="function"&&(a=window[r.map](a,e));let c={};return(a.ads||[]).forEach(l=>{l&&l.slotId&&(c[l.slotId]=l)}),c}};var Le={name:"iframe",async request(e,r,t){let o={};return e.forEach(i=>{let[a,c]=i.sizes&&i.sizes[0]||[i.params.width||300,i.params.height||250],l=fe(r.url,{params:i.params,width:a,height:c,site:t.site,slot:i.name,device:t.device,cb:W(),page:t.page,consent:{tcString:t.consent.tcString,gdpr:t.consent.gdprApplies?1:0}});o[i.id]={type:"url",url:l,width:a,height:c,sandbox:r.sandbox||void 0}}),o}};function je(e){return e.server.replace(/\/$/,"")+(e.deliveryPath||"/www/delivery")}var qe={name:"revive",async request(e,r,t){let o={};return e.forEach(i=>{if(i.params.zoneid==null){S(`revive: zoneid mancante per lo slot "${i.name}", slot saltato`);return}let[a,c]=i.sizes&&i.sizes[0]||[300,250],l=new URLSearchParams({zoneid:i.params.zoneid,cb:W()});t.page.ref&&l.set("referer",t.page.ref),Object.entries(i.params.vars||{}).forEach(([u,f])=>l.set(u,f)),o[i.id]={type:"url",url:`${je(r)}/afr.php?${l}`,width:a,height:c}}),o}},Re={name:"revive-async",async fill(e,r){let t={},o=`${je(r)}/asyncjs.php`,i=e.filter(l=>l.params.zoneid!=null?!0:(S(`revive-async: zoneid mancante per lo slot "${l.name}", slot saltato`),t[l.id]={filled:!1},!1));if(!i.length)return t;let a=i.map(l=>{let u=document.createElement("ins");return u.setAttribute("data-revive-zoneid",l.params.zoneid),u.setAttribute("data-revive-id",r.reviveId),Object.entries(l.params.vars||{}).forEach(([f,y])=>u.setAttribute("data-revive-"+f,y)),l.el.appendChild(u),new Promise(f=>{let y=p=>{E.disconnect(),clearTimeout(A);let v=u.getBoundingClientRect();t[l.id]={filled:p,width:Math.round(v.width),height:Math.round(v.height)},f()},E=new MutationObserver(()=>{u.querySelector("img,iframe,a,div,embed")&&y(!0)});E.observe(u,{childList:!0,subtree:!0});let A=setTimeout(()=>y(u.children.length>0),r.fillTimeoutMs||2500)})}),c=window.reviveAsync&&window.reviveAsync[r.reviveId];return c&&typeof c.refresh=="function"?c.refresh():await $(o),await Promise.all(a),t}};var ut=0,ne=new Map;function ft(e,r){return e.replace(/\{([\w.]+)\}/g,(t,o)=>{let i=o.split(".").reduce((a,c)=>a==null?void 0:a[c],r);return i==null?"":String(i)})}var re=new Set;function pt(e,r){let t=r||{};re.forEach(o=>{if(!(o in t)){try{e.clearTargeting(o)}catch(i){}re.delete(o)}}),Object.entries(t).forEach(([o,i])=>{e.setTargeting(o,i),re.add(o)})}var _e={name:"gpt",async init(e,r){window.googletag=window.googletag||{cmd:[]};let t=window.googletag;t.cmd.push(()=>{let o=t.pubads();e.singleRequest!==!1&&o.enableSingleRequest(),o.disableInitialLoad(),o.collapseEmptyDivs(!1),e.nonPersonalizedWithoutConsent&&r.consent&&!r.consent.granted&&o.setPrivacySettings&&o.setPrivacySettings({nonPersonalizedAds:!0}),t.enableServices()}),await $(e.src||"https://securepubads.g.doubleclick.net/tag/js/gpt.js",{crossorigin:"anonymous"})},fill(e,r,t){return new Promise(o=>{let i=window.googletag,a={},c=e.length;i.cmd.push(()=>{let l=i.pubads();pt(l,t.targeting);let u=[],f={};if(e.forEach(p=>{let v=document.createElement("div");v.id="ual-gpt-"+ ++ut,p.el.appendChild(v);let M=p.params.adUnitPath||ft(r.adUnitPath,{network:r.network,site:t.site,slot:p.name,section:p.params.section,params:p.params}),z=p.sizes.length?p.sizes:["fluid"],k=i.defineSlot(M,z,v.id);if(!k){a[p.id]={filled:!1},c--;return}k.addService(l),Object.entries(p.params.targeting||{}).forEach(([_,U])=>k.setTargeting(_,U)),ne.set(p.id,k),f[v.id]=p.id,u.push(k),i.display(v.id)}),!c)return o(a);let y,E=()=>{clearTimeout(y),l.removeEventListener("slotRenderEnded",A),Object.values(f).forEach(p=>{a[p]||(a[p]={filled:!1})}),o(a)},A=p=>{let v=f[p.slot.getSlotElementId()];if(!v||a[v])return;let[M,z]=Array.isArray(p.size)?p.size:[0,0];a[v]={filled:!p.isEmpty,width:M,height:z,meta:{advertiserId:p.advertiserId,lineItemId:p.lineItemId,creativeId:p.creativeId}},--c===0&&E()};l.addEventListener("slotRenderEnded",A),y=setTimeout(E,r.fillTimeoutMs||4e3),l.refresh(u)})})},destroy(e){let r=ne.get(e.id);r&&window.googletag&&window.googletag.destroySlots&&(window.googletag.destroySlots([r]),ne.delete(e.id))}};var Ue={name:"adsense",async init(e){await $(`https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=${encodeURIComponent(e.client)}`,{crossorigin:"anonymous"})},fill(e,r){return Promise.all(e.map(t=>new Promise(o=>{let i=document.createElement("ins");i.className="adsbygoogle",i.setAttribute("data-ad-client",r.client),i.setAttribute("data-ad-slot",t.params.slot);let[a,c]=t.sizes[0]||[];t.params.format||!a?(i.style.display="block",i.setAttribute("data-ad-format",t.params.format||"auto"),t.params.responsive!==!1&&i.setAttribute("data-full-width-responsive","true")):i.style.cssText=`display:inline-block;width:${a}px;height:${c}px`,r.test&&i.setAttribute("data-adtest","on"),t.el.appendChild(i);let l=y=>{u.disconnect(),clearTimeout(f);let E=i.getBoundingClientRect();o([t.id,{filled:y,width:Math.round(E.width),height:Math.round(E.height)}])},u=new MutationObserver(()=>{let y=i.getAttribute("data-ad-status");y==="filled"?l(!0):y==="unfilled"&&l(!1)});u.observe(i,{attributes:!0,attributeFilter:["data-ad-status"]});let f=setTimeout(()=>l(!!i.querySelector("iframe")),r.fillTimeoutMs||4e3);try{(window.adsbygoogle=window.adsbygoogle||[]).push({})}catch(y){l(!1)}}))).then(t=>Object.fromEntries(t))}};function mt(e){let r=e.reduce((o,i)=>o+(i.weight||1),0),t=Math.random()*r;for(let o of e)if(t-=o.weight||1,t<=0)return o;return e[e.length-1]}var Ne={name:"house",async request(e,r,t){let o=Date.now(),i={};return e.forEach(a=>{let c=(r.creatives||[]).filter(l=>!(l.slots&&!l.slots.includes(a.name)||l.devices&&!l.devices.includes(t.device)||l.from&&o<Date.parse(l.from)||l.to&&o>Date.parse(l.to)+864e5||a.sizes.length&&!a.sizes.some(([u,f])=>u===l.width&&f===l.height)));if(c.length){let l=mt(c);i[a.id]={...l,type:l.type||(l.html?"html":"image")}}}),i}};var gt="0.1.2";function De(){let e=new Map(Object.entries({json:Pe,iframe:Le,revive:qe,"revive-async":Re,gpt:_e,adsense:Ue,house:Ne}));return{...$e(e),version:gt}}var Fe="ual";(function(){let r=window[Fe]||{};if(r.version)return;let o={...De(),cmd:{push:u=>i(u)}};function i(u){try{u(o)}catch(f){S("Errore in comando cmd",f)}}let a=Array.isArray(r.cmd)?r.cmd:[];window[Fe]=o;let c=document.currentScript||document.querySelector('script[data-ual-config],script[data-config][src*="ual"]'),l=c&&(c.getAttribute("data-ual-config")||c.getAttribute("data-config"));if(a.forEach(i),l){let u=()=>o.init(l).catch(f=>S("Init fallito",f));document.readyState==="loading"?document.addEventListener("DOMContentLoaded",u):u()}})();})();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "universal-ad-loader",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Loader pubblicitario universale: un tag per sito, configurazione centralizzata, waterfall tra provider e consenso TCF. Componenti per React, Next.js, Vue e Astro.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "ArdensLab",
|