Firmy mají dostat větší páky na zprostředkovatelské služby a vyhledávače. Dohlédnout má na to ČTÚ

8. 6. 2020
Doba čtení: 8 minut

Sdílet

Autor: Depositphotos
Novela zákona o některých službách informační společnosti implementuje evropské nařízení a sněmovnou má projít zrychleně.

Ministerstvo průmyslu a obchodu (MPO) zaslalo 30. května 2020 do meziresortního připomínkového řízení novelu zákona o některých službách informační společnosti

Tato věta už sama o sobě dokáže vyděsit nejednoho poskytovatele služeb informační společnosti (klasicky třeba otázka odpovědnosti za obsah spolehlivě vystraší provozovatele Ulozto.cz), „naštěstí“ se ale jedná o novelu, která má český právní řád adaptovat na nařízení Evropského parlamentu a Rady (EU) 2019/1150 ze dne 20. června 2019 o podpoře spravedlnosti a transparentnosti pro podnikatelské uživatele online zprostředkovatelských služeb (dále „Nařízení“).

A vzhledem k tomu, že termín pro provedení adaptace je 12. července 2020, tak MPO spěchá a navrhuje, aby byl návrh přijat v Poslanecké sněmovně již v prvém čtení (podle tzv. „devadesátky“).

S ohledem na fakt, že se jedná o adaptaci, do zákona o některých službách informační společnosti „pouze“ dopisuje odkaz na Nařízení, určuje orgán dozoru a dopisuje přestupek za nedodržení povinností plynoucích z Nařízení. Konkrétní povinnosti si tedy povinný subjekt musí dohledat přímo v Nařízení.

Cílem Nařízení má být zlepšení fungování jednotného digitálního trhu nastolením rovnějších podmínek ve vztazích mezi poskytovateli internetových zprostředkovatelských služeb a jejich podnikovými uživateli, a to

  • vytvořením férovějšího podnikatelského prostředí pro menší podnikatelské subjekty, které získávají přístup ke spotřebitelům prostřednictvím poskytovatelů internetových zprostředkovatelských služeb,
  • zajištěním účinnější možnosti nápravy a řešení sporů ve vztazích mezi poskytovateli internetových zprostředkovatelských služeb a podnikovými uživateli jejich služeb,
  • vytvořením předvídatelného a inovativního prostředí na úrovni EU pro regulaci poskytovatelů internetových zprostředkovatelských služeb.

Kdo spadá do kategorie online zprostředkovatelských služeb? Na českém trhu třeba Heureka.cz nebo Zboží.cz a už teď je jasné, že jejich podmínky pro poskytování služeb obchodníkům se budou muset výrazně změnit. Ale regulace dopadne i na internetové vyhledávače, pokud poskytují služby podnikatelům a firmám a umožňují upřednostňovat některé firmy před jinými. Takže do rybníku regulovaného Nařízením spadne i Google (odkazuje na firmy usazené v EU a nabízí zboží nebo služby spotřebitelům v EU) a různé typy i zahraničních marketplace prostorů (weby s nabídkou více dodavatelů).

Proč se Evropská komise rozhodla regulovat online zprostředkovatelské služby? Protože je považuje za klíčovou součást podnikání a nových obchodních modelů, obchodu a inovací, které mohou zlepšit podmínky pro spotřebitele a čím dál tím častěji je používají soukromé i veřejné subjekty. Zároveň poskytují přístup k novým trhům a obchodním příležitostem a tím umožňují podnikům využít výhod vnitřního trhu. Zlí jazykové řeknou na plnou pusu, že důvodem je ambice zkrotit americké vyhledávací giganty.

Důvodová zpráva návrhu zákona uvádí, že online zprostředkovatelské služby mohou být rozhodující pro obchodní úspěch podniků, které je používají k oslovování spotřebitelů. K plnému využití výhod ekonomiky online platforem je proto důležité, aby podniky online zprostředkovatelským službám, s nimiž vstupují do obchodních vztahů, mohly důvěřovat. To má být důležité zejména proto, že rostoucí množství transakcí prostřednictvím online zprostředkovatelských služeb podporovaných silnými nepřímými síťovými účinky založenými na datech vede k vyšší závislosti, zejména mikropodniků a malých a středních podniků, na těchto službách k oslovování spotřebitelů.

Vzhledem k této zvyšující se závislosti mají poskytovatelé uvedených služeb často lepší vyjednávací pozici, která jim umožňuje chovat se v praxi jednostranně způsobem, který podle Evropské komise nemusí být vždy poctivý, a může tak poškozovat oprávněné zájmy jejich podnikatelských uživatelů a nepřímo i spotřebitelů v EU. 

