Co bude dál s 365internetem? Hledáme řešení, aby zákazníkům zůstaly původní podmínky, říká jednatel

12. 10. 2022
Doba čtení: 7 minut

Sdílet

Autor: Depositphotos
Poskytovatel přiznává, že za jeho podnikáním zůstaly milionové dluhy. Přesto o zákazníky nechce přijít a hledá způsob, jak jim služby poskytovat dál. Jisté je, že CETIN firmě 365internet přístup ke koncovým přípojkám DSL neobnoví.

Zákazníkům operátora 365internet už týden chybějí informace o tom, co s nimi bude po 1. listopadu. Minulou středu je CETIN při surfování přesměroval na svou stránku s informací, že z důvodů neplacení faktur od smlouvy s 365internet odstoupil a službu poskytne již jen do konce října. 

AKTUALIZACE: V noci na středu operátor na svém webu bez dalších podrobností napsal, že během středy 12. října služby zákazníkům obnoví.

Autor: screenshot, Lupa.cz

AKTUALIZACE 17:50: Přípojky 365internet na základě dohody obou společností převezme společnost WIA. CETIN k technickému přenosu služeb poskytl nezbytnou součinnost. Všechny tři firmy to oznámily ve společném prohlášení zveřejněném dnes odpoledne na webu 365internet.cz.

Lupě se podařilo získat pohled zástupců obou stran sporu i třetího pozorovatele a s jejich pomocí postupně začít luštit tajenku, o co v případu jde a co se v něm dosud odehrálo.

Milionové dluhy, co narůstaly dlouho

Nesporné je, že 365internet CETINu dluží nemalé peníze. Kumulované pohledávky dosahují řádu milionů korun a některé jsou více než rok po splatnosti. „Z mého pohledu jde o podnikatelské nezvládnutí řízení nákladů a pomalý růst,“ potvrzuje v rozhovoru pro Lupu existenci dluhu jednatel 365internet Jan Ivanko. „Přes rok už hradíme faktury jen částečně, jak jsme byli schopni zvládat je platit,“ dodává. 

Proč CETIN nechal dluh operátora narůst do takových výšin, netuší. Odmítá však, že by jako bývalý zaměstnanec O2 měl s infrastrukturní firmou nadstandardní vztahy. Podle obchodního rejstříku byl před pěti lety pětinovým společníkem v jeho firmě také Lukáš Sismilich, který následně přešel právě do CETINu, kde působí dodnes.

„Jedna strana nevyužívá všech nástrojů, které v té smlouvě jsou,“ říká Ivanko v narážce na to, že od CETINu očekával reakci na rostoucí saldo daleko dřív. „Ve chvíli, kdy hrozí, že každým okamžikem dostaneme výpověď, jsme logicky neiniciovali žádné akviziční kampaně a nepouštěli se do lovu zákazníků. Z jedné strany nepřišla garance toho, že ta výpověď nepřijde, a oni zase nevěřili našim akvizičním nápadům, co s tím hodláme dělat,“ doplňuje.

Šéf operátora WIA Filip Malina pro vyčkávací taktiku CETINu vysvětlení má: „365internet nám byl předkládán jako ten, na němž se demonstruje, že všechno jde. Když jsme upozorňovali na to, že se tu odehrává zásadní margin squeeze, že MMO nabídka se posouvá do režimu, kdy ji není možné udržet životaschopnou, velmi často nám bylo řečeno, podívejte se na 365internet, jak to tam jde.“

Mluvčí CETINu Adam Zbiejczuk se omezil na konstatování, že z důvodu obchodního tajemství detaily kolem pohledávek za 365internet nebude komentovat. Způsob, jakým CETIN přistoupil k informování zákazníků, kdy v rozporu s principy síťové neutrality přesměroval provoz na stránku se svým oznámením, už dříve zdůvodnil tím, že firma nemá na klienty přímý kontakt a tedy jinou možnost je o problému informovat a připodobnil jej k principu známému v energetice jako dodavatel poslední instance

Takové srovnání jednatel 365internet odmítá. „V případě energií obchodník jen nakupuje na burze a vystavuje faktury. Ale my vlastníme část infrastruktury, jsme tím, kdo zákazníkovi přiděluje IP adresu, kdo pro něho shání konektivitu. CETIN jsou prázdné pasivní trubky nebo kabely vedoucí od zásuvek,“ říká Ivanko.

Podle jeho slov je CETIN jediným věřitelem 365internet. Firmě proto nehrozí insolvence. „V tuto chvíli nemám povinnost podávat insolvenční návrh. Není mi známo, že by nastala situace, kdy by byly splněny všechny tři podmínky pro zahájení insolvenčního řízení,“ tvrdí jednatel.  

Kdo dodává internet?

Zásadní nesoulad mezi stranami je v otázce, kdo od 5. října službu připojení k internetu koncovým zákazníkům poskytuje. 365internet tvrdí, že ztratil veškerou kontrolu nad sítí i nad koncovými místy. To se podle Ivanka projevuje mimo jiné tím, že některým zákazníkům nefunguje Voyo, ti, kteří měli zaplacenu veřejnou IP adresu, o ni přišli, a služby DNS nejsou korektně nakonfigurované. 

Zbiejczuk připouští, že v souvislosti s odstoupením od smlouvy přišel 365internet o možnost nastavovat služby v administračním rozhraní. Odmítá ale, že by 365internet vůči svým zákazníkům přestal být poskytovatelem. To je přitom v rozporu s jeho dřívějším vyjádřením, že společnost nechtěla internetové připojení „prostě vypnout“, a dostat tak zákazníky do potíží, a proto jim připojení zajistila.

