Potravinářskou firmu stavěl na zelené louce. Teď míří k čtvrtmiliardovému obratu

1. 7. 2019
Doba čtení: 9 minut

Sdílet

Ilustrační obrázek
Autor: Karel Choc, Internet Info, podle licence: Rights Managed
Ilustrační obrázek
Firmu postavil z ničeho, na zelené louce, když na vysoké škole postrádal praxi. Dnes má společnost 160milionový roční obrat, chuť růst a dostat se dál do světa.

Řeč je o Martinovi Moučkovi, jednateli a společníkovi firmy FOODISH, která podniká v potravinářství a rozvíjí svou značku zdravé výživy Arax. Čtěte jeho příběh.

Ve škole postrádal praxi, tak začal podnikat

Firmu jsme stavěli úplně od základů, z ničeho, začíná Martin vyprávět svůj podnikatelský příběh. Když před více než deseti lety studoval vysokou ekonomickou školu, v hromadě teorie mu chyběla praxe. Dostal se k obchodu, který se učil i od současného obchodního ředitele firmy Karena Sargsyana.

Je původem Armén a Arméni jsou vyhlášení obchodníci, upozorňuje Martin, který investoval rodinný kapitál a v roce 2008 se se svými společníky pustil do podnikání. Vysokou sice k titulu nedotáhl, zato vybudoval firmu s ročním obratem kolem 160 milionů korun, která prosperuje a roste. Nemyslete si ale, že je náš byznys nějaký zlatý důl, dodává k rychlosti, jakou generují zisk, investují do nových technologií a dokáží růst.

Martin začal podnikat ve 23 letech a firmu považuje za své vypiplané dítě. Aby se vyvíjela, je podle něj nezbytné, aby se primárně vyvíjel její šéf a vedení. Co by tedy, s více než desetiletou zkušeností z byznysu, nyní doporučil těm, kteří se ve třiadvaceti vrhají do podnikání po hlavě jako tehdy on?

Pořád se rozvíjet a pracovat na sobě. Neztrácet chladnou hlavu a motivaci ani v dobrých, ani v těch nejtěžších obdobích. Věnovat čas nejlepším lidem, nikoliv lidem problematickým a neproduktivním – ti vám v malé nebo střední firmě mohou zlomit vaz. Brát do týmu motivované a produktivní lidi – a nikoho jiného, vypočítává.

Nejdřív punk, pak se vypracovali

Přiznává však, že ze začátku to byl punk. Zboží jsme skladovali v externích skladech, výrobky balili, kde se dalo, budovali jsme firmu, hledali cesty, jak a s kým pracovat. Neměl jsem žádnou praxi v managementu, nevěděl jsem ani, jak třeba dělat pohovory s uchazeči o práci, vzpomíná Martin.

Vše se učil za pochodu, metodou pokus omyl. Občas se vydal slepými uličkami, pak se vrátil a šel jinudy. Postupně se vypracovávali.

Původní záměr byl čistý obchod – nakupovat a dodávat suroviny lokálním zpracovatelům. Potom se ale rozhodli zaměřit na vlastní obchodní značku Arax, pod níž začali dodávat suché přílohové potraviny – luštěniny, obiloviny, rýži, kuskus a podobně – do maloobchodního trhu.

Navázali jsme na tradici značky, se kterou Karen začínal už v 90. letech. Araks je významná řeka, která teče na pomezí Arménie a Turecka, připomíná Martin původ názvu brandu.

Nákup proměnily protiruské sankce

Změnu v nákupu jim překvapivě přinesly sankce Evropské unie namířené na Rusko. Předtím jsme luštěniny a obiloviny vozili z Kanady. Dovoz trval dlouho a byl finančně náročný. Po zavedení sankcí Rusko našláplo své hospodářství a začalo pěstovat stejné plodiny jako v Kanadě. Naprostá většina českých firem i firem jinde v Evropě přešla od nákupu z Kanady k Rusku. Na sankcích tedy v této oblasti nejvíc prodělala Kanada, vysvětluje Martin.

Protože má Karen v Rusku spoustu živých obchodních kontaktů, byli mezi prvními, kdo spolupráci na východě rozvíjel. Dnes už jsme o tuto konkurenční výhodu přišli, ale na počátku sankcí pro nás byla velkým plus, upřesňuje Martin.

