Jak vzniká cena léků, co ji tvoří a kdy do ní promlouvá stát

27. 9. 2023

Sdílet

Autor: Depositphotos
Mysleli jste si, že stát nakupuje léky a určuje jejich cenu? Zatímco první tvrzení je až na výjimky chybné, u druhého máte zčásti pravdu. Vysvětlíme vám, jak se tvoří cena léků, kdy ji reguluje stát a jaké nástroje k tomu používá. A dozvíte se i to, proč je to složité s doplatky.

Léky jsou speciální kategorií zboží, která je přísně hlídána a regulována jak ze strany státu, tak evropských úřadů. Před uvedením na trh musí projít klinickými zkouškami (tj. prokázání účinnosti a bezpečnosti). Pokud je splní, pak i povinnou registrací. Po uvedení na trh mohou být zcela, či zčásti hrazené z veřejných peněz a po celou dobu podávání pacientům jsou sledovány jejich benefity i rizika.

Co se dozvíte v článku
  1. Kdy cenu určuje trh
  2. Kdy a jak do cen vstupuje stát
  3. Co je doplatek a kdy vzniká
  4. Proč se výše doplatků liší
  5. Zvýší ceny změna DPH?

V následujícím textu si vysvětlíme, jak vzniká cena léku a co všechno ji ovlivňuje. A také to, proč se doplatky liší v jednotlivých lékárnách i napříč nimi.

Kdy cenu určuje trh

Mezi léky, u nichž stát do ceny nezasahuje, patří ty volně prodejné. Typicky běžné tablety, tobolky či sirupy na horečku a tlumení bolesti. Cena není také nijak regulovaná u doplňků stravy, což jsou fakticky potraviny. Patří mezi ně vitaminy nebo čaje. A do této skupiny můžeme zařadit také kosmetiku, jež si našla své místo i v lékárnách.

„Ceny u nich určuje trh,“ potvrzuje lékárník a viceprezident České lékárnické komory Martin Kopecký. Výrobci, distributoři a lékárny tedy u nich nemají žádné státem vytyčené mantinely. A stane-li se například to, že vzrostou náklady na výrobu, firmy mohou bez jakýchkoliv omezení cenu navýšit a je na zákazníkovi, zda ji akceptuje, či nikoliv.

Stejná je situace u léků na předpis, ale nehrazených z veřejného zdravotního pojištění. Jde třeba o hypnotika, antikoncepci či léky na potenci. „Také jejich ceny jsou neregulované a určované trhem,“ potvrzuje Martin Kopecký.

To také znamená, že jejich cena se nezapočítává do tzv. ochranného limitu. Tedy hranice vytyčující to, kolik pacient za rok může maximálně dát za tzv. doplatky za léky. Nad tuto hranici mu doplatky zpětně a jednou čtvrtletně vrací zdravotní pojišťovna.

Lékárníci chtějí, aby pacienti neplatili doplatky nad limit a nemuseli čekat na vracení peněz Přečtěte si také:

Lékárníci chtějí, aby pacienti neplatili doplatky nad limit a nemuseli čekat na vracení peněz

Kdy a jak do cen vstupuje stát

Jiná situace je u tzv. regulovaných léčiv„Jsou to všechna ta, která mají úhradu ze zdravotního pojištění. U nich je, až na pár výjimek, cena vždy regulovaná státem,“ vysvětluje lékárník Martin Kopecký. Takových léků přitom není zanedbatelné množství. Jsou lékárny, třeba ty nemocniční, na poliklinikách nebo v menších obcích, kde regulovaná léčiva tvoří většinu sortimentu.

Cenová regulace má několik podob. První z nich je tzv. maximální cena, neboli cena původce. To je strop, do nějž se musí vejít výrobce. Tento strop ale zároveň umožňuje, aby farmaceutická společnost dodávala na trh za ceny nižší, než je ta maximální. Cena stanovená výrobcem se proto pro jednotlivé distributory a lékárny může i přes regulaci lišit. Například větší lékárna díky vyšším objemům vydaných léčiv si může přijít na lepší cenu než lékárna venkovská. Ale také nemusí. Nicméně vždy platí, že ze strany výrobce nesmí být překročeno maximum. 

