Z prázdninové brigády můžete dostat odvedenou daň zpět. Jak na to?

15. 8. 2024
Doba čtení: 7 minut

Sdílet

Autor: Depositphotos
Jakými pravidly se řídí odvod daně z příjmů a pojistného u prázdninových brigád a jaké změny nás v této oblasti čekají? Z příležitostného přivýdělku můžete získat zaplacenou daň zpět. Poradíme, jak.

Studenti, kteří si o prázdninách přivydělávají, mohou z těchto brigád profitovat i později prostřednictvím vrácené daně. I brigády u dohod konaných mimo pracovní poměr se někdy daní a za určitých podmínek je možné získat daň i zpět. Nejprve si představíme podmínky týkající se odvodu pojistného a placení daně u obou dohod, které se využívají pro brigády nejčastěji.

Dohoda o pracovní činnosti

Při práci na dohodu o pracovní činnosti (dále jen DPČ) platí, že pokud měsíční hrubý příjem činí alespoň 4000 Kč, jste účastni nemocenského pojištění a budete odvádět i důchodové a zdravotní pojištění.

V rámci zaměstnání malého rozsahu měsíční příjem nedosahuje 4000 Kč nebo není sjednán vůbec. Při výkonu zaměstnání malého rozsahu jste pojištěni jen v těch měsících, v nichž váš příjem dosáhl rozhodné částky.

Důchodové, resp. sociální pojištění odvádíte jako u běžného zaměstnaneckého poměru kromě případů, kdy jde o zaměstnání malého rozsahu. A to je definováno příjmem nižším, než je tzv. rozhodná částka, která je letos ve výši 4000 Kč měsíčně.

U zdravotního pojištění platí, že jste považováni za zaměstnance, pokud dosáhnete tzv. započitatelného příjmu. Jeho hranice se odvozuje od limitu pro povinnou účast na nemocenském pojištění, který začíná od částky 4000 Kč.

Limit pro pojistné platí pro každého zaměstnavatele, se kterým máte sjednanou DPČ, zvlášť. Pokud byste měli naopak více těchto dohod podepsaných u jednoho zaměstnavatele, příjmy z nich se pro tyto účely sčítají.

Placení daně z příjmů

V případě odvodu daně z příjmů z této dohody může nastat několik situací, které závisí na výši hrubého měsíčního příjmu a na faktu, zda jste u daného zaměstnavatele podepsali Prohlášení poplatníka daně z příjmů (dále jen Prohlášení). Připomínáme, že v jednom měsíci můžete mít formulář podepsaný jen u jednoho zaměstnavatele. Pokud ho podepíšete, můžete uplatňovat daňové slevy.

V případě, že jste podepsali Prohlášení, platíte 15% zálohovou daň (a uplatníte daňové slevy) bez ohledu na výši příjmu.

V případě, že jste nepodepsali Prohlášení, záleží ještě na výši hrubého měsíčního příjmu. Pokud je v úhrnné výši u jednoho zaměstnavatele:

  • do 4000 Kč vč. odvedete 15% srážkovou daň (tento limit je opět nastaven podle částky rozhodné pro účast na nemocenském pojištění),
  • ve výši 4001 Kč a výše odvedete 15% zálohovou daň.

Srážková daň

Jde o zvláštní sazbu daně, která je vybírána srážkou přímo u zdroje (zaměstnavatele).

Zálohová daň

Zálohová daň se aplikuje v případech, ve kterých se nepoužije zvláštní sazba daně. Zejména když pracovník podepíše Prohlášení. V daném měsíci to může udělat pouze u jediného zaměstnavatele. Pak si může od mzdy odečíst daňové slevy.

Jak napovídá název, zálohová daň se strhává ve formě záloh a ty jsou po skončení zdaňovacího období zúčtovány.

Pozor na slovíčka

Ačkoli se zdá pojistný a daňový limit stejný, každý je definovaný jinak. Účast na nemocenském pojištění totiž vzniká při příjmu alespoň ve výši 4000 Kč, zatímco srážková daň se odvádí při příjmu do 4000 Kč.

