Od pomoci kolegyni k vlastnímu podnikání: Jak Michal záchranil značku?

13. 6. 2025
Doba čtení: 6 minut

Sdílet

Michal stojí za značkou, která ulehčuje život nejen spoustě maminek malých i větších dětí. Přináší totiž na trh unikátní jmenovky a mnoho dalšího.

Díky značce mylabels si mohou lidé sami navrhnout originální samolepky, nažehlovačky nebo například prostírání. Stojí za ní programátor Michal Bumbálek.

Co se dozvíte v článku
  1. Systém, který dobře znal
  2. Náročný marketing i technická stránka
  3. Výhodou je design a funkčnost
  4. Vedou samolepky 
  5. Zákazník designérem 
  6. S návrhy pomáhá i umělá inteligence
  7. Tip na další příběh

Systém, který dobře znal

Michal Bumbálek je vývojář a současný systém spojený s mylabels vytvořil pro svou bývalou kolegyni. Několik let jej provozovala a bohužel projekt musela náhle ukončit ze zdravotních důvodů. Mně bylo líto, že by to přišlo vniveč, protože udělala hodně práce a já koneckonců taky. Je to docela unikátní věc, takže jsem se rozhodl, že to od ní odkoupím, abych mohl projekt provozovat dál, popisuje. Tím, že systém vytvořil, dobře ho znal a mohl s mylabels bez problémů pokračovat. Práce pro něj byla tedy jednodušší především co se týče technické stránky. Sice to byl můj produkt, ale ne pro mě. A potom se mi zase vrátil, zamýšlí se s úsměvem. 

Když Michal mylabels přebíral, bylo jasné, že jde o velkou věc, která bude mít dopad na rodinu. Proto se s manželkou museli rozhodnout společně a zdůrazňuje, že by do toho určitě nešel, kdyby jeho žena byla proti. Prvním produktem mylabels byly nějaké samolepky, k nim se poté přidaly nažehlovačky. Když projekt převzal Michal, doplnil k tomu jídelní prostírání, protože konfigurátor je podle něj relativně univerzální. Mě napadlo, že by si lidi mohli dát do domácnosti nejenom samolepky na kořenky a dózy, ale právě i nějaké prostírání na stůl, přidává.

Náročný marketing i technická stránka

V začátcích byl pro Michala nejtěžší marketing. Tím, že je technik, vyhovuje mu psaní, ale prezentace produktů a podobné věci, to jej trošku bolelo. Bolí to do dneška, není mi to úplně přirozené, přiznává. Dnes u nich marketing zahrnuje všechny kanály jako je Facebook, Instagram, placené reklamy, spolupráce s Instagramerkami, a reklama v dětských časopisech. Podle Michala se nedá říct, co nejlépe funguje, protože je to hodně proměnlivé. Navíc má poslední dobou pocit, že všechny tyto kanály už nemají takovou energii a že jsou lidé otupělí a zahlčení všemi testy, videi a reklamou. Takže nemám pocit, že by něco z toho fungovalo lépe než něco jiného. Ten mix se musí řešit konstantně dál a dál, myslí si. 

Michala také překvapila technická náročnost provozu. Ta je pro něj jedno velké překvapení. Já jsem jako programátor žil spíše ve virtuálním světě, který nemá přesah do fyzična. Takže samozřejmě potýkat se tady s tiskárnou štítků, to je zajímavá zkušenost, doplňuje. 

Produkty, které mylabels nabízí, řeší spíše maminky. To je pro Michala Bumbálka málokdy výzvou. Většina zákaznic je podle něj spokojená s tím, jak to funguje a reklamací je naprosté minimum. Když se něco vyskytne, tak se většinou domluví na nějakém řešení a je to bez problémů. Mám fůru kladných ohlasů, kdy jsou lidé nadšení z toho, že jim to život trošku zjednoduší a že to opravdu funguje. Takže za mě je to super, dodává. 

Výhodou je design a funkčnost

U samolepek je důležitou částí design, kdy řada zákazníků oceňuje, že jsou opravdu propracované a hezké. Po praktické stránce jde o to, že samolepky i nažehlovačky opravdu drží. To se podle Michala bohužel ne každému, kdo v tomhle oboru dělá a prodává podobné věci, povede. Jejich samolepky jsou vyladěné a vyzkoušené, takže naprosté většině zákazníků fungují a drží na všem. To je velký benefit mylabels: design a ta funkčnost, zdůrazňuje Michal. 

Kromě samolepek a nažehlovaček sloužících především pro označování dětského oblečení a dalších předmětů nabízí mylabels také spoustu samolepek pro domácnost. K tomuto rozšíření došlo podle Michala proto, že samolepky na oblečení a do školy jsou hodně sezónní. Největší náraz tak samozřejmě nastává před začátkem školního roku. Proto se snažili vyrovnat sezónnost a přijít s něčím dalším, aby stroj nestál a bylo co dělat i po zbytek roku. 

