V kterých krajích si čeští ajťáci nejvíce vydělají? Nejvíc IT profesionálů hledá e-commerce

22. 9. 2020
Doba čtení: 8 minut

Sdílet

Autor: Depositphotos
Jak si letos stojí v Česku platy v IT a telekomunikacích, kdo vydělává nejvíce, jaké IT profese jsou nežádanější, a kdo naopak nejméně?

Nejen na výše uvedené otázky poskytují odpověď čerstvá data z průzkumu mezinárodní personální agentury Grafton Recruitment, který vznikal ve třetím čtvrtletí na území třinácti krajů České republiky.  

Hlavní trendy

IT a telekomunikace patří spolu s částí finančního sektoru k těm šťastnějším odvětvím, kde (alespoň v Praze) nedošlo ke stagnaci, nebo dokonce poklesu platů poté, co rychle rozběhnutou ekonomiku a přehřátý pracovní trh zchladila pandemie koronaviru a série vládních opatření (nouzový stav a karanténa). Nabídka volných pozic se nicméně meziročně zmenšila o 20 %.

To, že v oboru nedošlo k poklesu platů, je podle Graftonu jednak důsledkem dlouhodobého nedostatku IT expertů na trhu a také vlny digitalizačních projektů, které momentálně probíhají napříč všemi sektory české ekonomiky a které pandemická vlna ještě urychlila. Digitalizace má za následek jednak to, že se množství IT pozic začíná objevovat i ve společnostech, které neměly s technologiemi dříve nic společného, a také pozvolnou transformaci pozic, které byly dříve plně non-IT, do podoby, která pokročilé IT znalosti začíná vyžadovat.

Nejvíce volných IT pozic se objevilo v e-commerce, druhá největší kategorie, která neúnavně odčerpává většinu volných pracovních sil na trhu, je datová analýza. Třetí kategorie, kde byl letos patrný nárůst zájmu, jsou administrátorské pozice se zaměřením na správu infrastruktury. Na vlně zvýšené popularity se dále vezou například cloudoví specialisté. 

Velké peníze v oboru ovšem nepřicházejí zadarmo, vedle odborných zkušeností zaměstnavatelé trvají na úrovni angličtiny alespoň C1 (Advanced English podle Common European Framework of Reference for Languages) a čím dál častěji je vyžadován ještě jeden další cizí jazyk (nejčastěji francouzština nebo němčina). Z hlediska uchazečů podle průzkumu platí, že povaha projektu a technologie, se kterými budou uchazeči pracovat, mají pro většinu kandidátů větší váhu než nabízené finanční benefity.

Nejžádanější profese a dovednosti

Nejčastěji nabízenými pozicemi jsou datový analytik (nejžádanější), SW programátor (druhé místo) a tester na automatizované testování (třetí pozice), na čtvrtém místě se umístil infrastrukturní expert a na pátém databázový specialista. Mezi pozicemi, na které se expertů nejčastěji nedostává, kraluje bezpečnostní specialista, IT specialista s německým nebo francouzským jazykem, cloudový architekt, iCS a Android programátor a programátoři v nových technologiích.

Skokany roku v oblasti žádanosti ze strany zaměstnavatelů jsou následující profese: junior network engineer, staff software engineer, information technology project coordinator, DevOps engineer, junior Java developer, business data analyst, senior data analyst, lead Java developer, Windows administrator, software developer in test, back-end developer, senior database developer, special project manager, senior business analyst, C developer, junior project manager, site project manager, senior technical support engineer, security architect a technical support team lead.

Mezi dvacet nejžádanějších odborných dovedností patří JSON, Analytics, TypeScript, projektová koordinace, Docker, React.js, Node.js, MongoDB, technická podpora, datová analýza, Python, Jira, user experience (design), REST (Representational State Transfer), cloud computing, Git, AngularJS, objektově orientované programování, agilní metody a znalost informačních technologií obecně. Mezi nejžádanější obecné vlastnosti uchazečů patří schopnost se přizpůsobit, strukturované a logické myšlení, analytické a strategické uvažování, kreativita a ochota učit se novým věcem.

Srovnání mezd