Z toho vyplývá, že při příjmu do 3999 Kč vč. je možné danit srážkou a neodvádí se pojistné. Při příjmu 4000 Kč měsíčně vzniká účast na nemocenském pojištění a platí se i zdravotní a sociální pojištění a ještě je možné uplatnit i srážkovou daň. U příjmu o korunu vyššího, tedy od 4001 Kč, platí pro odvody to samé, ale daň už se odvádí zálohou.

Studenti a pojistné při studiu a po něm. Přehled modelových situací Přečtěte si také:

Studenti a pojistné při studiu a po něm. Přehled modelových situací

Dohoda o provedení práce

dohody o provedení práce (DPP) se z hlediska odvodů pracuje s limitem hrubého měsíčního příjmu ve výši 10 000 Kč. Výše příjmu rozhoduje o tom, jak budete platit daň z příjmů.

Záleží i na tom, zda jste u zaměstnavatele podepsali Prohlášení, díky kterému si můžete uplatnit daňové slevy a mít vyšší výplatu (opět platí, že formulář můžete v jednom měsíci podepsat jen u jednoho zaměstnavatele).

Z hlediska zdanění může nastat několik situací:

  • u zaměstnavatele jste nepodepsali Prohlášení a váš hrubý měsíční příjem nepřesáhne 10 000 Kč = platíte 15% daň srážkou,
  • u zaměstnavatele jste nepodepsali Prohlášení a váš hrubý měsíční příjem přesáhne 10 000 Kč = platíte 15% zálohovou daň,
  • u zaměstnavatele jste podepsali Prohlášení a váš hrubý měsíční příjem nepřesáhne 10 000 Kč = platíte 15% zálohovou daň,
  • u zaměstnavatele jste podepsali Prohlášení a váš hrubý měsíční příjem přesáhne 10 000 Kč = platíte 15% zálohovou daň.

Sociální a zdravotní pojištění

Hranice měsíčního hrubého příjmu ve výši 10 000 Kč rozhoduje i o tom, zda budete odvádět i pojistné na zdravotní a sociální pojištění. Pokud se se svým hrubým měsíčním výdělkem do limitu vejdete, pojistné odvádět nebudete.

V případě, že je váš měsíční hrubý příjem vyšší než 10 000 Kč, odvedete zálohy na sociální a zdravotní pojištění a vznikne vám tím i účast na nemocenském pojištění. Hranice příjmu pro vznik účasti na nemocenském pojištění a pro povinné odvody je tedy u DPP stejná.

Limit příjmu ve výši 10 tis. Kč hrubého měsíčně platí pro každého zaměstnavatele zvlášť. Máte-li ale u jedné firmy více těchto dohod, posuzuje se příjem dohromady.

Změny u dohod

U dohod došlo a ještě dojde ke změnám, pojďme si je shrnout.

Od října 2023 u obou dohod platí, že vám zaměstnavatel musí nejméně 3 dny před započetím práce předložit pracovní rozvrh a do 7 dnů od započetí zase předat informační dokument, který popisuje vaše práva, a musí vám umožnit, abyste v pracovní době navštívili lékaře. Vzniklo právo na příplatky za práci o víkendu, ve svátek či v noci nebo za práci ve ztíženém pracovním prostředí a na náhradu za překážky v práci. Zaměstnavatele také smíte požádat o převedení na pracovní poměr (pokud jste během uplynulých 12 po sobě jdoucích měsíců odpracovali aspoň 180 dní). Dostanete-li výpověď, můžete požádat o její zdůvodnění (zaměstnavatel je povinen do 1 měsíce odpovědět).

Od ledna 2024 mají dohodáři právo na dovolenou, pokud odpracují víc než 80 hodin a smluvní vztah překročí hranici 28 pracovních dnů.

Od července 2024 musí zaměstnavatelé evidovat a hlásit platné (a dosud neregistrované) DPP.