Také Filip Malina dřívější vyjádření CETINu chápe tak, že se tato korporace stala poskytovatelem internetu koncovým uživatelům. „To je pro nás bezprecedentní. Je to velkoobchodní hráč a porušuje tím svá dřívější ujištění, že v maloobchodě služby neposkytuje,“ zdůrazňuje.

V této otázce a ve způsobu, jakým došlo k aplikaci smluvních ujednání o odstoupení od smlouvy, spatřuje 365internet porušení MMO kontraktu i zákona o elektronických komunikacích, a chystá se proto iniciovat spor před Českým telekomunikačním úřadem (ČTÚ).

„Pracujeme na tom, za sebe říkám, že určitě jsem připraven sáhnout i k tomuto kroku, o kterém si můj dodavatel myslí, že nikdy neudělám,“ přiznává Ivanko rezolutně. CETIN se sporu nebojí. „Postupovali jsme vždy striktně podle smluvních podmínek. To samozřejmě neupírá společnosti 365internet možnost spor iniciovat,“ říká Zbiejczuk.

Že postup vlastníka infrastruktury nemusí být úplně čistý, naznačuje i Filip Malina: „V současné době se na nás obracejí zákazníci, kteří mají platnou smlouvu s 365internetem a chtějí odejít k nám. A tu změnu operátora neschvaluje 365internet, ale schvaluje ji CETIN. Což je v rozporu se zákonem. Oni neopouštějí CETIN, oni opouštějí 365internet.“

Co bude dál se zákazníky?

365internet plánuje brzy zveřejnit, jak chce zajistit, aby zákazníci o své služby na konci října nepřišli. „Jak to uděláme, kde to uděláme, s kým, jak to vymyslíme, to v tuto chvíli neříkám, ale pracujeme na tom, abychom narovnali stav, který je pro všechny zúčastněné špatně,“ slibuje Ivanko. 

V rozhovoru pro Lupu v úterý 11. října připustil, že jeho firmě už CETIN služby neobnoví. „CETIN při rozhovorech, které jsme měli naposledy minulý týden, potvrdil, že nikdy nedojde k zapojení z jejich strany směrem k nám. To ale neznamená, že nemůže dojít k zapojení těch přípojek tak, aby byly naše,“ naznačuje tajemně.

Co teď chystáte směrem k zákazníkům?

Ať bude zvolena jakákoliv z variant, která je ve hře, tak pro zákazníky se řešení, jak jim dále poskytovat službu, na kterou jsou zvyklí, najde. V té samé kvalitě, pod tím samým kontraktem. Co se stalo s celou zákaznickou bází, se dozvíme až následně.

Je variantou i to, že zákazník bude mít smlouvu s jiným partnerem za stejných podmínek?

Žádná z variant není v tuto chvíli uzavřena. Můj cíl je obnovit služby tak, jak je měli zákazníci 5. října v 7 hodin ráno.

Kdy se zákazník dozví, co pro něj bude platit?

Tu informaci chceme poslat už dnes (v úterý – pozn. redakce), protože je potřeba něco dalšího sdělit. A tam řekneme, ke kterému datu se vrátíme do legálního stavu, kdy zákazníkovi poskytuje službu jeho poskytovatel, se kterým uzavřel smluvní vztah a který přijímá platbu za tu službu.

Jakým způsobem vyřešíte dluh vůči CETINu?

Mezi námi skončí smlouva, kterou máme do měsíce vypořádat. To asi nevypořádáme a budeme dál řešit dluh, kterým tam je. A to tak, že se ho pokusíme zaplatit z toho, co ve společnosti zůstane. Hlavně je to ale závislé na tom, jak bude vypadat podoba zákaznické báze poté, co situaci vrátíme do legálního stavu.

Máte odhad, kolik vašich zákazníků už od 5. října změnilo poskytovatele?

Oficiálně informace, kolik přípojek je zmigrováno jinam, nemám. Nevím, kolik zákazníků zůstane, kolik jich bude chtít pokračovat, nebo radši přejdou jinam, protože se budou bát.

Kde je příčina toho, že jste nebyli schopni dostát závazkům vůči CETINu?

Ta služba má velmi nízkou marži. I když máme určité množství přípojek, nejsme schopni dosahovat zisku. Je to problém všech MMO smluv partnerů, kteří mají méně než 5000 připojek. Pokud někdo nabízí službu pod MMO a stojí méně než 300 korun s DPH, tak ta služba nemůže mít marži.

Je tedy řešení nabízet služby nejen pod MMO, ale i jiným způsobem?

Pokud má někdo své portfolio širší, má více služeb a řekne si v rámci finančního výpočtu, že mu nebude vadit, že na jedné konkrétní službě není tak vysoká marže, protože se zahojí jinde, pak to logicky vychází. Ale nám to nevychází. Na žádné ze služeb, které prodáváme, nemáme zápornou marži. Jenom kumulativně nedáme tu částku, která by pokryla všechny obslužné náklady, jako je konektivita, servery, marketing, účetnictví, zaměstnanci včetně odvodů.

CIF25 SE debata

Může být podle vás MMO smlouva vůbec profitabilní?

Na Unicorn College existuje moje bakalářská práce a tam to vycházelo. Mezitím se podmínky změnily. Například Terminátor zdražil přípojku o 20 korun, čili snížil marži přípojky. Marže neroste v okamžiku, kdy si budu brát vyšší rychlost. Průměrné rychlosti přípojek se zvyšují, ale zákazníci nebudou platit najednou třikrát tolik.

Autor článku

Redaktor serveru Lupa.cz se zaměřením na telekomunikace, média, IT a právo. Dříve šéfredaktor Právního rádce a mluvčí Českého telekomunikačního úřadu.

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