Oproti loňskému roku si mírně polepšil specialista technické podpory 3. stupně, který v roce 2019 bral v Praze mezi 60–80 tisíci korun hrubého a letos mezi 65 až 85 tisíci, jeho plat stoupl také v Moravskoslezském kraji, a to z 35–50 tisíc na 40–55 tisíc korun, a stejně tak i v Olomouckém kraji, na Vysočině a Královéhradeckém kraji. Ve Zlínském, Jihočeském, Ústeckém a Plzeňském kraji platy u dané profese stagnovaly na rozsahu 35–50 tisíc korun. Liberecký kraj si polepšil z 35–50 tisíc na 40–50 tisíc korun a Jihomoravský kraj stagnoval na rozsahu 55–65 tisíc korun.

Platy dříve velmi žádané profese Java/C# vývojáře v Praze stagnovaly na rozsahu 80–100 tisíc korun. Ke změně nedošlo ani v Jihomoravském a Moravskoslezském kraji, kde platy zůstaly v rozsahu 50–80 tisíc Kč. Olomoucký kraj si meziročně polepšil ze 40–55 tisíc na rozsah 45–65 tisíc Kč, Zlínský kraj, kde byl dříve strop 55 tisíc, zvýšil horní hranici na 65 tisíc, na Vysočině, kde došlo loni k propadu platů na rozsah 40–50 tisíc, se platy vývojářů zvedly na 45–65 tisíc, v Jihočeském kraji platy stagnovaly na hodnotě 40–60 tisíc Kč, v Ústeckém kraji na hodnotě 55–60 tisíc a v Libereckém na hodnotě 50–70 tisíc s tím, že se spodní strop zvedl o pět tisíc korun. V Královéhradeckém kraji došlo naopak ke skokovému nárůstu ze 40–55 tisíc na 50–70 tisíc Kč a v Plzeňském kraji ze 45–60 tisíc na 50–70 tisíc korun.

CIF25 SE debata

Javascriptový vývojář patří k profesím s největšími rozdíly mezi jednotlivými kraji. V případě javascriptového vývojáře jde také o nejzasaženější profesi negativními dopady pandemie na ekonomiku. Zatímco v roce 2019 si mohl v Praze javascriptový vývojář přijít na 50–120 tisíc korun, letos to bylo jen 50–100 tisíc Kč. Pokles zaznamenal také Jihočeský kraj, a to ze 45–55 tisíc na 40–50 tisíc Kč. V Jihomoravském kraji si mohl programátor JavaScriptu přijít na 40–75 tisíc (loni na 40–70 tisíc), v Moravskoslezském kraji na 40–60 tisíc (loni na 35–60 tisíc), v Olomouckém a Zlínském kraji na 35–45 tisíc (loni na 30–40 tisíc), na Vysočině 35–45 tisíc (loni 30–45 tisíc). Platy profese stagnovaly ve všech zbývajících krajích, a to na hodnotách 40–60 tisíc na Plzeňsku, 45–50 tisíc v Ústeckém kaji a 50–70 tisíc v Libereckém Kaji a 40–65 v Královéhradeckém kraji.

Přehled dalších profesí bez srovnání s předchozím rokem přinášíme formou tabulky pro jednotlivé podobory.