To znamená, že by například mohli vůči podnikatelům jednostranně uplatňovat praktiky, které se odchylují od zásad poctivého obchodního styku nebo odporují dobré víře a poctivému jednání. A proto přichází Nařízení a členské státy mají určit dohledový orgán. U nás navrhuje Ministerstvo průmyslu a obchodu Český telekomunikační úřad (ČTÚ).

Proč Český telekomunikační úřad?

ČTÚ podle předkladatele „splňuje všechna kritéria uvedená v čl. 14 Nařízení, který v otázce soudních řízení vedených zastupujícími organizacemi nebo sdruženími a veřejnými subjekty ponechává členským státům značnou flexibilitu v rámci implementace Nařízení, a proto se jeví jako vhodný dozorový orgán pro dané Nařízení“. 

„Zároveň je nutné zdůraznit, že se s ČTÚ nepočítá v roli mediátora pro řešení daných sporů. Ministerstvo průmyslu a obchodu je toho názoru, že za daných okolností není třeba vytvářet novou instituci v rámci dozoru a Česká republika může být v tomto řešení příkladem pro ostatní členské státy.“

Ministerstvo průmyslu a obchodu si také dává závazek „být připraven podpořit administrativní a finanční posílení ČTÚ“.

Je zřejmé, že ještě dojde k úpravě textu. Není úplně jasné, proč předkladatel argumentuje článkem 14, který dává oprávnění k aktivní legitimaci zastupujícím organizacím, sdružením nebo veřejným subjektům, a zároveň v návrhu zákona je ČTÚ uveden jako orgán dozoru, který dbá na dodržování povinností. 

Fakticky to jsou dvě různé věci – orgán dozoru a veřejný subjekt, který má aktivní legitimaci podávat žalobu třeba na Google, protože „nepoctivě“ jedná s Alzou. Důvodová zpráva také uvádí, že se nepočítá s ČTÚ jako mediátorem – to ale ani nemůže, mediátora si volí online zprostředkovatelské služby a internetové vyhledávače (a ten, kterého vyberou, musí splňovat dané podmínky z Nařízení).

Současně není jasné, proč návrh novely zákona říká, že nebude dopad do státního rozpočtu, a zároveň na jiném místě si MPO dává závazek „podpořit administrativní a finanční posílení ČTÚ“.

Zcela jistě to však bude pro ČTÚ (kromě rozhodování sporů za nezaplacené faktury) další neregulační kompetence. Tak uvidíme, jak se s tím popere.

Text části návrhu zákona navrhující ČTÚ jako orgán dozoru:

(1) Orgánem příslušným k výkonu dozoru nad dodržováním tohoto zákona (dále jen „orgán dozoru“) je 

a) pro šíření obchodních sdělení podle § 7 Úřad pro ochranu osobních údajů, 

b) pro povinnosti vyplývající z § 8 odst. 3 příslušná profesní samosprávná komora zřízená zákonem.,

c) pro povinnosti stanovené přímo použitelným předpisem Evropské unie upravujícím podporu spravedlnosti a transparentnosti pro podnikatelské uživatele online zprostředkovatelských služeb11) Český telekomunikační úřad.

(2) Orgán dozoru působí jako kontaktní místo pro členské státy Evropské unie a Komisi. 

(3) Kontaktní místo pro členské státy Evropské unie a Komisi 

a) podává obecné informace o smluvních právech a povinnostech, jakož i o postupech pro podávání stížností a pro opravné prostředky v případě sporů včetně praktických aspektů využívání těchto postupů, 

b) poskytuje údaje o orgánech, sdruženích nebo subjektech, od nichž lze získat další informace či praktickou pomoc. 

CIF25_SE_terc

Karta právního předpisu

Název

Nařízení EP a Rady (EU) 2019/1150 o podpoře spravedlnosti a transparentnosti pro podnikatelské uživatele online zprostředkovatelských služeb

Komu jsou povinnosti ukládány

Online zprostředkovatelské služby a internetové vyhledavače poskytované (nebo nabízené k poskytnutí) podnikatelským uživatelům a uživatelům firemních internetových stránek, kteří:

a)     jsou usazeni nebo mají místo pobytu v Unii a

b)     nabízejí zboží nebo služby spotřebitelům v Unii.

Komu nejsou povinnosti ukládány

Online platební služby, online reklamní nástroje, online reklamní výměny, které nejsou poskytovány s cílem usnadnit zahájení přímých transakcí a které nezahrnují smluvní vztah se spotřebiteli.

Povinnosti poskytovatele online zprostředkovatelských služeb

·       Zajistit, aby podmínky poskytování služeb:

o byly jasné a srozumitelné,

o byly snadno dostupné (vždy i před uzavřením smlouvy),

o obsahovaly důvody pro rozhodnutí zcela nebo zčásti pozastavit, ukončit nebo omezit poskytování svých služeb,