Od roku 2025 bude DPP považována buď za klasické zaměstnání, nebo za zaměstnání malého rozsahu – dle výše příjmu. Výjimkou budou DPP v tzv. režimu oznámené dohody. Tato dohoda bude zvýhodněná a bude možné na ni uplatnit vyšší limit pro odvod sociálního a zdravotní pojištění (tzv. rozhodná částka pro účast na pojištění). Ten se u ní stanoví jako 25 % průměrné mzdy (pro rok 2024 jde po zaokrouhlení na celé pětistovky dolů o částku 10 500 Kč – rozhodnou částku bude vyhlašovat MPSV). Protože tento limit bude platný jen u toho zaměstnavatele, který oznámí DPP jako první, mohou si ostatní u ČSSZ online ověřit, že tuto hlavní DPP u daného člověka neoznámil někdo jiný už dříve. V případě DPP, u které zaměstnanec nepodepsal tzv. Prohlášení poplatníka, aplikuje zaměstnavatel na odměnu srážkovou daň. U ostatních neoznamovaných DPP bude platit limit pro odvody pojistného ve výši 4000 Kč. Při příjmu do této rozhodné částky půjde o režim zaměstnání malého rozsahu (pojistné se neplatí) a je aplikována srážková daň. Při příjmu nad rozhodnou částku se odvádí pojistné a platí se zálohová daň.

Nárok na vrácení daně z DPP

Pokud student odvede z DPP daň, může ji za určitých podmínek získat zpátky.  Obdržet zpět formou daňového přeplatku lze přitom odvedenou srážkovou daň i zálohovou daň z příjmu, uvedla Gabriela Ivanco, daňová poradkyně společnosti Forvis Mazars.

Jak už jsme uvedli výše, brigádníci mohou u zaměstnavatele podepsat Prohlášení a získat nárok na slevu na poplatníka, která činí 2570 Kč měsíčně a odečítá se přímo od stanovené daně. Prohlášení je ale možné za daný měsíc podepsat jen u jednoho zaměstnavatele. Je vhodné podepsat prohlášení k dani u zaměstnavatele s nejvyšší měsíční hrubou mzdou či hrubou odměnou, radí Ivanco.

Pokud nepracujete celoročně, ale pouze v některých měsících, neuplatníte slevu na poplatníka, která ročně činí 30 840 Kč, v plné míře. Zrovna na tuto slevu ale mají nárok poplatníci v plné výši i přes to, že ve skutečnosti nepracovali po celý rok. A neplatí to jen pro studenty, ale i poplatníky na mateřské či rodičovské nebo důchodce.

Do ročního daňového základu ve výši 205 600 Kč je daň z příjmu za letošní rok nulová, a zaplacenou zálohu na daň z příjmu během roku tak poplatníci mohou obdržet v plné částce zpět, vypočetla Gabriela Ivanco.

V případě, že jste platili daň srážkou (u DPP tedy při příjmu do 10 tis. Kč měsíčně a nepodepsaném Prohlášení), můžete si tyto příjmy zahrnout do daňového přiznání a započíst proti celkové daňové povinnosti právě i zaplacenou sraženou daň. Srážkovou daň z dohody o provedení práce nelze obdržet zpět na základě ročního zúčtování daně, upozornila daňová poradkyně (řešením je tedy pouze podat daňové přiznání). To za podmínky, že nemáte během roku ještě jiné příjmy, na které byste daňové slevy a odpočty od základu daně, na které máte nárok, využili v plné míře. 

Školení pro účetní - podzimní novinky

Daňový přeplatek z letních brigád logicky nemůže být vyšší, než byla zaplacená daň z přivýdělku. Např. ze souhrnných odměn z letních brigád ve výši 80 000 Kč, bez podepsaného prohlášení k dani, byla odvedena daň z příjmu ve výši 12 000 Kč, což bude i částka daňové vratky, vypočetla Ivanco na závěr.

Přímo v daňovém přiznání se uvádí příjmy daněné srážkou spolu s ostatními příjmy ze zaměstnání na řádek 31 na druhé straně formuláře. Srážková daň se uvádí do řádku 87, zálohová daň ze závislé činnosti po odečtení slev pak do řádku 84.

Průměrný výdělek vysokoškoláka je o více než 17 tisíc Kč vyšší než u středoškoláka Přečtěte si také:

Průměrný výdělek vysokoškoláka je o více než 17 tisíc Kč vyšší než u středoškoláka

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