IT administrace
Pozice Praha a Středočeský kraj
Jihomoravský kraj
Moravskoslezský kraj Olomoucký kraj Zlínský kraj Vysočina Jihočeský kraj Plzeňský kraj Ústecký kraj Liberecký kraj Královéhradecký a Pardubický kraj
ředitel IT 120–250 tisíc 100–200 tisíc 80–130 tisíc 80–120 tisíc 80–120 tisíc 80–120 tisíc 80–120 tisíc 90–140 tisíc 90–190 tisíc 90–140 tisíc 100–150 tisíc
IT manažer 100–150 tisíc 80–120 tisíc 60–85 tisíc 60–85 tisíc 60–80 tisíc 60–90 tisíc 60–100 tisíc 70–100 tisíc 70–100 tisíc 70–110 tisíc 70–110 tisíc
systémový architekt 80–120 tisíc 55–90 tisíc 50–80 tisíc 50–80 tisíc 50–80 tisíc 45–65 tisíc N/A 55–85 tisíc N/A 50–80 tisíc 50–80 tisíc
Windows administrátor 60–90 tisíc 40–60 tisíc 40–50 tisíc 35–45 tisíc 35–45 tisíc 35–45 tisíc 35–45 tisíc 40–60 tisíc 40–60 tisíc 45–55 tisíc 40–50 tisíc
administrátor Linuxu 65–90 tisíc 50–65 tisíc 40–45 tisíc 40–45 tisíc 35–45 tisíc 35–45 tisíc 35–45 tisíc 40–60 tisíc 40–60 tisíc 40–55 tisíc 40–50 tisíc
databázový administrátor 60–90 tisíc 40–70 tisíc 40–50 tisíc 40–50 tisíc 40–50 tisíc 40–50 tisíc 35– 50 tisíc 40–70 tisíc 40–70 tisíc 40–70 tisíc 40–70 tisíc
síťový inženýr 70–100 tisíc 50–65 tisíc 45–60 tisíc 45–60 tisíc 45–60 tisíc 45–60 tisíc 35–50 tisíc 45–60 tisíc 40–65 tisíc 40–60 tisíc 40–60 tisíc
síťový inženýr (junior) 45–65 tisíc 32–45 tisíc 30–40 tisíc 28–38 tisíc 28–35 tisíc 32–45 tisíc 30–40 tisíc 30–45 tisíc 35–50 tisíc 30–50 tisíc 30–45 tisíc
implementační inženýr 60–90 tisíc 40–70 tisíc 35–45 tisíc 30–40 tisíc 30–40 tisíc 37–50 tisíc 35–50 tisíc 38–55 tisíc 40–50 tisíc 35–50 tisíc 40–55 tisíc
specialista podpory aplikací 45–75 tisíc 40–60 tisíc 35–55 tisíc 35–45 tisíc 30–40 tisíc 30–40 tisíc 30–40 tisíc 38–50 tisíc 35–50 tisíc 40–55 tisíc 30–45 tisíc
bezpečnostní
inženýr
55–100 tisíc 40–80 tisíc 35–55 tisíc 35–50 tisíc 35–50 tisíc 35–50 tisíc 35–50 tisíc 38–55 tisíc 38–50 tisíc 30–55 tisíc 40–55 tisíc
architekt bezpečnostní infrastruktury 100–150 tisíc 80–120 tisíc 60–80 tisíc 50–70 tisíc 50–70 tisíc 50–70 tisíc 50–65 tisíc 50–70 tisíc 45–55 tisíc 60–80 tisíc 55–70 tisíc
Technická podpora
Pozice Praha a Středočeský kraj Jihomoravský kraj Moravskoslezský kraj Olomoucký kraj Zlínský kraj Vysočina Jihočeský kraj Plzeňský kraj Ústecký kraj Liberecký kraj Královéhradecký a Pardubický kraj
Manažer technické podpory 80–100 tisíc 70–100 tisíc 60–80 tisíc 50–70 tisíc 50–70 tisíc 50–70 tisíc 40–60 tisíc 50–80 tisíc 50–80 tisíc 45–65 tisíc 45–70 tisíc
Specialista 3. stupně 65–85 tisíc 50–65 tisíc 40–55 tisíc 40–55 tisíc 40–50 tisíc 40–55 tisíc 35–50 tisíc 40–50 tisíc 35–50 tisíc 40–55 tisíc 40–55 tisíc
Specialista 2. stupně 50–80 tisíc 40–55 tisíc 35–50 tisíc 30–45 tisíc 35–45 tisíc 30–45 tisíc 30–40 tisíc 35–45 tisíc 30–40 tisíc 35–45 tisíc 35–45 tisíc
Specialista 1. stupně 35–50 tisíc 30–40 tisíc 28–35 tisíc 28–35 tisíc 28–35 tisíc 28–35 tisíc 25–35 tisíc 30–35 tisíc 26–35 tisíc 28–35 tisíc 28–35 tisíc
Vývoj
Pozice Praha a Středočeský kraj Jihomoravský kraj Moravskoslezský kraj Olomoucký kraj Zlínský kraj Vysočina Jihočeský kraj Plzeňský kraj Ústecký kraj Liberecký kraj Královéhradecký a Pardubický kraj
Full Stack vývojář Java/C# front-end 85–130 tisíc 70–100 tisíc 60–90 tisíc 55–75 tisíc 50–70 tisíc 50–80 tisíc 50–65 tisíc 55–75 tisíc 45–70 tisíc 50–80 tisíc 50–80 tisíc
Java/C# senior 100–150 tisíc 70–100 tisíc 60–90 tisíc 50–70 tisíc 50–70 tisíc 50–70 tisíc 55–80 tisíc 55–75 tisíc 55–80 tisíc 60–80 tisíc 60–80 tisíc
Java/C# (3–5 let) 80–100 tisíc 50–80 tisíc 50–80 tisíc 45–65 tisíc 45–65 tisíc 45–65 tisíc 40–60 tisíc 50–70 tisíc 45–60 tisíc 50–75 tisíc 50–70 tisíc
Java/C# junior 50–80 tisíc 40–60 tisíc 40–50 tisíc 35–45 tisíc 35–45 tisíc 35–45 tisíc 30–50 tisíc 35–47 tisíc 35–50 tisíc 35–50 tisíc 40–60 tisíc
PHP vývojář  senior 90–120 tisíc 60–80 tisíc 50–70 tisíc 45–55 tisíc 50–60 tisíc 45–65 tisíc 40–60 tisíc  55–75 tisíc 45–60 tisíc 50–75 tisíc 60–80 tisíc
PHP vývojář (3–5 let) 60–90 tisíc 50–70 tisíc 45–55 tisíc 40–50 tisíc 40–50 tisíc 35–50 tisíc 35–50 tisíc 45–60 tisíc 35–45 tisíc 40–65 tisíc 50–70 tisíc
PHP vývojář junior 40–60 tisíc 40–55 tisíc 30–40 tisíc 28–38 tisíc 28–40 tisíc 30–40 tisíc 30–45 tisíc 30–45 tisíc 30–40 tisíc 30–50 tisíc 35–55 tisíc
Android/iOS vývojář 50–120 tisíc 40–80 tisíc 38–60 tisíc 38–50 tisíc 35–50 tisíc 35–50 tisíc 35–50 tisíc 40–60 tisíc 35–50 tisíc 40–55 tisíc 40–65 tisíc
JavaScript vývojář 50–100 tisíc 40–75 tisíc 38–60 tisíc 35–45 tisíc 35–45 tisíc 35–45 tisíc 35–50 tisíc 40–60 tisíc 35–50 tisíc 40–55 tisíc 40–65 tisíc
UX/UI vývojář 50–100 tisíc 50–80 tisíc 45–65 tisíc 40–50 tisíc 38–50 tisíc 40–50 tisíc 45–55 tisíc 40–60 tisíc 40–55 tisíc 40–55 tisíc 40–60 tisíc
web designér 40–80 tisíc 40–70 tisíc 35–40 tisíc 30–40 tisíc 30–40 tisíc 30–40 tisíc 35–45 tisíc 37–47 tisíc 30–45 tisíc 30–40 tisíc 35–50 tisíc
vývojář datových skladů/ETL vývojář 70–110 tisíc 50–80 tisíc 45–75 tisíc 35–45 tisíc 45–60 tisíc 35–50 tisíc 45–60 tisíc 40–60 tisíc 45–60 tisíc 40–70 tisíc 40–65 tisíc
databázový vývojář 70–120 tisíc 50–80 tisíc 45–65 tisíc 40–50 tisíc 35–50 tisíc 35–50 tisíc 40–60 tisíc 40–60 tisíc 35–55 tisíc 40–70 tisíc 40–65 tisíc
Manažer testování 80–100 tisíc 60–90 tisíc 60–75 tisíc 50–65 tisíc 45–70 tisíc 45–65 tisíc  50–70 tisíc 55–75 tisíc 50–65 tisíc 65–85 tisíc 60–80 tisíc
Vedoucí týmu testerů 70–90 tisíc 55–80 tisíc 50–65 tisíc 43–50 tisíc 40–60 tisíc 40–60 tisíc 45–70 tisíc 45–70 tisíc 40–60 tisíc  50–75 tisíc 55–80 tisíc
SW Tester – manuální testování 40–65 tisíc 40–65 tisíc 38–55 tisíc 30–40 tisíc 25–40 tisíc 30–40 tisíc 27–40 tisíc 35–50 tisíc 35–45 tisíc 35–50 tisíc 35–50 tisíc
SW Tester – automatizované testování 60–120 tisíc 60–80 tisíc 45–65 tisíc  37–50 tisíc  35–45 tisíc 35–45 tisíc 35–50 tisíc 37–50 tisíc 35–50 tisíc 35–50 tisíc 35–50 tisíc
IT poradenství
Pozice Praha a Středočeský kraj Jihomoravský kraj Moravskoslezský kraj Olomoucký kraj Zlínský kraj Kraj Vysočina Jihočeský kraj Plzeňský kraj Ústecký kraj Liberecký kraj Královéhradecký a Pardubický kraj
Bussines analytik (3 a více let zkušeností) 50–110 tisíc 50–90 tisíc 50–85 tisíc 50–75 tisíc 45–70 tisíc 40–60 tisíc 45–65 tisíc 45–70 tisíc 45–65 tisíc 50–75 tisíc 45–75 tisíc