Produkty nejprve balili ručně. Kde se dalo. Pak si pořídili první balicí stroj, po roce další. Rostli krok za krokem. Jak jsme rostli, rostla i chuť našich zákazníků odebírat více produktů a nakupovat novinky. Šlo to ruku v ruce i s vývojem trhu, objasňuje Martin. Začínali totiž sice v období krize, ale brzo se svezli na vlně, kdy trh zase začal ožívat. Byla to také doba většího nástupu zdravého stravování, kdy zdravá výživa začínala zajímat širší okruh zákazníků.

Z pronajatých prostor do vlastního závodu

Dnes ve firmě pracuje mírně přes čtyřicet lidí a jsme mezi předními zpracovateli a dodavateli konvenčních potravin, připomíná s tím, že ve svém produktovém portfoliu už mají i některé bio kousky. Není to však jejich hlavní doména. To, že se víc soustředí na konvenční potraviny, odpovídá podle Martina jejich filozofii. Nadšení pro bio potraviny tolik nesdílíme. Bio produkty bývají v porovnání s konvenčními až třikrát dražší, a to se přímo nepotkává s naším posláním přinášet výrobky s nejlepším poměrem ceny a kvality, sdílí firemní přístup a jak dodává, chtějí svůj obchod cílit na co nejširší okruh zákazníků.

Čtěte také o podnikatelích, kteří se pustili do veganských produktů a rozjeli „nemlékárnu“, a to v článku Vsadit na veganské potraviny se jim vyplatilo. Jak jejich „nemlékárna“ funguje?

Celý firemní provoz, tedy výrobu i sklad, nyní mají na pomezí Nučic a Rudné u Prahy. Teď už je jim ale pronajatý prostor malý a pracují na výstavbě vlastního závodu ve Zdicích za Berounem. Mají koupené pozemky, na nichž postaví moderní skladovací a výrobní halu velkou asi 7000 metrů čtverečních. Je to pro nás zásadní krok. V novém závodu plánujeme řadu nových technologií. Chceme naši firmu co nejvíce transformovat z obchodní na výrobní, v tom je budoucnost, vysvětluje Martin. Suroviny tedy nechtějí nadále jen balit a prodávat, ale sami z nich také vyrábět produkty s přidanou hodnotou. V té souvislosti plánují alespoň dvojnásobný růst firmy a za pět let trojnásobný obrat. Možná trochu nadhodnocuji, tak jako minimum uvedu milník čtvrt miliardy, dodává vzápětí.

Od obchodu k výrobě

Přerod ostatně nastartovali už teď. Postavili si vlastní výrobní linku na kuskus. Co víme, jsme jediní výrobci kuskusu od středu na východ Evropy. Nejbližší výrobci jsou ve Francii a Itálii, říká Martin hrdě. Na lince, která je prototypem, přitom pracovali pět let, více méně svépomocí. Bylo náročné ji postavit, ale hodně jsme se na tom naučili, upozorňuje.

Hitparáda produktů

Trojku nejprodávanějších produktů Araxu vede jasmínová rýže, následuje ji rýže basmati a, snad trochu překvapivě, pohanka.

Pohanka frčí. Jak do gastra, tak do školek a do škol, říká Martin Moučka.

Na posun od obchodu k výrobě má vliv i to, jak se vyvíjí trh. Podle Martina ho čím dál více zajímá kvalita (i když domácí zákazník zároveň stále slyší na co nejnižší ceny) i české produkty. Teď v Česku ve firmě nakupují jen asi jedno procento plodin, které prodávají. Osobně mě to hrozně trápí, ale v tuzemsku nakupujeme jenom hrách, všechno ostatní musíme vozit ze zahraničí. S kuskusem konečně můžeme dělat z mouky namleté v Česku lokální produkt, aktuálně zhruba 150 tun měsíčně, říká podnikatel spokojeně.

Nebojují cenou, tlak ustáli

Na téma maloobchodní ceny a (ne)ochoty zákazníků si za kvalitu připlatit pak dodává: V atmosféře, kdy se obchodníci předhánějí ve slevách, raději udržíme lepší kvalitu s o něco vyšší cenou, i když přijdeme o kšeft, a pak například rýže neprodáme takové množství jako naše konkurence. Chceme nakupovat efektivně, ale nevozíme za každou cenu to nejlevnější, uvádí ke stylu, kterého se drží. Na začátku také bojovali cenou, dnes se spíš soustředí na spolehlivost v kvalitě.