o obsahovaly informace o dodatečných distribučních kanálech a přidružených programech,

o obsahovaly všeobecné informace o účincích podmínek práva duševního vlastnictví podnikatelských uživatelů, včetně kontroly,

o hlavní parametry určující pořadí a důvody relativní důležitosti těchto hlavních parametrů v porovnání s ostatními parametry.

o popis jakéhokoli rozdílného zacházení, které uplatňují nebo mohou uplatňovat ve vztahu ke zboží a službám (popis se vztahuje na hlavní ekonomická, obchodní nebo právní hlediska uvedeného rozdílného zacházení),

o obsahovaly informace o podmínkách ukončení smlouvy,

o popis technického a smluvního přístupu k informacím poskytnutým nebo vygenerovaným podnikatelským uživatelem, které uchovávají po skončení smlouvy (nebo musí uvést, že takový technický a smluvní přístup neexistuje).

o popis technického a smluvního přístupu podnikatelských uživatelů k jakýmkoli osobním či jiným údajům, jež podnikatelství uživatelé nebo spotřebitelé poskytují pro účely používání zprostředkovatelských služeb

o informace o přístupu k internímu systému pro vyřizování stížností (nevztahuje se na malé podniky).

o určení dvou nebo více mediátorů pro pokus o dosažení dohody o mimosoudním řešení sporů (nevztahuje se na malé podniky).

·       Změny podmínek poskytování služeb musí být oznámeny na trvalém nosiči a to v minimální lhůtě 15 dnů.

·       Pokud podmínky nesplňují výše uvedené, jsou neplatné.

·       Ve svých internetových vyhledavačích stanoví snadno a veřejně přístupný popis hlavních parametrů, které jsou jednotlivě nebo společně nejvýznamnější při určování pořadí. V případě, že přímá nebo nepřímá úplata může ovlivnit parametry, i to musí být uvedeno.

·       Zřídí bezplatný a snadno dostupný interní systém pro vyřizování stížností podnikatelských uživatelů (nevztahuje se na malé podniky).

·       Sestaví informace o fungování a efektivnosti interního systému pro vyřizování stížností a zajistí snadný přístup veřejnosti k nim (celkový počet podaných stížností, průměrnou dobu potřebnou na vyřízení, souhrnná informace o výsledku).

Povinnosti poskytovatele internetových vyhledavačů

·       Uvede popis každého rozdílného způsobu zacházení, který uplatňují nebo mohou uplatňovat ve vztahu ke zboží a službám, jež spotřebitelům prostřednictvím těchto vyhledavačů nabízí

Aktivní legitimace k podání žaloby na ukončení nebo zákaz neplnění příslušných požadavků tohoto nařízení

·       Veřejné subjekty zřízené v členských státech (musí mít tuto kompetenci v národní legislativě), nebo

·       Organizace a sdružení, které mají oprávněný zájem na zastupování podnikatelských uživatelů nebo uživatelů firemních internetových stránek, které

o jsou řádně založeny podle práva členského státu,

o sledují cíle ve společném zájmu „členů“,

o jsou neziskové,

o na jejich rozhodování nemá nepatřičný vliv žádná třetí strana, která poskytuje financování (zejména poskytovatelé online zprostředkovatelských služeb nebo internetových vyhledavačů).

Subjekty, které splňují tyto podmínky a jsou nahlášeny Evropské komisi, jsou zahrnuty do seznamu, který je zveřejněn v Úředním věstníku Evropské unie.

Přezkum

Do 13. ledna 2022 (a poté každé 3 roky)

Orgán dozoru v ČR

Český telekomunikační úřad

Pokuta za nesplnění povinností

Až 10 milionů Kč

Bude zajímavé sledovat, jak Nařízení promění trh srovnávacích služeb a zda opravdu bude mít tento typ regulace pozitivní dopad. Nebo zda se naplní černé představy oponentů této regulace a poskytovatelé srovnávacích služeb a elektronických tržišť nedokáží splnit nové regulační podmínky, zaniknou a ceny pro spotřebitele půjdou naopak nahoru. Nebo jestli budou mít pravdu zastánci tohoto nařízení a v EU vznikne protiváha amerických vyhledávacích gigantů.

Osud tohoto návrhu budeme dále sledovat, termín na zaslání připomínek je 26. června 2020.

Autor článku

Autor je odborník na regulace telekomunikací. Pracuje pro sdružení CZ.NIC a NIX.CZ, od roku 2022 je poradcem ministra průmyslu a obchodu. V letech 2013 až 2020 byl předsedou Rady ČTÚ. Seriál Krátké vlny vychází současně také na blogu sdružení CZ.NIC.

'; 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 »