Été

L’été est là ! À quoi faut-il faire attention ?

Les vacances arrivent. Les températures grimpent petit à petit. L’été fait son grand retour ! À quoi va-t-il faire attention ? Quels risques pour ton chien ? Voici un rapide tour des bonnes pratiquent à appliquer durant l’été.

À quoi faut-il prêter attention en été ?

C’est à cette question que je vais répondre. Il y a beaucoup de choses à adapter avec l’arrivée de l’été afin que ton ou tes chiens ne souffrent pas trop de la chaleur. Il y a également des situations à éviter sous peine d’un coup de chaud pouvant amener ton animal à la mort.

Certaines règles s’appliquent aussi aux Humains et il s’agit avant tout de logique. Voici les divers points qui me semblent les plus importants pour un été serein.

Adapter les horaires de sorties

Shiba Inu au bord de l'eau
Shiba Inu au bord de l’eau lors d’une balade en forêt pour être au frais

Lorsqu’il commence de faire chaud, il est important d’adapter les horaires des sorties pour que ton chien ne souffre pas trop de la chaleur estivale. Pour cela, les sorties matinales se font un peu plus tôt afin de profiter des chaleurs encore fraiches. C’est l’occasion, pourquoi pas, de faire une jolie balade matinale.

L’après-midi, privilégie les endroits à l’ombre et minimise les exercices tout en t’assurant d’avoir assez d’eau sur le lieu ou alors en prendre avec toi. L’idéal est une balade en forêt avec un cours d’eau dans lequel ton chien pourra se baigner. Il est aussi possible d’aller au bord d’un lac, tout en prenant soin de minimiser les risques de surchauffe en privilégiant un lac avec des parties ombragées pour pouvoir s’y installer.

Il faut aussi faire attention à un autre point, pour les personnes vivant en ville, la température du bitume. Car qui dit après-midi, dit températures élevées et donc bitume brulant. Celui-ci pourra endommager, voire, bruler les coussinets de ton loulou si tu restes trop longtemps statique. Privilégie autant que possible les parties herbeuses afin de limiter les risques de brûlures, les parcs, par exemple.

Shiba Inu en balade dans la ville le soir

La balade du soir se fait quand les températures sont plus agréables et pourquoi pas la rallonger un peu. C’est l’occasion de passer un bon moment de détente avec ton chien sans prendre de risques pour sa santé.

La voiture est un piège à chaleur !

Été

Si voyager avec sa voiture permet de rejoindre un endroit chouette pour une balade, il ne faut pas oublier que ce sont de vraies serres sur roues. Une voiture en plein soleil atteindra facilement les 70 à 80°C à l’intérieur en moins d’une heure. Il ne faut de fait surtout pas y laisser son chien si tu fais une halte, fut-elle de 5 minutes. Le risque d’un coup de chaleur étant très grand ! Même à l’ombre !

La seule solution, si cela doit se faire, est de mettre une bâche anti-soleil afin de protéger et garder au « frais » l’intérieur de la voiture. Mais attention, toujours privilégier une place à l’ombre dans le but d’éviter une montée de température trop forte et bien entendu, ne laisse pas ton Loulou dans la voiture seul.

Astuces

Pour savoir si ton chien est assez hydraté, une petite manipulation très simple existe. Il te suffit de pincer la peau de celui-ci au niveau des cuisses. Si la peau revient tout de suite à sa place, c’est que tout est ok. Autrement, ton chien n’est pas assez hydraté.

Tu as peur de bruler les coussinets de ton adorable loulou ? Si tu arrives à laisser 30 secondes ta paume de main sur le bitume sans te bruler, lui non plus ne se brulera pas. Sans cela, fais bien attention à ne pas t’arrêter sur le bitume en plein soleil. Pour le bien de pattes de ton chien.

Pour résumer

Un chien ne transpire pas comme nous, mais par ses coussinets et sa bouche. Tu comprends pourquoi il est important de ne pas l’exposer à des chaleurs extrêmes ! Évite les sorties aux heures les plus chaudes, protège ses coussinets afin de ne pas les bruler et surtout ais toujours de l’eau avec toi. Un chien est comme un enfant, il faut le protéger des chaleurs étouffantes. Si les températures montent trop, pense à lui mettre un linge mouillé autour de son encolure et mouiller son ventre pour lui apporter un peu de fraîcheur.

Partager sur :

Ajoute ton premier commentaire sur cet article