Maximální cenu v ČR určuje Státní ústav pro kontrolu léčiv (SÚKL). K jejímu stanovení používá tři možné postupy. Nejčastěji je odvozena od průměru tří nejnižších cen ze zemí referenčního koše. Ten tvoří země EU s výjimkou devíti – Bulharska, ČR, Estonska, Lucemburska, Rakouska, Rumunska, Řecka, Kypru a Malty.

Platíte doplatky za léky na recept?

Další regulací, která krotí ceny hrazených léčiv, je zastropování přirážky. Jde o podíl, jenž si k ceně výrobce mohou přičíst distributoři a lékárny. Výše přirážky se pohybuje od dvou do 37 procent a platí, že čím vyšší je cena léku, tím nižší je procento přirážky. Přirážka je jedna pomyslná hromádka, kterou si distributoři a lékárny rozdělí sami mezi sebe. V jakém poměru, to je věcí jejich dohody. Část přirážky může připadnout také výrobci, a to v případě, že výrobce je zároveň také distributorem léku.

Podle lékárnické komory jsou při rozdělování přirážky menší lékárny v nevýhodě oproti těm větším. „Protože ty si mohou dohodnout výhodnější podmínky,“ říká Martin Kopecký.

Co je doplatek a kdy vzniká

Další formou regulace je úhrada ze zdravotního pojištění. Také tu vyhlašuje SÚKL, ale vliv na její výši mají i zdravotním pojišťovny. Tato částka říká, jaký podíl z ceny léku bude uhrazen z veřejných peněz.

Vztah mezi cenou a úhradou je klíčový pro pacienta. Od jejich rozdílu se odvíjí doplatek, tedy částka, kterou musí v lékárně zaplatit pacient.

Pokud se úhrada zdravotních pojišťoven rovná maximální ceně, je doplatek pro pacienta nulový. To ale neznamená, že lék je zdarma. Není, je uhrazený z veřejného zdravotního pojištění.

Pak jsou situace, a ty jsou častější, kdy úhrada zdravotních pojišťoven je nižší než maximální cena. V takovém případě musí pacient sáhnout do vlastní peněženky. „Doplatek je rozdíl mezi konečnou cenou léku a stanovenou úhradou. To znamená, že je-li třeba cena léku 100 Kč a úhrada je 80 Kč, pak doplatek bude činit 20 Kč,“ uvádí příklad Martin Kopecký.

Značná část doplatků je takzvaně započitatelná. To znamená, že se jich týkají ochranné limity, které říkají, kolik maximálně na doplatcích za rok zaplatí dospělý, kolik dítě, senior nebo invalidní pacient. Pokud tento strop pacient překročí, jeho zdravotní pojišťovna mu peníze zaplacené nad tento limit zpětně vrátí.

Proč se výše doplatků liší

Zatímco do ceny, přirážky a úhrady stát vstupuje, výše doplatků regulována z jeho strany není. V ČR totiž neplatí předpisy, které by vedly k tomu, aby doplatky byly ve všech lékárnách shodné, nebo alespoň velmi podobné. Proto se výše doplatků u stejných léčiv liší, a to nejen mezi lékárnami, ale v čase se může lišit také v každé jednotlivé lékárně.

Rozdíly mezi doplatky přitom nemusí být malé. Nedávno jsme upozornili na výjimečný případ, kdy rozdíl činil více než šest tisíc korun.

Doplatky na léky se liší i o tisíce. Nezbývá než oběhat s receptem více lékáren Přečtěte si také:

Doplatky na léky se liší i o tisíce. Nezbývá než oběhat s receptem více lékáren

Pokud chce pacient na doplatku ušetřit, moc možností dnes nemá. Buď si musí okolní lékárny obtelefonovat, nebo oběhat a pak si vybrat tu, kde je doplatek nejnižší. Lékárny totiž nemají povinnost doplatky zveřejňovat a žádná jejich centrální databáze neexistuje.

Jak je ale možné, že se doplatky liší, když tu máme regulovanou cenu i úhradu ze zdravotního pojištění? Je to z více důvodů. 