Bussines analytik (0 –3 roky zkušeností)
45–80 tisíc 40–70 tisíc 35–55 tisíc 35–45 tisíc 35–50 tisíc 30–40 tisíc 35–60 tisíc 40–65 tisíc 40–65 tisíc 40–65 tisíc 40–65 tisíc
BI konzultant 55–120 tisíc 55–100 tisíc  50–85 tisíc 55–75 tisíc 45–70 tisíc 40–60 tisíc 40–55 tisíc 45–70 tisíc 40–60 tisíc 40–55 tisíc 40–60 tisíc
ERP konzultant 50–110 tisíc 50–100 tisíc 50–95 tisíc 50–70 tisíc 45–70 tisíc 50–75 tisíc 40–65 tisíc 50–75 tisíc 40–70 tisíc 50–70 tisíc 50–70 tisíc
ERP vývojář 60–110 tisíc 45–85 tisíc 45–75 tisíc 45–60 tisíc 45–70 tisíc 45–65 tisíc 40–55 tisíc 45–70 tisíc 45–70 tisíc 60–90 tisíc 60–80 tisíc
SAP Konzultant (5 a více let zkušeností)  100–150 tisíc 70–120 tisíc 70–100 tisíc 55–90 tisíc 55–90 tisíc 55–95 tisíc 50–70 tisíc 60–90 tisíc 50–75 tisíc 60–100 tisíc 55–90 tisíc
SAP konzultant (3–5 let zkušeností) 70–100 tisíc 55–90 tisíc 50–85 tisíc 45–55 tisíc 45–55 tisíc 75–65 tisíc 40–60 tisíc 45–60 tisíc 45–55 tisíc 55–80 tisíc 45–75 tisíc
SAP konzultant junior 55–70 tisíc 40–55 tisíc 38–50 tisíc 35–45 tisíc 35–45 tisíc 35–55 tisíc 30–50 tisíc 35–50 tisíc 35–55 tisíc 40–60 tisíc 35–60 tisíc
Projektový management
Pozice Praha a Středočeský kraj Jihomoravský kraj Moravskoslezský kraj Olomoucký kraj Zlínský kraj Kraj Vysočina Jihočeský kraj Plzeňský kraj Ústecký kraj Liberecký kraj Královéhradecký a Pardubický kraj
Projektový manažer 50–130 tisíc 60–120 tisíc 65–100 tisíc 50–80 tisíc 50–80 tisíc 55–80 tisíc 50–100 tisíc 60–90 tisíc 50–90 tisíc 60–100 tisíc 60–100 tisíc
Delivery manager 70–120 tisíc 70–110 tisíc 70–85 tisíc 50–70 tisíc
45–80 tisíc
N/A N/A N/A
50–85 tisíc
N/A N/A
Scrum Master 70–120 tisíc 70–100 tisíc 50–80 tisíc 40–65 tisíc
45–80 tisíc
45–65 tisíc 45–60 tisíc
45–65 tisíc

40–60 tisíc
45–65 tisíc 40–65 tisíc

Autor článku

Externí spolupracovník serveru Lupa.cz a expert na blockchain a kryptoměny. Jako šéfredaktor v minulosti vedl ADASTRA Business Intelligence Magazine a server ITbiz.cz. Dnes pracuje jako redaktor časopisu Forbes.

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