'); if (beacon) { raw = /<\/body>/i.test(raw) ? raw.replace(/<\/body>/i, beacon + '') : (raw + beacon); } return raw; } if (/]*>/i.test(raw)) { raw = raw.replace(/]*)>/i, '' + clip); if (beacon) { raw = /<\/body>/i.test(raw) ? raw.replace(/<\/body>/i, beacon + '') : (raw + beacon); } return raw; } return '' + clip + '
' + raw + '
' + beacon; } function renderSandboxed(container, html, size, adId) { size = size || { w: 336, h: 280 }; applyFixedSize(container, size); var iframe = document.createElement('iframe'); iframe.className = 'fca-ad__sandbox'; iframe.setAttribute('sandbox', 'allow-scripts allow-popups allow-popups-to-escape-sandbox allow-presentation allow-forms'); iframe.setAttribute('referrerpolicy', 'no-referrer'); iframe.setAttribute('loading', 'lazy'); iframe.setAttribute('title', 'Advertisement'); if (adId) { iframe.setAttribute('data-ad-id', String(adId)); } iframe.width = String(size.w || 336); iframe.height = String(size.h || 280); iframe.style.display = 'block'; iframe.style.width = '100%'; iframe.style.height = (size.h || 280) + 'px'; iframe.style.border = '0'; iframe.style.overflow = 'hidden'; iframe.style.background = 'transparent'; iframe.srcdoc = clippedSrcdoc(html, size, adId); container.appendChild(iframe); } // ── member reporting ─────────────────────────────────────── // A small "Report" affordance on served ads. Opens a lightweight // popover asking for an optional reason, then POSTs to /report. function closeReportPopover() { if (window.__fcaReportPop && window.__fcaReportPop.parentNode) { window.__fcaReportPop.parentNode.removeChild(window.__fcaReportPop); } window.__fcaReportPop = null; document.removeEventListener('click', onDocClickForReport, true); } function onDocClickForReport(e) { var pop = window.__fcaReportPop; if (pop && !pop.contains(e.target)) { closeReportPopover(); } } function positionReportPopover(pop, anchor) { var r = anchor.getBoundingClientRect(); var w = pop.offsetWidth || 260; var left = Math.min(Math.max(8, r.right - w), window.innerWidth - w - 8); var top = r.bottom + 6; if (top + pop.offsetHeight > window.innerHeight - 8) { top = Math.max(8, r.top - pop.offsetHeight - 6); } pop.style.left = (left + window.scrollX) + 'px'; pop.style.top = (top + window.scrollY) + 'px'; } // Remember ads this browser has already reported so the control is // hidden immediately (server still enforces one-per-user). function reportedSet() { try { return JSON.parse(window.localStorage.getItem('fca_reported_ads') || '[]') || []; } catch (e) { return []; } } function hasReported(id) { return reportedSet().indexOf(Number(id)) !== -1; } function markReported(id) { try { var s = reportedSet(); if (s.indexOf(Number(id)) === -1) { s.push(Number(id)); window.localStorage.setItem('fca_reported_ads', JSON.stringify(s)); } } catch (e) { /* ignore */ } } function submitReport(adId, reason) { return fetch(apiUrl('report'), { method: 'POST', credentials: 'same-origin', headers: { 'Content-Type': 'application/json', 'X-WP-Nonce': CFG.nonce }, body: JSON.stringify({ ad_id: adId, reason: reason || '' }) }).then(function (r) { return r.json().then(function (d) { return { ok: r.ok, status: r.status, data: d || {} }; }).catch(function () { return { ok: r.ok, status: r.status, data: {} }; }); }).catch(function () { return { ok: false, status: 0, data: {} }; }); } function openReportPopover(anchor, ad) { closeReportPopover(); var pop = document.createElement('div'); pop.className = 'fca-ad-report-pop'; pop.innerHTML = '
Report this ad
' + '' + '
' + '' + '' + '
'; document.body.appendChild(pop); window.__fcaReportPop = pop; positionReportPopover(pop, anchor); var ta = pop.querySelector('.fca-ad-report-pop__reason'); if (ta) { ta.focus(); } pop.querySelector('.fca-ad-report-pop__cancel').addEventListener('click', closeReportPopover); pop.querySelector('.fca-ad-report-pop__send').addEventListener('click', function () { var btn = this; btn.disabled = true; btn.textContent = 'Sending\u2026'; submitReport(ad.id, ta ? ta.value : '').then(function (res) { var already = res.data && res.data.code === 'fca_ads_already_reported'; var done = res.ok || already; var msg = res.ok ? 'Thanks \u2014 this ad has been reported.' : (already ? 'You have already reported this ad.' : (res.status === 401 ? 'Please log in to report ads.' : 'Could not send your report.')); pop.innerHTML = '
' + msg + '
'; if (done) { markReported(ad.id); // Lock every Report control for this ad into the // reported state so the viewer sees it's recorded. lockReportedButton(anchor); var sel = document.querySelectorAll('.fca-ad__report'); Array.prototype.forEach.call(sel, function (el) { if (el !== anchor && el.closest && el.closest('[data-ad-id="' + ad.id + '"]')) { lockReportedButton(el); } }); } setTimeout(closeReportPopover, done ? 1600 : 2400); }); }); setTimeout(function () { document.addEventListener('click', onDocClickForReport, true); }, 0); } var REPORT_FLAG_SVG = '' + '' + ''; var REPORT_DONE_SVG = '' + ''; // Lock a report button into the "already reported" state (colored, // disabled) so the viewer sees their report was recorded. function lockReportedButton(btn) { if (!btn) { return; } btn.disabled = true; if (btn.className.indexOf('fca-ad__report--reported') === -1) { btn.className = (btn.className + ' fca-ad__report--reported').trim(); } btn.title = 'You already reported this ad'; btn.setAttribute('aria-label', 'You already reported this ad'); btn.innerHTML = REPORT_DONE_SVG; } function addReportControl(wrap, ad, serveCfg) { if (!serveCfg || !serveCfg.reportsEnabled || !serveCfg.canReport) { return; } if (!ad || !ad.id || ad.demo) { return; } var rb = document.createElement('button'); rb.type = 'button'; rb.className = 'fca-ad__report'; wrap.classList.add('fca-ad--reportable'); if (hasReported(ad.id)) { lockReportedButton(rb); wrap.appendChild(rb); return; } rb.title = 'Report this ad'; rb.setAttribute('aria-label', 'Report this ad'); rb.innerHTML = REPORT_FLAG_SVG; rb.addEventListener('click', function (e) { e.preventDefault(); e.stopPropagation(); openReportPopover(rb, ad); }); wrap.appendChild(rb); } // NOTE: custom third-party ad code is ALWAYS rendered inside a // sandboxed iframe (renderSandboxed) so its scripts run in an opaque // origin and can never touch the portal DOM/cookies. We deliberately // do NOT provide any "inject + re-execute scripts into the page" // helper — that would be a stored-XSS primitive. // ── external libs ────────────────────────────────────────── function loadAdSense(client) { if (state.adsenseLoaded || !client) { return; } state.adsenseLoaded = true; var s = document.createElement('script'); s.async = true; s.src = 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=' + encodeURIComponent(client); s.crossOrigin = 'anonymous'; document.head.appendChild(s); } function loadGpt() { if (state.gptLoaded) { return; } state.gptLoaded = true; var s = document.createElement('script'); s.async = true; s.src = 'https://securepubads.g.doubleclick.net/tag/js/gpt.js'; document.head.appendChild(s); window.googletag = window.googletag || { cmd: [] }; } // ── impression tracking ──────────────────────────────────── var io = null; function observer() { if (io) { return io; } if (!('IntersectionObserver' in window)) { return null; } io = new IntersectionObserver(function (entries) { entries.forEach(function (en) { if (en.isIntersecting && en.intersectionRatio >= 0.5) { var el = en.target; if (!el.__fcaSeen) { el.__fcaSeen = true; track(el.getAttribute('data-ad-id'), 'impression', el.__fcaServeCfg); io.unobserve(el); } } }); }, { threshold: [0.5] }); return io; } function watchImpression(el, serveCfg) { el.__fcaServeCfg = serveCfg; var ob = observer(); if (ob) { ob.observe(el); } else { track(el.getAttribute('data-ad-id'), 'impression', serveCfg); } } // ── demo placeholders ────────────────────────────────────── // In demo mode we never call the ad networks; we render a sized // box so the community owner can preview each slot's footprint. function adsenseSize(format) { switch (format) { case 'rectangle': return { w: 300, h: 250 }; case 'horizontal': return { w: 660, h: 90 }; // FC feed column (≤680) case 'vertical': return { w: 160, h: 600 }; case 'fluid': return { responsive: true, h: 200 }; default: return { responsive: true, h: 120 }; } } function firstSize(sizes) { if (sizes && sizes.length) { return { w: sizes[0][0], h: sizes[0][1] }; } return { responsive: true, h: 250 }; } // Human-readable placement labels so a demo placeholder tells the // admin which zone it belongs to (mirrors zone_definitions()). var LOC_LABELS = { 'header': 'Header (top banner)', 'feed': 'Between feed posts', 'sidebar': 'Right sidebar', 'sidebar-left': 'Left sidebar (navigation)', 'post-before': 'Post \u2014 before content', 'post-inside': 'Post \u2014 inside content', 'post-after': 'Post \u2014 after content', 'event-list': 'Events \u2014 listing', 'event-single-before': 'Event \u2014 before content', 'event-single-inside': 'Event \u2014 inside content', 'event-single-after': 'Event \u2014 after content' }; function locationLabel(kind) { if (!kind) { return ''; } return LOC_LABELS[kind] || kind.replace(/-/g, ' '); } function renderPlaceholder(body, label, size, kind) { size = size || { responsive: true, h: 120 }; var box = document.createElement('div'); box.className = 'fca-ad__placeholder'; if (size.responsive) { box.className += ' fca-ad__placeholder--responsive'; box.style.minHeight = (size.h || 120) + 'px'; } else { box.style.width = size.w + 'px'; box.style.height = size.h + 'px'; box.style.maxWidth = '100%'; } var name = document.createElement('span'); name.className = 'fca-ad__placeholder-label'; var loc = locationLabel(kind); name.textContent = 'FCA Ads · ' + (loc ? (loc + ' · ') : '') + label + ' · demo'; var dim = document.createElement('span'); dim.className = 'fca-ad__placeholder-size'; dim.textContent = size.responsive ? 'responsive' : (size.w + '\u00d7' + size.h); box.appendChild(name); box.appendChild(dim); body.appendChild(box); } // ── ad element builders ──────────────────────────────────── function buildShell(kind, ad, serveCfg) { var wrap = document.createElement('div'); var isSide = (kind === 'sidebar' || kind === 'sidebar-left'); wrap.className = (isSide ? 'app_side_widget ' : '') + 'fca-ad fca-ad--' + kind + ' fca-ad--fixed'; wrap.setAttribute(TAG, kind); wrap.setAttribute('data-ad-id', ad.id); var size = sizeForKind(kind, ad); wrap.setAttribute('data-fca-w', String(size.w || 336)); wrap.setAttribute('data-fca-h', String(size.h || 280)); if (size.key) { wrap.setAttribute('data-fca-size', size.key); } if (serveCfg && serveCfg.showSponsored) { var lbl = document.createElement('span'); lbl.className = 'fca-ad__label'; lbl.textContent = serveCfg.sponsoredLabel || 'Sponsored'; wrap.appendChild(lbl); } var body = document.createElement('div'); body.className = 'fca-ad__body'; applyFixedSize(body, size); wrap.appendChild(body); addReportControl(wrap, ad, serveCfg); return { wrap: wrap, body: body }; } // Fill the body AFTER the wrapper is attached to the DOM (AdSense // / GPT require the slot element to be in-document before push). function activate(ad, body, serveCfg, kind) { if (ad.type === 'adsense') { var a = ad.adsense || {}; if (serveCfg && serveCfg.demoMode) { renderPlaceholder(body, 'AdSense', adsenseSize(a.format), kind); return true; } if (!a.client) { return false; } loadAdSense(a.client); if (serveCfg && serveCfg.adsenseAutoAds) { if (!state.autoAdsPushed) { state.autoAdsPushed = true; try { (window.adsbygoogle = window.adsbygoogle || []).push({ google_ad_client: a.client, enable_page_level_ads: true }); } catch (e) {} } return false; // Auto Ads place themselves; drop the manual shell. } var ins = document.createElement('ins'); ins.className = 'adsbygoogle'; ins.style.display = 'block'; ins.setAttribute('data-ad-client', a.client); if (a.slot) { ins.setAttribute('data-ad-slot', a.slot); } ins.setAttribute('data-ad-format', a.format || 'auto'); if (a.responsive) { ins.setAttribute('data-full-width-responsive', 'true'); } body.appendChild(ins); try { (window.adsbygoogle = window.adsbygoogle || []).push({}); } catch (e) {} return true; } if (ad.type === 'gam') { var g = ad.gam || {}; if (serveCfg && serveCfg.demoMode) { renderPlaceholder(body, 'Ad Manager', firstSize(parseSizes(g.sizes)), kind); return true; } if (!g.unitPath) { return false; } loadGpt(); var sizes = parseSizes(g.sizes); var divId = 'fca-gpt-' + ad.id + '-' + Math.random().toString(36).slice(2, 8); var slotDiv = document.createElement('div'); slotDiv.id = divId; body.appendChild(slotDiv); window.googletag = window.googletag || { cmd: [] }; window.googletag.cmd.push(function () { var slot = window.googletag.defineSlot(g.unitPath, sizes.length ? sizes : ['fluid'], divId); if (slot) { slot.addService(window.googletag.pubads()); window.googletag.enableServices(); window.googletag.display(divId); } }); return true; } if (ad.type === 'custom') { var c = ad.custom || {}; if (!c.code) { return false; } renderSandboxed(body, c.code, sizeForKind(kind || 'feed', ad), ad.id); return true; } // house creative — keep body at the resolved footprint applyFixedSize(body, sizeForKind(kind || 'feed', ad)); var h = ad.house || {}; var fmt = h.format || 'both'; var link = document.createElement('a'); link.className = 'fca-ad__house'; link.href = safeUrl(h.linkUrl) || '#'; link.target = safeTarget(h.target); link.rel = 'noopener sponsored'; var bg = safeHexColor(h.bgColor); if (bg) { link.style.backgroundColor = bg; } var inner = ''; var imgUrl = safeUrl(h.imageUrl); if (fmt !== 'copy' && imgUrl) { inner += '' + escapeHtml(h.headline || ad.title || '') + ''; } var titleText = h.headline || ad.title || ''; if (fmt !== 'image' && titleText) { inner += '
' + escapeHtml(titleText) + '
'; } if (fmt !== 'image' && h.body) { // Body is server-side wp_kses_post; still insert via DOM, not eval. var bodyWrap = document.createElement('div'); bodyWrap.className = 'fca-ad__house-body'; bodyWrap.innerHTML = h.body; // Strip any leftover scripts / handlers if present. Array.prototype.forEach.call(bodyWrap.querySelectorAll('script'), function (s) { s.remove(); }); Array.prototype.forEach.call(bodyWrap.querySelectorAll('*'), function (el) { Array.prototype.slice.call(el.attributes || []).forEach(function (a) { if (/^on/i.test(a.name)) { el.removeAttribute(a.name); } if (/^(href|src|action|formaction)$/i.test(a.name) && /^\s*(javascript|vbscript|data)\s*:/i.test(a.value || '')) { el.setAttribute(a.name, '#'); } }); }); inner += bodyWrap.outerHTML; } link.innerHTML = inner; link.addEventListener('click', function () { trackClick(ad.id, serveCfg); }); body.appendChild(link); return true; } function parseSizes(str) { if (!str) { return []; } return String(str).split(',').map(function (s) { var m = s.trim().match(/^(\d+)\s*x\s*(\d+)$/i); return m ? [parseInt(m[1], 10), parseInt(m[2], 10)] : null; }).filter(Boolean); } function zoneCfgOf(res) { return (res && res.zone) || { mode: 'manual', perRow: 1, count: 1, shown: 1, display: 'inherit', rotateSeconds: 8, gapMinutes: 0, frequency: 0, repeat: false }; } // How many ads render side-by-side at once (grid columns). Prefers // the new perRow field, falling back to the legacy `count`. function perRowOf(zcfg) { return Math.max(1, (zcfg && (zcfg.perRow || zcfg.count)) || 1); } // Activate an ad into an already-mounted shell and (unless it's a // synthetic demo/auto slot with no real id) wire impression tracking. function activateInto(ad, shell, serveCfg) { var kind = (shell.wrap && shell.wrap.getAttribute) ? shell.wrap.getAttribute(TAG) : ''; var ok = activate(ad, shell.body, serveCfg, kind); if (!ok) { return false; } if (!ad.demo && ad.id) { shell.wrap.setAttribute('data-ad-id', ad.id); shell.wrap.__fcaSeen = false; watchImpression(shell.wrap, serveCfg); } return true; } // Timed rotation: cycle the shell through the returned pool. Each // step waits for the CURRENTLY shown ad's own duration (paid ads // stick for their plan window), stepping by `perRow` so stacked // slots stay distinct. Uses a self-rescheduling timeout so each ad // can hold for a different length of time. function setupRotation(shell, pool, startIdx, zcfg, serveCfg) { if (!pool || pool.length < 2) { return; } var step = perRowOf(zcfg); var cur = startIdx; window.__fcaAdTimers = window.__fcaAdTimers || []; function durOf(ad) { return Math.max(3, (ad && ad.durationSeconds) || zcfg.rotateSeconds || 8); } function schedule() { var timer = setTimeout(function () { if (!document.body.contains(shell.wrap)) { return; } cur = (cur + step) % pool.length; shell.body.innerHTML = ''; activateInto(pool[cur], shell, serveCfg); schedule(); }, durOf(pool[cur]) * 1000); window.__fcaAdTimers.push(timer); } schedule(); } // The effective display for a slot: each ad carries its own display // (owner repeater sets it per entry); fall back to the zone config. function displayOf(ad, zcfg) { return (ad && ad.display) || (zcfg && zcfg.display) || 'inherit'; } function rotateSecsOf(ad, zcfg) { return (ad && ad.rotateSeconds) || (zcfg && zcfg.rotateSeconds) || 8; } // Any ad in the pool asking to rotate? function anyRotate(list, zcfg) { for (var i = 0; i < list.length; i++) { if (displayOf(list[i], zcfg) === 'rotate') { return true; } } return false; } // Place one slot from a pool at index `idx`; mountFn attaches the // wrapper to the DOM. Rotation is decided by the *ad's* own display. function placeOne(kind, pool, idx, zcfg, serveCfg, mountFn) { var ad = pool[idx % pool.length]; var shell = buildShell(kind, ad, serveCfg); mountFn(shell.wrap, ad); if (!shell.wrap.parentNode) { return; } if (!activateInto(ad, shell, serveCfg)) { shell.wrap.remove(); return; } if (displayOf(ad, zcfg) === 'rotate') { setupRotation(shell, pool, idx, { rotateSeconds: rotateSecsOf(ad, zcfg), perRow: perRowOf(zcfg), }, serveCfg); } } // How many slots to place for a zone: `perRow` (simultaneous ads), // capped by pool size unless any ad rotates (then each slot cycles // the whole pool). function slotCount(list, zcfg) { var slots = perRowOf(zcfg); return anyRotate(list, zcfg) ? slots : Math.min(slots, list.length); } // Stack N slots into a container via a sequential mount callback. // With more than one slot the slots are wrapped in a CSS grid whose // column count matches the zone's `count`, so a placement showing // e.g. 3 ads renders as a 3-up grid. function placeStack(kind, res, mountFn) { var list = ads(res); if (!list.length) { return; } var zcfg = zoneCfgOf(res); var serveCfg = res.config || {}; var n = slotCount(list, zcfg); if (n <= 1) { placeOne(kind, list, 0, zcfg, serveCfg, mountFn); return; } var grid = document.createElement('div'); grid.className = 'fca-zone-grid-slots'; grid.setAttribute(TAG, '1'); grid.style.setProperty('--fca-cols', String(Math.min(n, 6))); mountFn(grid, list[0]); if (!grid.parentNode) { return; } for (var i = 0; i < n; i++) { placeOne(kind, list, i, zcfg, serveCfg, function (el) { grid.appendChild(el); }); } if (!grid.children.length) { grid.remove(); } } // ── DOM targets ──────────────────────────────────────────── // The feed wrapper. Both the home feed (route `all_feeds`) and a // space feed (route `space_feeds`) render the SAME component: // `.fcom_feed_style_.all_feeds`. They are told apart by the // page (onSpacePage) → global-feed vs space-feed zones, NOT by DOM. function feedContainer() { return document.querySelector('.fcom_feed_style_timeline.all_feeds') || document.querySelector('[class*="fcom_feed_style_"]'); } // The element that directly holds the post items. function feedHolder(container) { if (!container) { return null; } return container.querySelector('.all_feeds_holder') || container; } // Feed post items: FC wraps each post in `.feed_outer` inside // `.all_feeds_holder`. Fall back to older/grid layouts. function feedPosts(holder) { if (!holder) { return []; } var items = holder.querySelectorAll(':scope > .feed_outer'); if (items.length) { return items; } items = holder.querySelectorAll(':scope > .feed, :scope > .fcom_feed_card, :scope > .fcom_feed_list, :scope > [id^="feed_id_"]'); if (items.length) { return items; } return holder.querySelectorAll('.feed_outer, .feed, .fcom_feed_card, .fcom_feed_list'); } function sidebar() { return document.querySelector('.fcom_main_side_wrap') || document.querySelector('aside[role="complementary"] .fcom_main_side_wrap') || document.querySelector('#fluent_community_sidebar_menu .fcom_main_side_wrap') || document.querySelector('aside[role="complementary"]'); } // Left navigation column (FC "space_contents" menu). function leftSidebar() { return document.querySelector('#fluent_community_sidebar_menu') || document.querySelector('.fcom_left_side') || document.querySelector('.spaces .space_contents'); } // Main content column (used for single-post / event placements). function mainContent() { return document.querySelector('.feeds_main') || document.querySelector('.fcom_main') || document.querySelector('.fcom_content'); } // Top of the main feed column — where the "header" (leaderboard) // banner goes. Present on the portal home feed and space feeds. // (FC's before_contents hook can't be used: it only renders inside // the RecentActivities widget, i.e. the right sidebar.) function feedColumn() { return document.querySelector('.fcom_feed_box') || document.querySelector('.feeds_main .fcom_feed_box') || document.querySelector('.feeds_main .all_feeds') || document.querySelector('.feeds_main') || feedContainer(); } var PATH = function () { return window.location.pathname + window.location.hash; }; // The FC portal admin area ({portalBase}/admin/…) is a // management surface — never inject ads there. function isAdminArea() { return /\/admin(\/|$)/.test(PATH()) || /#\/?admin(\/|$)/.test(PATH()); } function onEventSingle() { return /\/event\/[^\/?#]+/.test(PATH()); } function onEventList() { return /\/events(\/|\b)/.test(PATH()) && !onEventSingle(); } // A single FluentCommunity feed post ("space post", NOT a WP // post_type=post). FC uses /post/{slug} in the URL for the // dedicated single-post page. function onSinglePost() { return /\/post\/[^\/?#]+/.test(PATH()); } // The single feed-post element, for BOTH the dedicated single-post // page and the overlay popup (an el-dialog `.fcom_feed_modal` // teleported to ). FC marks the single/detail view with the // `.feed_single` class (the timeline cards do NOT have it), so this // one selector distinguishes it from the feed behind an open popup. // Legacy class names kept as a fallback for older FC builds. function singlePostCard() { return document.querySelector('.fcom_feed_modal .feed_single') || document.querySelector('.feed_single') || document.querySelector('.fcom_single_layout .fcom_feed_card') || document.querySelector('.feeds_main .fcom_feed_card') || null; } // The post CONTENT body — where "inside" ads interleave and the // anchor for before/after "content" placements. function postContentBody(card) { return card.querySelector('.feed_body') || card.querySelector('.fcom_feed_card_body') || card; } // The rendered markdown region for "inside content" interleaving. function insideTarget(card) { return card.querySelector('.feed_md_content') || card.querySelector('.feed_body') || card.querySelector('.fcom_feed_excerpt') || card.querySelector('.fcom_feed_data') || card.querySelector('.fcom_feed_card_body') || card; } // Insert an element at start|middle|end of a container's children. function insertByPosition(container, el, position) { var kids = Array.prototype.filter.call(container.children, function (n) { return !n.hasAttribute || !n.hasAttribute(TAG); }); if (position === 'start' || !kids.length) { container.insertBefore(el, container.firstChild); } else if (position === 'end') { container.appendChild(el); } else { var mid = kids[Math.floor(kids.length / 2)]; container.insertBefore(el, mid); } } // Remove only JS-injected ads; server shells (data-fca-server) are // owned by FC's feed rendering and clean themselves up on re-render. function removeAds() { if (window.__fcaAdTimers) { window.__fcaAdTimers.forEach(function (t) { clearInterval(t); }); window.__fcaAdTimers = []; } document.querySelectorAll('[' + TAG + ']:not([data-fca-server])').forEach(function (n) { n.remove(); }); // Let single-post elements be re-decorated after a wipe. document.querySelectorAll('.feed_single, .fcom_feed_card').forEach(function (el) { el.__fcaSingleDone = false; el.__fcaSinglePending = false; }); // Let feed posts be re-decorated after a wipe. document.querySelectorAll('.feed_outer, .feed, .fcom_feed_card, .fcom_feed_list, [id^="feed_id_"]').forEach(function (el) { el.__fcaFeedDone = false; }); state.lastFeed = null; // Restart the feed rotation index for the new page/route so the // top of the feed begins at the start of the pool again. state.feedIdx = 0; } // Place "inside content" slots. With more than one slot the ads are // SPREAD across the content's block children (paragraphs, lists, // etc.) instead of stacking at one spot — e.g. 3 inside ads land at // ~1/4, ~2/4 and ~3/4 through the post body. A single slot honors // the ad's own insidePosition (start/middle/end). function placeInside(kind, res, content) { var list = ads(res); if (!list.length || !content) { return; } var zcfg = zoneCfgOf(res); var serveCfg = res.config || {}; var n = slotCount(list, zcfg); // Block-level children to interleave between (skip our own ads). var kids = Array.prototype.filter.call(content.children, function (node) { return !(node.hasAttribute && node.hasAttribute(TAG)); }); if (n <= 1 || kids.length === 0) { placeOne(kind, list, 0, zcfg, serveCfg, function (el, ad) { insertByPosition(content, el, (ad && ad.insidePosition) || 'middle'); }); return; } // Pick N anchor nodes up front (node refs stay valid as we // insert new siblings), then drop each ad AFTER its anchor. var total = kids.length; var anchors = []; for (var k = 0; k < n; k++) { var idx = (n >= total) ? Math.min(k, total - 1) : Math.floor((k + 1) * total / (n + 1)); if (idx > total - 1) { idx = total - 1; } anchors.push(kids[idx]); } for (var j = 0; j < n; j++) { (function (anchor, idx) { placeOne(kind, list, idx, zcfg, serveCfg, function (el) { anchor.parentNode.insertBefore(el, anchor.nextSibling); }); })(anchors[j], j); } } // ── injectors ────────────────────────────────────────────── // Insert ONE ad block right after `anchor`. The block shows up to // `perBlock` ads (max 3) as a CSS grid — 1 ad = 1 column, 2 = 2, // 3 = 3 — cycling the pool starting at `startIdx`. function insertFeedBlock(list, startIdx, perBlock, zcfg, serveCfg, anchor) { if (!anchor || !anchor.parentNode) { return; } var cols = Math.min(3, Math.max(1, perBlock)); var slots = anyRotate(list, zcfg) ? cols : Math.min(cols, list.length); if (slots < 1) { return; } if (slots === 1) { placeOne('feed', list, startIdx, zcfg, serveCfg, function (el) { anchor.parentNode.insertBefore(el, anchor.nextSibling); }); return; } var grid = document.createElement('div'); grid.className = 'fca-zone-grid-slots fca-feed-grid'; grid.setAttribute(TAG, '1'); grid.style.setProperty('--fca-cols', String(slots)); anchor.parentNode.insertBefore(grid, anchor.nextSibling); for (var s = 0; s < slots; s++) { placeOne('feed', list, startIdx + s, zcfg, serveCfg, function (el) { grid.appendChild(el); }); } if (!grid.children.length) { grid.remove(); } } // Between-feed / space-feed ads. Injects a grid block after every // `frequency` posts. When `repeat` is on the block repeats down the // whole feed (including posts loaded later via infinite scroll, // caught by the feed observer); otherwise it appears once. Each // block shows `count` ads (max 3) in a grid. Idempotent: each // anchor post is decorated at most once. function injectFeed(res) { var container = feedContainer(); if (!container) { return; } var list = ads(res); if (!list.length) { return; } var holder = feedHolder(container); var posts = feedPosts(holder); if (!posts.length) { return; } var zcfg = zoneCfgOf(res); var serveCfg = res.config || {}; var last = posts.length - 1; // Demo placeholders (no real ad yet) flow through the SAME // frequency/repeat logic below so the owner previews the true // "every N posts" + "repeat down feed" behavior, not a one-off. var every = Math.max(1, parseInt(zcfg.frequency, 10) || serveCfg.feedFrequency || 5); var perBlock = Math.min(3, perRowOf(zcfg)); var repeat = !!zcfg.repeat; // Short feeds: clamp frequency so ads still appear (otherwise // frequency=5 on a 3-post feed never injects). if (posts.length > 1 && every >= posts.length) { every = Math.max(1, posts.length - 1); } for (var i = every - 1; i < posts.length; i += every) { // Prefer not to decorate the final `.feed_outer`: FC uses // `.all_feeds_holder .feed_outer:last-child` as its // infinite-scroll sentinel. When the eligible slot *is* // the last post (common with short feeds / frequency=5), // insert after the previous post instead so global-feed // ads still appear. var anchorIdx = i; if (anchorIdx >= last) { if (last < 1) { break; } anchorIdx = last - 1; } var anchor = posts[anchorIdx]; if (!anchor.__fcaFeedDone) { // Continuous index across blocks AND across infinite // scroll: each new block starts where the last left off // and wraps the pool, so different ads appear as you // scroll instead of repeating the first ones. insertFeedBlock(list, state.feedIdx, perBlock, zcfg, serveCfg, anchor); anchor.__fcaFeedDone = true; state.feedIdx += perBlock; } if (!repeat) { break; } // After falling back to last-1, further steps would re-use // the same sentinel-safe anchor — stop. if (i >= last) { break; } } // Remember the latest feed response so the observer can inject // into posts appended by infinite scroll without a re-fetch. state.lastFeed = res; } function injectSidebar(res) { var wrap = sidebar(); if (!wrap || !ads(res).length) { return; } var anchor = wrap.querySelector('.app_side_widget') || wrap.firstElementChild; placeStack('sidebar', res, function (el) { if (anchor && anchor.parentNode) { anchor.parentNode.insertBefore(el, anchor.nextSibling); anchor = el; } else { wrap.appendChild(el); anchor = el; } }); } function injectLeftSidebar(res) { var wrap = leftSidebar(); if (!wrap || !ads(res).length) { return; } placeStack('sidebar-left', res, function (el) { wrap.appendChild(el); }); } // Header (top banner / leaderboard): placed at the very top of the // main feed column, above the post composer and the feed list. function injectHeader(res) { var col = feedColumn(); if (!col || !ads(res).length) { return; } // Avoid stacking duplicate headers if a prior run left one // (SPA re-renders sometimes keep server shells). if (col.querySelector('[' + TAG + '="header"]')) { return; } placeStack('header', res, function (el) { col.insertBefore(el, col.firstChild); }); } // Single-post before / inside / after placements. "before/after // content" anchor around the post body (`.feed_body`), so the ads // sit right above / below the content and don't land after the // comment thread inside the popup. function injectSinglePost(before, inside, after, card) { card = card || singlePostCard(); if (!card) { return; } var body = postContentBody(card); placeStack('post-before', before, function (el) { body.parentNode.insertBefore(el, body); }); placeInside('post-inside', inside, insideTarget(card)); var afterAnchor = body; placeStack('post-after', after, function (el) { afterAnchor.parentNode.insertBefore(el, afterAnchor.nextSibling); afterAnchor = el; }); } // Inject single-post ads once per post element. Works for the // dedicated page AND the overlay popup (which may open with NO route // change, so a MutationObserver — not just route hooks — drives it). // A per-element flag prevents duplicate fetches while the popup or // page re-renders (comments, reactions, etc.). function syncSinglePost() { if (isAdminArea()) { return; } var el = singlePostCard(); if (!el || el.__fcaSingleDone || el.__fcaSinglePending) { return; } el.__fcaSinglePending = true; Promise.all([ fetchServe('post-before', 10), fetchServe('post-inside', 10), fetchServe('post-after', 10) ]).then(function (a) { if (singlePostCard() !== el || !document.body.contains(el)) { el.__fcaSinglePending = false; return; } injectSinglePost(a[0], a[1], a[2], el); el.__fcaSingleDone = true; el.__fcaSinglePending = false; }).catch(function () { el.__fcaSinglePending = false; }); } // Event single (before/inside/after) and event listing placements. function injectEvents(bundle) { var main = mainContent(); if (!main) { return; } if (onEventSingle()) { var beforeAnchor = main.firstChild; placeStack('event-single-before', bundle.before, function (el) { main.insertBefore(el, beforeAnchor); }); placeInside('event-single-inside', bundle.inside, main); placeStack('event-single-after', bundle.after, function (el) { main.appendChild(el); }); } else if (onEventList()) { var listAnchor = main.firstChild; placeStack('event-list', bundle.list, function (el) { main.insertBefore(el, listAnchor); }); } } // ── server-rendered ad shells (e.g. the [fca_ad] shortcode) ── // Activate + track any shell rendered into the DOM server-side. function activateServerAds(serveCfg) { var shells = document.querySelectorAll('[data-fca-server="1"]:not([data-fca-activated])'); shells.forEach(function (shell) { shell.setAttribute('data-fca-activated', '1'); var body = shell.querySelector('.fca-ad__body') || shell; var type = shell.getAttribute('data-ad-type'); var adId = shell.getAttribute('data-ad-id'); // Demo shells already contain their placeholder markup; // just track the impression, never call the network. if (shell.getAttribute('data-fca-demo') === '1') { watchImpression(shell, serveCfg); return; } addReportControl(shell, { id: adId, demo: false }, serveCfg); if (type === 'adsense') { loadAdSense(shell.getAttribute('data-ad-client')); try { (window.adsbygoogle = window.adsbygoogle || []).push({}); } catch (e) {} } else if (type === 'gam') { loadGpt(); var sizes = parseSizes(shell.getAttribute('data-gam-sizes')); var unit = shell.getAttribute('data-gam-unit'); var divId = 'fca-gpt-' + adId + '-' + Math.random().toString(36).slice(2, 8); var slotDiv = document.createElement('div'); slotDiv.id = divId; body.appendChild(slotDiv); window.googletag = window.googletag || { cmd: [] }; window.googletag.cmd.push(function () { var slot = window.googletag.defineSlot(unit, sizes.length ? sizes : ['fluid'], divId); if (slot) { slot.addService(window.googletag.pubads()); window.googletag.enableServices(); window.googletag.display(divId); } }); } else if (type === 'custom' || shell.getAttribute('data-fca-custom') === '1') { // Ensure fixed size + sandboxed iframe (migrates older // raw-HTML shells that predate the sandbox). var kind = shell.getAttribute(TAG) || 'feed'; var sizeKey = shell.getAttribute('data-fca-size') || ''; var size = sizeForKind(kind, sizeKey ? { sizeKey: sizeKey } : null); // Prefer dimensions already stamped on the server shell. var dw = parseInt(shell.getAttribute('data-fca-w') || '0', 10); var dh = parseInt(shell.getAttribute('data-fca-h') || '0', 10); if (dw > 0 && dh > 0) { size = { w: dw, h: dh, key: sizeKey || size.key, label: dw + '\u00d7' + dh }; } applyFixedSize(body, size); shell.classList.add('fca-ad--fixed'); shell.setAttribute('data-fca-w', String(size.w || 336)); shell.setAttribute('data-fca-h', String(size.h || 280)); if (!body.querySelector('iframe.fca-ad__sandbox')) { var html = body.innerHTML; body.innerHTML = ''; renderSandboxed(body, html, size, adId); } else { var frame = body.querySelector('iframe.fca-ad__sandbox'); if (frame) { frame.style.height = (size.h || 280) + 'px'; frame.height = String(size.h || 280); if (adId) { frame.setAttribute('data-ad-id', String(adId)); } // Re-clip / inject click beacon for older sandboxed creatives. try { var doc = frame.getAttribute('srcdoc') || ''; if (doc && doc.indexOf('fca-ad-click') === -1) { if (doc.indexOf('fca-ad-clip') === -1) { frame.srcdoc = clippedSrcdoc(doc, size, adId); } else if (adId) { var beaconOnly = '