Lékárny jednak nakupují léky za různé ceny. Již jsme si řekli, že sice existuje maximální cena, ale řada výrobců na trh dodává léky za nižší ceny, které nijak limitované nejsou. Ceny se tedy mohou ze strany výrobců lišit. Odlišná cena nemusí ale znamenat odlišnou úhradu, a proto změna ceny ze strany výrobce může vést k nižšímu, či naopak vyššímu doplatku.

Mnohem zásadnější dopad má na výši doplatků ale jiná záležitost. Takzvané revize. Jde o neustálý proces, ve kterém SÚKL přehodnocuje jak výši úhrady, tak maximální ceny. Kvůli revizím se doplatek liší nejen mezi lékárnami, ale také v samotných jednotlivých lékárnách, kde může být každý měsíc jiný.

„Na konci každého měsíce se do číselníků propisují výsledky ukončených správních řízení SÚKL, kterými se v lékárnách řídíme,“ podotýká Martin Kopecký. „Změní-li se na konci měsíce úhrada, třeba klesne z 80 Kč na 60 Kč, přičemž cena léku je stále 100 Kč, tak ze dne na den je z doplatku 20 Kč doplatek čtyřicetikorunový,“ popisuje jednu z variant lékárník. „Pokud ale výrobce sníží cenu ze 100 Kč na 80 Kč, tak poplatek klesne opět na dvacetikorunu. Pokud by cena výrobce činila 60 Kč, doplatek bude nulový, protože cena bude stejná jako úhrada zdravotních pojišťoven,“ doplňuje Martin Kopecký.

Uvádí hypotetický příklad popisující v praxi běžný průběh změn u doplatků„Lék, který stál v srpnu 100 Kč, může takto stát ještě na začátku září, ale už koncem srpna může přijít také dodávka, ve které bude ten samý lék za 80 Kč, protože jej výrobce zlevnil. Úhrada v srpnu byla 80 Kč, od 1. 9. pak 60 Kč. Dostáváme se tedy do situace, kdy doplatek na přelomu měsíců může být 20 Kč (100 − 80 nebo 80 − 60), 40 Kč (100 − 60), nebo také 0 Kč (80 − 80),“ říká Martin Kopecký.

Podle značné části lékárníků by rozdíly mezi doplatky vznikat neměly a jejich výše by měla být jednotná. Výrobci léčiv, SÚKL, ale ani ministerstvo ovšem o zavedení takové regulace neuvažují. Podle nich by to vedlo k tomu, že by dopláceli i ti pacienti, kteří dnes mají doplatky nulové. Podle Martina Kopeckého je to ale lichý argument. „Doplatky by byly v takové výši, v jaké by je pacientům určil stát,“ doplňuje lékárník.

Takhle lžou lékoví šmejdi. Tvrdí, že vyléčí srdce i cukrovku, za neúčinné léky inkasují tisíce Přečtěte si také:

Takhle lžou lékoví šmejdi. Tvrdí, že vyléčí srdce i cukrovku, za neúčinné léky inkasují tisíce

Zvýší ceny změna DPH?

Konečnou cenu léku, kterou na účtence vidí pacient, tedy tvoří cena výrobce (asi ze 70 procent), společná přirážka distributora a lékárny a také daň z přidané hodnoty (DPH).

DPH činí v současné době u léčiv deset procent. Pokud parlamentem projde tzv.  konsolidační balíček, od ledna 2024 vzroste na 12 procent. Podle Martina Kopeckého nejde o tak velký skok, aby se do cen a doplatků nějak výrazně promítl. „Léky tato změna zdraží, ale v případě doplatků půjde o zvýšení v haléřích a desetihaléřích, maximálně v korunách, protože zvýšení DPH se promítne nejen do cen, ale i do zvýšení úhrad pojišťoven,“ vysvětluje lékárník.