I na ně supermarkety tlačily, aby šli s cenami dolů. Odmítli. A obchody nakonec na mírně vyšší cenu kývly. Naši rýži si tam uvařili, ochutnali, uznali, že ji máme opravdu dobrou. A prodávají ji dál, ukazuje, jak vypadá jejich spolupráce s maloobchodními řetězci, které jsou spolu s velkoobchody jejich největšími odběrateli. Nezapírá přitom, že je to spolupráce tvrdá a těžká, kde se netolerují žádné chyby. Mezi nákupčími v řetězcích se už ale podle Martina objevují lidé, kterým záleží i na kvalitě zboží, které zákazníkům nabízejí. Samozřejmě jdou po ceně, protože to točí peníze. Nicméně už jsou rozumnější, chápou, že s cenou může padat kvalita. Také řetězce se transformují, mění svoje zaměření a vliv na to mají i požadavky zákazníků, vysvětluje.

Dodávají i do bezobalových obchodů, které prožívají boom, a jednají se společnostmi, které nabízejí vratné obaly. Budou nám je dodávat vymyté, my je budeme plnit a vracet do oběhu. Souvisí s tím i to, že jako firma zabalíme ročně zboží do více jak 15 tun obalů, a to mi připadá moc. Byl bych rád, kdybychom se v tom polepšili, přemýšlí Martin.

Nový obchod a české výrobky do zahraničí

Zatím se soustředili hlavně na český trh, zahraničí je v plenkách, přímo vyvážejí hlavně na Slovensko. Zprostředkovaně jde jejich zboží i do Maďarska, Rumunska nebo do Pobaltí. Jejich cílem však je, aby – i po rozšíření vlastní výroby – do zahraničí dostali české produkty. Po Česku teď nemáme problém dodat kamkoliv zboží od půl palety do druhého dne, vysvětluje Martin s tím, že jim v tom pomáhá systémová logistika. Dva roky rozváželi vlastními dodávkami, potom logistiku předali partnerské firmě. Martin tvrdí, že to byl pro firmu a její distribuci průlom. Podpořil ho i přechod na chytrý vnitropodnikový informační systém. A k dalšímu pořádku v interních procesech jim pomohl International Food Standard, certifikace, kterou získali v roce 2017.

Podnikatelka Martina Grulichová zase ve výrobě vsadila na tradiční valašské frgály. Čtěte, jak se jí daří, v článku Jedinečnost frgálů je především v jejich chuti, říká Martina z Fryštáku.

Mezi změnami, které teď chystají, zmiňuje Martin i rozvoj obchodního oddělení. Doteď byl celý obchod na Karenovi. Od většího týmu si slibují například právě to, že se jejich kuskus a další výrobky dostanou do Evropy. A pouští se i do silnějšího rozvoje propagace a marketingu, za využití moderních komunikačních kanálů, včetně sociálních sítí. Chystají nové webovky, budou natáčet produktová videa atd. V tomhle směru jsme trochu zaspali, hodně jsme se soustředili na samotný byznys, marketing jsme začali dělat až tak čtyři roky zpátky, tak to teď chceme dohnat, vysvětluje Martin.

Lidé? Nepanikařit, vybírat

Aby změn nebylo málo, když se Martin na chvíli utrhl od mikromanagementu a absolvoval jeden z manažerských kurzů, začal ve firmě trochu jinak přistupovat i k práci s lidmi. Lidi na trhu práce jsou, jen je potřeba nepanikařit a vybírat, tvrdí dneska, když se hovor stáčí k tomu, jak nyní vypadá trh práce.

Naučil se psát zajímavé pracovní inzeráty a už jejich prostřednictvím oslovovat jen takové lidi, které do firmy chce – tedy produktivní a motivované primárně jinak než penězi. Na ostatních věcech i dovednostech se podle něj dá pracovat. Řídím se tím, že kdo nechce, hledá důvody, kdo chce, hledá způsoby, popisuje podnikatel, který je schopný ve firmě zastat všechny pozice a přesně ví, co je na které z nich možné a co ne.

školení červen - ochrana os. údajů

Sám je spokojený, když jsou spokojení zaměstnanci, kteří se těší do práce, i když rozhodně není lehká. Těší se, protože podle Martina sami vidí, že dělají dobré poctivé produkty, které se prodávají, plní své poslání a lidé je znají.

Podívejte se také na to, jak vypadá výroba hummusu, která se inspirovala v Izraeli:

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.


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