Michal Bumbálek je hrdý na celý sortiment. Jsou to vše odladěné věci, které podle něj nevznikly úplně omylem nebo nějakou náhodou. Všechno jsou za něj velmi povedené produkty. Pokud by v sortimentu bylo něco, co se mi nezdá, tak to v nabídce prostě nebude, shrnuje. 

Vedou samolepky 

Ze samolepek a nažehlovaček jsou oblíbenější samolepky. Je to také proto, že občas mámy řeší, že když chtějí oblečení prodat a je na něm nažehlená jmenovka, tak ji z toho nikdo nedostane. Když je naopak polepené samolepkou, stačí ji odlepit a někdo další si tam může nalepit svoji. Takže při posunu v rámci dětí nebo pro budoucí prodej jsou lepší samolepky. Ty jsou určitě preferovanější, říká Michal a dále popisuje, že nažehlovačky zase mají tu výhodu, že lépe drží.

U samolepek se přece jenom může časem stát, například po více pracích cyklech, že můžou odpadnout. To se u nažehlovačky nestane, upřesňuje. Dalším benefitem nažehlovaček je, že si můžete pořídit opravdu velkou s nějakým obrázkem nebo fotkou a nažehlit ji například na triko. To by u samolepek sice také šlo, ale bylo by to nepraktické a oblečení by bylo příliš tuhé a nepohodlné. 

Zákazník designérem 

U většiny produktů od mylabels se zákazníci stávají sami designery. Co si mohou zvolit, se trochu liší produkt od produkty. Obecně podle Michala platí, že jakmile si vyberou nějaký tvar, volí z barev a obrázků, můžou zadat vlastní nápis a u toho si zvolí typ písma a barvu. Vznikají stovky kombinací a málokdy se stane, že by si víc zákazníků objednalo v podstatě totožný design. To se stává jen u pěti nejprodávanějších produktů, že se tam občas něco opakuje designově, ale všechno jsou to ve výsledku originály, popisuje Michal. 

Dále přiznává, že samozřejmě vznikají chyby, kdy člověk něco přehlédne a má tam například velké písmo nebo nekontrastní barvu písma k pozadí. S nějakými nevkusnými nebo nevhodnými věcmi se však Michal nesetkal. Výhoda tohoto řešení je, že tak, jak si to ten zákazník nakonfiguruje, tak to lze rovnou tisknout. Do toho už nemůžete vůbec vstupovat jako člověk a ručně něco řešit, vysvětluje s tím, že pokud si zákazník všimne nějaké chyby, tak není problém objednávku vystornovat a udělat ji znovu správně. Systém je tedy postavený tak, že co člověk vidí v konfigurátoru, tak to nakonec také dostane. 

S návrhy pomáhá i umělá inteligence

U grafiky produktů, která je v nabídce, jsou všechno autorská díla. U fotoproduktů mohou zákazníci nahrávat vlastní obrázky, což je problematické z hlediska autorských práv. Mylabels to má tedy nastaveno tak, že za to nese odpovědnost zákazník a je na to také upozorněn. U návrhů také využívá umělou inteligenci. Podle Michala je to spíše atraktivní doplněk, který zákazníci využívají především tak, že si vyzkouší vygenerovat obrázek. Málokdy jej však použijí na výsledný produkt. 

Zatím je to o tom, že lidi s tím neumí pracovat. Umělá inteligence dává velmi dobré výsledky, ale musí se jí samozřejmě dát správné zadání. Vidím v historii pokusů, že to lidé zatím nemají zažité, takže příkazy velmi zjednodušují a výsledek potom asi není úplně to, co čekali, dodává. 

WT100 25_SE

Nové produkty přidávají na mylabels průběžně, a to tak, aby nabídka byla zajímavá a vyvážená pro kluky, pro holky, na léto nebo na zimu. V tuhle chvíli se nechystá úplně nový typ produktů, ale v těch stávajících samozřejmě budou přibývat nějaké nové motivy a designy, prozrazuje závěrem Michal Bumbálek.

Tip na další příběh

Dojemný příběh podnikatele, který vyrábí hudební nástroj pro radost i léčbu duše

Když měl Vladimir Jerechynsky zdravotní problémy, objevil takzvané bubny štěstí, které se rozhodl prodávat i široké veřejnosti. Seznamte se s jeho příběhem. Více v článku.

Zajímá vás toto téma? Chcete se o něm dozvědět víc?

Objednejte si upozornění na nově vydané články do vašeho mailu. Žádný článek vám tak neuteče.


Autor článku

Jana Langerová píše o marketingu, podnikatelských příbězích a digitálních trendech.​ Profil autorky →

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