Pokud avizovaná změna DPH přijde, přinese i zlevnění.„U zdravotnických prostředků a potravin pro zvláštní zdravotnické účely, kam patří třeba speciální výživy pro pacienta, by se cena s 12procentí sazbou DPH snížila, protože nyní u nich DPH činí 15 procent,“ upozorňuje Martin Kopecký. Pokud se u regulované ceny sníží DPH, lékárny musí s cenou dolů„Pokud je cena regulovaná, při snižování DPH se musí přepočítat a klesnout. Pokud je to ale naopak a DPH vzrůstá, tak cena může klesnout, ale také nemusí,“ doplňuje viceprezident ČLnK.

Odborná spolupráce:

PharmDr. Martin Kopecký, Ph.D.

Viceprezident České lékárnické komory, pracuje v Lékárně Zdraví v Zábřehu na Moravě, jejímž je spolumajitelem.

Autor článku

Redaktorka Vitalia.cz. Vystudovala žurnalistiku a češtinu na Univerzitě Palackého v Olomouci, pracovala v Deníku, na webu TV Nova a iDNES.cz. Píše o zdravotnictví. Je držitelkou novinářských cen Psychiatrické společností ČLS JEP za rok 2021 a 2022. 

'; document.getElementById('preroll-iframe').onload = function () { setupIframe(); } prerollContainer = document.getElementsByClassName('preroll-container-iframe')[0]; } function setupIframe() { prerollDocument = document.getElementById('preroll-iframe').contentWindow.document; let el = prerollDocument.createElement('style'); prerollDocument.head.appendChild(el); el.innerText = "#adContainer>div:nth-of-type(1),#adContainer>div:nth-of-type(1) > iframe { width: 99% !important;height: 99% !important;max-width: 100%;}#videoContent,body{ width:100vw;height:100vh}body{ font-family:'Helvetica Neue',Arial,sans-serif}#videoContent{ overflow:hidden;background:#000}#adMuteBtn{ width:35px;height:35px;border:0;background:0 0;display:none;position:absolute;fill:rgba(230,230,230,1);bottom:20px;right:25px}"; videoContent = prerollDocument.getElementById('contentElement'); videoContent.style.display = 'none'; videoContent.volume = 1; videoContent.muted = false; const playPromise = videoContent.play(); if (playPromise !== undefined) { playPromise.then(function () { console.log('PREROLL sound allowed'); // setUpIMA(true); videoContent.volume = 1; videoContent.muted = false; setUpIMA(); }).catch(function () { console.log('PREROLL sound forbidden'); videoContent.volume = 0; videoContent.muted = true; setUpIMA(); }); } } function setupDimensions() { prerollWidth = Math.min(iinfoPrerollPosition.offsetWidth, 480); prerollHeight = Math.min(iinfoPrerollPosition.offsetHeight, 320); } function setUpIMA() { google.ima.settings.setDisableCustomPlaybackForIOS10Plus(true); google.ima.settings.setLocale('cs'); google.ima.settings.setNumRedirects(10); // Create the ad display container. createAdDisplayContainer(); // Create ads loader. adsLoader = new google.ima.AdsLoader(adDisplayContainer); // Listen and respond to ads loaded and error events. adsLoader.addEventListener( google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, onAdsManagerLoaded, false); adsLoader.addEventListener( google.ima.AdErrorEvent.Type.AD_ERROR, onAdError, false); // An event listener to tell the SDK that our content video // is completed so the SDK can play any post-roll ads. const contentEndedListener = function () { adsLoader.contentComplete(); }; videoContent.onended = contentEndedListener; // Request video ads. const adsRequest = new google.ima.AdsRequest(); adsRequest.adTagUrl = iinfoVastUrls[iinfoVastUrlIndex]; console.log('Preroll advert: ' + iinfoVastUrls[iinfoVastUrlIndex]); videoContent.muted = false; videoContent.volume = 1; // Specify the linear and nonlinear slot sizes. This helps the SDK to // select the correct creative if multiple are returned. // adsRequest.linearAdSlotWidth = prerollWidth; // adsRequest.linearAdSlotHeight = prerollHeight; adsRequest.nonLinearAdSlotWidth = 0; adsRequest.nonLinearAdSlotHeight = 0; adsLoader.requestAds(adsRequest); } function createAdDisplayContainer() { // We assume the adContainer is the DOM id of the element that will house // the ads. prerollDocument.getElementById('videoContent').style.display = 'none'; adDisplayContainer = new google.ima.AdDisplayContainer( prerollDocument.getElementById('adContainer'), videoContent); } function unmutePrerollAdvert() { adVolume = !adVolume; if (adVolume) { adsManager.setVolume(0.3); prerollDocument.getElementById('adMuteBtn').innerHTML = ''; } else { adsManager.setVolume(0); prerollDocument.getElementById('adMuteBtn').innerHTML = ''; } } function onAdsManagerLoaded(adsManagerLoadedEvent) { // Get the ads manager. const adsRenderingSettings = new google.ima.AdsRenderingSettings(); adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true; adsRenderingSettings.loadVideoTimeout = 12000; // videoContent should be set to the content video element. adsManager = adsManagerLoadedEvent.getAdsManager(videoContent, adsRenderingSettings); // Add listeners to the required events. adsManager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, onAdError); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED, onContentPauseRequested); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED, onContentResumeRequested); adsManager.addEventListener( google.ima.AdEvent.Type.ALL_ADS_COMPLETED, onAdEvent); // Listen to any additional events, if necessary. adsManager.addEventListener(google.ima.AdEvent.Type.LOADED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.STARTED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.COMPLETE, onAdEvent); playAds(); } function playAds() { // Initialize the container. Must be done through a user action on mobile // devices. videoContent.load(); adDisplayContainer.initialize(); // setupDimensions(); try { // Initialize the ads manager. Ad rules playlist will start at this time. adsManager.init(1920, 1080, google.ima.ViewMode.NORMAL); // Call play to start showing the ad. Single video and overlay ads will // start at this time; the call will be ignored for ad rules. adsManager.start(); // window.addEventListener('resize', function (event) { // if (adsManager) { // setupDimensions(); // adsManager.resize(prerollWidth, prerollHeight, google.ima.ViewMode.NORMAL); // } // }); } catch (adError) { // An error may be thrown if there was a problem with the VAST response. // videoContent.play(); } } function onAdEvent(adEvent) { const ad = adEvent.getAd(); console.log('Preroll event: ' + adEvent.type); switch (adEvent.type) { case google.ima.AdEvent.Type.LOADED: if (!ad.isLinear()) { videoContent.play(); } prerollDocument.getElementById('adContainer').style.width = '100%'; prerollDocument.getElementById('adContainer').style.maxWidth = '640px'; prerollDocument.getElementById('adContainer').style.height = '360px'; break; case google.ima.AdEvent.Type.STARTED: window.addEventListener('scroll', onActiveView); if (ad.isLinear()) { intervalTimer = setInterval( function () { // Example: const remainingTime = adsManager.getRemainingTime(); // adsManager.pause(); }, 300); // every 300ms } prerollDocument.getElementById('adMuteBtn').style.display = 'block'; break; case google.ima.AdEvent.Type.ALL_ADS_COMPLETED: if (ad.isLinear()) { clearInterval(intervalTimer); } if (prerollLastError === 303) { playYtVideo(); } break; case google.ima.AdEvent.Type.COMPLETE: if (ad.isLinear()) { clearInterval(intervalTimer); } playYtVideo(); break; } } function onAdError(adErrorEvent) { console.log(adErrorEvent.getError()); prerollLastError = adErrorEvent.getError().getErrorCode(); if (!loadNext()) { playYtVideo(); } } function loadNext() { iinfoVastUrlIndex++; if (iinfoVastUrlIndex < iinfoVastUrls.length) { iinfoPrerollPosition.remove(); playPrerollAd(); } else { return false; } adVolume = 1; return true; } function onContentPauseRequested() { videoContent.pause(); } function onContentResumeRequested() { videoContent.play(); } function onActiveView() { if (prerollContainer) { const containerOffset = prerollContainer.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight/1 && containerOffset.bottom > 0.0) { if (prerollPaused) { adsManager.resume(); prerollPaused = false; } return true; } else { if (!prerollPaused) { adsManager.pause(); prerollPaused = true; } } } return false; } function playYtVideo() { iinfoPrerollPosition.remove(); youtubeIframe.style.display = 'block'; youtubeIframe.src += '&autoplay=1&mute=1'; } }
Upozorníme vás na články, které by vám neměly uniknout (maximálně 2x týdně).
'; document.getElementById('outstream-iframe').onload = function () { setupIframe(); } replayScreen = document.getElementById('iinfoOutstreamReplay'); iinfoOutstreamPosition = document.getElementById('iinfoOutstreamPosition'); outstreamContainer = document.getElementsByClassName('outstream-container')[0]; setupReplayScreen(); } function setupIframe() { outstreamDocument = document.getElementById('outstream-iframe').contentWindow.document; let el = outstreamDocument.createElement('style'); outstreamDocument.head.appendChild(el); el.innerText = "#adContainer>div:nth-of-type(1),#adContainer>div:nth-of-type(1) > iframe { width: 99% !important;height: 99% !important;max-width: 100%;}#videoContent,body{ width:100vw;height:100vh}body{ font-family:'Helvetica Neue',Arial,sans-serif}#videoContent{ overflow:hidden;background:#000}#adMuteBtn{ width:35px;height:35px;border:0;background:0 0;display:none;position:absolute;fill:rgba(230,230,230,1);bottom:-5px;right:25px}"; videoContent = outstreamDocument.getElementById('contentElement'); videoContent.style.display = 'none'; videoContent.volume = 1; videoContent.muted = false; if ( location.href.indexOf('rejstriky.finance.cz') !== -1 || location.href.indexOf('finance-rejstrik') !== -1 || location.href.indexOf('firmy.euro.cz') !== -1 || location.href.indexOf('euro-rejstrik') !== -1 || location.href.indexOf('/rejstrik/') !== -1 || location.href.indexOf('/rejstrik-firem/') !== -1) { outstreamDirectPlayed = true; soundAllowed = true; iinfoVastUrlIndex = 0; } if (!outstreamDirectPlayed) { console.log('OUTSTREAM direct'); setUpIMA(true); } else { if (soundAllowed) { const playPromise = videoContent.play(); if (playPromise !== undefined) { playPromise.then(function () { console.log('OUTSTREAM sound allowed'); setUpIMA(false); }).catch(function () { console.log('OUTSTREAM sound forbidden'); renderBanner(); }); } } else { renderBanner(); } } } function getWrapper() { let articleWrapper = document.querySelector('.rs-outstream-placeholder'); // Outstream Placeholder from RedSys manipulation if (articleWrapper && articleWrapper.style.display !== 'block') { articleWrapper.innerHTML = ""; articleWrapper.style.display = 'block'; } // Don't render OutStream on homepages if (articleWrapper === null) { if (document.querySelector('body.p-index')) { return null; } } if (articleWrapper === null) { articleWrapper = document.getElementById('iinfo-outstream'); } if (articleWrapper === null) { articleWrapper = document.querySelector('.layout-main__content .detail__article p:nth-of-type(6)'); } if (articleWrapper === null) { // Euro, Autobible, Zdravi articleWrapper = document.querySelector('.o-article .o-article__text p:nth-of-type(6)'); } if (articleWrapper === null) { articleWrapper = document.getElementById('sidebar'); } if (!articleWrapper) { console.error("Outstream wrapper of article was not found."); } return articleWrapper; } function setupDimensions() { outstreamWidth = Math.min(iinfoOutstreamPosition.offsetWidth, 480); outstreamHeight = Math.min(iinfoOutstreamPosition.offsetHeight, 320); } /** * Sets up IMA ad display container, ads loader, and makes an ad request. */ function setUpIMA(direct) { google.ima.settings.setDisableCustomPlaybackForIOS10Plus(true); google.ima.settings.setLocale('cs'); google.ima.settings.setNumRedirects(10); // Create the ad display container. createAdDisplayContainer(); // Create ads loader. adsLoader = new google.ima.AdsLoader(adDisplayContainer); // Listen and respond to ads loaded and error events. adsLoader.addEventListener( google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, onAdsManagerLoaded, false); adsLoader.addEventListener( google.ima.AdErrorEvent.Type.AD_ERROR, onAdError, false); // An event listener to tell the SDK that our content video // is completed so the SDK can play any post-roll ads. const contentEndedListener = function () { adsLoader.contentComplete(); }; videoContent.onended = contentEndedListener; // Request video ads. const adsRequest = new google.ima.AdsRequest(); if (direct) { adsRequest.adTagUrl = directVast; console.log('Outstream DIRECT CAMPAING advert: ' + directVast); videoContent.muted = true; videoContent.volume = 0; outstreamDirectPlayed = true; } else { adsRequest.adTagUrl = iinfoVastUrls[iinfoVastUrlIndex]; console.log('Outstream advert: ' + iinfoVastUrls[iinfoVastUrlIndex]); videoContent.muted = false; videoContent.volume = 1; } // Specify the linear and nonlinear slot sizes. This helps the SDK to // select the correct creative if multiple are returned. // adsRequest.linearAdSlotWidth = outstreamWidth; // adsRequest.linearAdSlotHeight = outstreamHeight; adsRequest.nonLinearAdSlotWidth = 0; adsRequest.nonLinearAdSlotHeight = 0; adsLoader.requestAds(adsRequest); } function setupReplayScreen() { replayScreen.addEventListener('click', function () { iinfoOutstreamPosition.remove(); iinfoVastUrlIndex = 0; outstreamInit(); }); } /** * Sets the 'adContainer' div as the IMA ad display container. */ function createAdDisplayContainer() { // We assume the adContainer is the DOM id of the element that will house // the ads. outstreamDocument.getElementById('videoContent').style.display = 'none'; adDisplayContainer = new google.ima.AdDisplayContainer( outstreamDocument.getElementById('adContainer'), videoContent); } function unmuteAdvert() { adVolume = !adVolume; if (adVolume) { adsManager.setVolume(0.3); outstreamDocument.getElementById('adMuteBtn').innerHTML = ''; } else { adsManager.setVolume(0); outstreamDocument.getElementById('adMuteBtn').innerHTML = ''; } } /** * Loads the video content and initializes IMA ad playback. */ function playAds() { // Initialize the container. Must be done through a user action on mobile // devices. videoContent.load(); adDisplayContainer.initialize(); // setupDimensions(); try { // Initialize the ads manager. Ad rules playlist will start at this time. adsManager.init(1920, 1080, google.ima.ViewMode.NORMAL); // Call play to start showing the ad. Single video and overlay ads will // start at this time; the call will be ignored for ad rules. adsManager.start(); // window.addEventListener('resize', function (event) { // if (adsManager) { // setupDimensions(); // adsManager.resize(outstreamWidth, outstreamHeight, google.ima.ViewMode.NORMAL); // } // }); } catch (adError) { // An error may be thrown if there was a problem with the VAST response. // videoContent.play(); } } /** * Handles the ad manager loading and sets ad event listeners. * @param { !google.ima.AdsManagerLoadedEvent } adsManagerLoadedEvent */ function onAdsManagerLoaded(adsManagerLoadedEvent) { // Get the ads manager. const adsRenderingSettings = new google.ima.AdsRenderingSettings(); adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true; adsRenderingSettings.loadVideoTimeout = 12000; // videoContent should be set to the content video element. adsManager = adsManagerLoadedEvent.getAdsManager(videoContent, adsRenderingSettings); // Add listeners to the required events. adsManager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, onAdError); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED, onContentPauseRequested); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED, onContentResumeRequested); adsManager.addEventListener( google.ima.AdEvent.Type.ALL_ADS_COMPLETED, onAdEvent); // Listen to any additional events, if necessary. adsManager.addEventListener(google.ima.AdEvent.Type.LOADED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.STARTED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.COMPLETE, onAdEvent); playAds(); } /** * Handles actions taken in response to ad events. * @param { !google.ima.AdEvent } adEvent */ function onAdEvent(adEvent) { // Retrieve the ad from the event. Some events (for example, // ALL_ADS_COMPLETED) don't have ad object associated. const ad = adEvent.getAd(); console.log('Outstream event: ' + adEvent.type); switch (adEvent.type) { case google.ima.AdEvent.Type.LOADED: // This is the first event sent for an ad - it is possible to // determine whether the ad is a video ad or an overlay. if (!ad.isLinear()) { // Position AdDisplayContainer correctly for overlay. // Use ad.width and ad.height. videoContent.play(); } outstreamDocument.getElementById('adContainer').style.width = '100%'; outstreamDocument.getElementById('adContainer').style.maxWidth = '640px'; outstreamDocument.getElementById('adContainer').style.height = '360px'; break; case google.ima.AdEvent.Type.STARTED: window.addEventListener('scroll', onActiveView); // This event indicates the ad has started - the video player // can adjust the UI, for example display a pause button and // remaining time. if (ad.isLinear()) { // For a linear ad, a timer can be started to poll for // the remaining time. intervalTimer = setInterval( function () { // Example: const remainingTime = adsManager.getRemainingTime(); // adsManager.pause(); }, 300); // every 300ms } outstreamDocument.getElementById('adMuteBtn').style.display = 'block'; break; case google.ima.AdEvent.Type.ALL_ADS_COMPLETED: if (ad.isLinear()) { clearInterval(intervalTimer); } if (outstreamLastError === 303) { if (isBanner) { renderBanner(); } else { replayScreen.style.display = 'flex'; } } break; case google.ima.AdEvent.Type.COMPLETE: // This event indicates the ad has finished - the video player // can perform appropriate UI actions, such as removing the timer for // remaining time detection. if (ad.isLinear()) { clearInterval(intervalTimer); } if (isBanner) { renderBanner(); } else { replayScreen.style.display = 'flex'; } break; } } /** * Handles ad errors. * @param { !google.ima.AdErrorEvent } adErrorEvent */ function onAdError(adErrorEvent) { // Handle the error logging. console.log(adErrorEvent.getError()); outstreamLastError = adErrorEvent.getError().getErrorCode(); if (!loadNext()) { renderBanner(); } } function renderBanner() { if (isBanner) { console.log('Outstream: Render Banner'); iinfoOutstreamPosition.innerHTML = ""; iinfoOutstreamPosition.style.height = "330px"; iinfoOutstreamPosition.appendChild(bannerDiv); } else { console.log('Outstream: Banner is not set'); } } function loadNext() { iinfoVastUrlIndex++; if (iinfoVastUrlIndex < iinfoVastUrls.length) { iinfoOutstreamPosition.remove(); outstreamInit(); } else { return false; } adVolume = 1; return true; } /** * Pauses video content and sets up ad UI. */ function onContentPauseRequested() { videoContent.pause(); // This function is where you should setup UI for showing ads (for example, // display ad timer countdown, disable seeking and more.) // setupUIForAds(); } /** * Resumes video content and removes ad UI. */ function onContentResumeRequested() { videoContent.play(); // This function is where you should ensure that your UI is ready // to play content. It is the responsibility of the Publisher to // implement this function when necessary. // setupUIForContent(); } function onActiveView() { if (outstreamContainer) { const containerOffset = outstreamContainer.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight/1 && containerOffset.bottom > 0.0) { if (outstreamPaused) { adsManager.resume(); outstreamPaused = false; } return true; } else { if (!outstreamPaused) { adsManager.pause(); outstreamPaused = true; } } } return false; } let outstreamInitInterval; if (typeof cpexPackage !== "undefined") { outstreamInitInterval = setInterval(tryToInitializeOutstream, 100); } else { const wrapper = getWrapper(); if (wrapper) { let outstreamInitialized = false; window.addEventListener('scroll', () => { if (!outstreamInitialized) { const containerOffset = wrapper.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight / 1 && containerOffset.bottom > 0.0) { outstreamInit(); outstreamInitialized = true; } } }); } } function tryToInitializeOutstream() { const wrapper = getWrapper(); if (wrapper) { const containerOffset = wrapper.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight / 1 && containerOffset.bottom > 0.0) { if (cpexPackage.adserver.displayed) { clearInterval(outstreamInitInterval); outstreamInit(); } } } else { clearInterval(outstreamInitInterval); } } }
OSZAR »