1<!DOCTYPE html> 2<html lang="de-DE"> 3 4<head> 5 <meta charset="UTF-8"> 6 <meta name="viewport" content="width=device-width, initial-scale=1"> 7 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 8 <link rel="profile" href="http://gmpg.org/xfn/11"> 9 <link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/npm/[email protected]/slick/slick.css" /> 10 <!--
10<script src="https://kit.fontawesome.com/c54d711b5b.js" crossorigin="anonymous"></script>
10 --> 11 <!--
11<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
11 12
12<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
12 13
13<script type="text/javascript" src="//cdn.jsdelivr.net/npm/[email protected]/slick/slick.min.js"></script>
13 --> 14 15 <link rel="stylesheet" href="https://www.rollingstone.de/wp-content/themes/RS-Theme-2023/inc/assets/css/slick.css"> 16 <link rel="stylesheet" href="https://www.rollingstone.de/wp-content/themes/RS-Theme-2023/inc/assets/css/slick-theme.css"> 17
17<script src="https://www.rollingstone.de/wp-content/themes/RS-Theme-2023/inc/assets/js/jquery-3.6.0.min.js"></script>
17 18
18<script src="https://www.rollingstone.de/wp-content/themes/RS-Theme-2023/inc/assets/js/bootstrap-5.1.3.bundle.min.js"></script>
18 19
19<script src="https://www.rollingstone.de/wp-content/themes/RS-Theme-2023/inc/assets/js/slick.min.js"></script>
19 20 21 <!-- Script https://resources-production.la.welt.de/loader/la-loader-default.js blocked until consent is given -->
22<script type="text/javascript"> 23 if (typeof window.rs_blocked_scripts === "undefined") { 24 window.rs_blocked_scripts = []; 25 } 26 window.rs_blocked_scripts.push({ 27 blocked_src: "https://resources-production.la.welt.de/loader/la-loader-default.js", 28 category: "advertising", 29 id: "interactive-tools-js", 30 async: true 31 }); 32 </script>
32 33 34 <!--
34<script type='text/javascript' src="https://www.rollingstone.de/wp-content/themes/RS-Theme-2023/main.js"></script>
34 --> 35 <!--
35<script src="https://cdn.bitmovin.com/player/web/8/bitmovinplayer.js" type="text/javascript"></script>
35 --> 36
36<script type="text/javascript" id="rs-contentpass-script-blocker"> 37 (function() { 38 39 if (window.rs_consent_given === true) { 40 return; 41 } 42 43 window.rs_check_consent_status = function() { 44 try { 45 if (localStorage.getItem('_sp_v1_consent')) { 46 return true; 47 } 48 49 // Check for Sourcepoint consent in localStorage 50 try { 51 var spConsentData = localStorage.getItem('_sp_user_consent_33834'); 52 if (spConsentData) { 53 var consentData = JSON.parse(spConsentData); 54 55 // Check if user has consented to all purposes (full consent) 56 if (consentData && consentData.gdpr && consentData.gdpr.consentStatus && 57 consentData.gdpr.consentStatus.consentedAll === true) { 58 console.log('[RS Script Blocker] Full consent detected (consentedAll=true)'); 59 return true; 60 } 61 62 // If not full consent, check for specific ad-related consent 63 if (consentData && consentData.gdpr && consentData.gdpr.grants) { 64 // Ad-related purpose IDs (based on consent_cookie.doc analysis) 65 // These IDs correspond to advertising-related purposes 66 var adRelatedPurposeIds = [ 67 '68376c7807181a682b59bbce', // Create profiles for personalised advertising 68 '68376c7807181a682b59bc78', // Select personalised advertising 69 '68376c7807181a682b59bf8c', // Create a personalised ads profile 70 '68376c7807181a682b59c422', // Select basic ads 71 '68376c7907181a682b59c847' // Measure ad performance 72 ]; 73 74 // Check for ad-related purpose grants 75 var hasAdConsent = false; 76 77 // Check if any vendor has ad-related purpose grants 78 for (var vendorId in consentData.gdpr.grants) { 79 var vendor = consentData.gdpr.grants[vendorId]; 80 81 // Skip if vendor has no purpose grants 82 if (!vendor.purposeGrants) continue; 83 84 // Check if any ad-related purpose is granted 85 for (var i = 0; i < adRelatedPurposeIds.length; i++) { 86 var purposeId = adRelatedPurposeIds[i]; 87 if (vendor.purposeGrants[purposeId] === true) { 88 console.log('[RS Script Blocker] Ad-related purpose consent found for purpose:', purposeId); 89 hasAdConsent = true; 90 break; 91 } 92 } 93 94 if (hasAdConsent) break; 95 } 96 97 if (hasAdConsent) { 98 console.log('[RS Script Blocker] Ad-related consent found in localStorage'); 99 return true; 100 } 101 } 102 } 103 } catch (e) { 104 console.error('[RS Script Blocker] Error checking _sp_user_consent_33834:', e); 105 } 106 107 var cpToken = localStorage.getItem('cp_token') || localStorage.getItem('cp.token'); 108 if (cpToken && cpToken.split('.').length === 3) { 109 return true; 110 } 111 112 if (sessionStorage.getItem('rs_consent_given') === 'true') { 113 return true; 114 } 115 116 117 } catch (e) { 118 console.log('Error', 'Error checking consent', e); 119 } 120 121 return false;
122 }; 123 124 // Create a debug logger for ContentPass SDK calls 125 window.rs_cp_debug_logger = { 126 calls: [], 127 maxCalls: 50, 128 logCall: function(command, args) { 129 try { 130 this.calls.push({ 131 command: command, 132 args: args, 133 timestamp: new Date().toISOString() 134 }); 135 136 if (this.calls.length > this.maxCalls) { 137 this.calls.shift(); 138 } 139 140 if (command === 'authenticate' || command === 'render' || command === 'on') { 141 console.log('ContentPass', 'SDK call observed: ' + command, { 142 args: args, 143 timestamp: new Date().toISOString() 144 }); 145 } 146 147 148 } catch (e) { 149 console.error('[RS Debug] Error in passive CP monitoring:', e); 150 } 151 } 152 }; 153 154 window.rs_cp_observer = new MutationObserver(function(mutations) { 155 if (typeof window.cp === 'function' && !window._rs_cp_monitored) { 156 window._rs_cp_monitored = true; 157 158 document.addEventListener('rsContentPassAuthStatusChanged', function(event) { 159 if (event.detail && typeof event.detail.isAuthenticated === 'boolean') { 160 window.rs_cp_debug_logger.logCall('authStatusChanged', [event.detail.isAuthenticated]); 161 } 162 }); 163 164 window.rs_cp_observer.disconnect(); 165 } 166 }); 167 168 window.rs_cp_observer.observe(document, { 169 childList: true, 170 subtree: true 171 }); 172 173 setTimeout(function() { 174 if (window.rs_cp_observer) { 175 window.rs_cp_observer.disconnect(); 176 } 177 }, 10000); 178 179 function checkExistingConsent() { 180 try { 181 function getCookie(name) { 182 var match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)')); 183 return match ? match[2] : null; 184 } 185 186 if (getCookie('rs_consent_given') === 'true') { 187 window.rs_consent_given = true; 188 return 'cmp'; 189 } 190 191 // Check for Sourcepoint CMP consent in localStorage 192 try { 193 var spConsentData = localStorage.getItem('_sp_user_consent_33834'); 194 if (spConsentData) { 195 var consentData = JSON.parse(spConsentData); 196 197 // Check if user has consented to all purposes (full consent) 198 if (consentData && consentData.gdpr && consentData.gdpr.consentStatus && 199 consentData.gdpr.consentStatus.consentedAll === true) { 200 console.log('[RS Script Blocker] Full consent detected (consentedAll=true)'); 201 window.rs_consent_given = true; 202 return 'cmp'; 203 } 204 205 // If not full consent, check for specific ad-related consent 206 if (consentData && consentData.gdpr && consentData.gdpr.grants) { 207 // Ad-related purpose IDs (based on consent_cookie.doc analysis) 208 var adRelatedPurposeIds = [ 209 '68376c7807181a682b59bbce', // Create profiles for personalised advertising 210 '68376c7807181a682b59bc78', // Select personalised advertising 211 '68376c7807181a682b59bf8c', // Create a personalised ads profile 212 '68376c7807181a682b59c422', // Select basic ads 213 '68376c7907181a682b59c847' // Measure ad performance 214 ]; 215 216 // Check for ad-related purpose grants 217 var hasAdConsent = false;
218 219 // Check if any vendor has ad-related purpose grants 220 for (var vendorId in consentData.gdpr.grants) { 221 var vendor = consentData.gdpr.grants[vendorId]; 222 223 // Skip if vendor has no purpose grants 224 if (!vendor.purposeGrants) continue; 225 226 // Check if any ad-related purpose is granted 227 for (var i = 0; i < adRelatedPurposeIds.length; i++) { 228 var purposeId = adRelatedPurposeIds[i]; 229 if (vendor.purposeGrants[purposeId] === true) { 230 console.log('[RS Script Blocker] Ad-related purpose consent found for purpose:', purposeId); 231 hasAdConsent = true; 232 break; 233 } 234 } 235 236 if (hasAdConsent) break; 237 } 238 239 if (hasAdConsent) { 240 console.log('[RS Script Blocker] Ad-related consent found in localStorage'); 241 window.rs_consent_given = true; 242 return 'cmp'; 243 } 244 } 245 } 246 } catch (e) { 247 console.error('[RS Script Blocker] Error parsing _sp_user_consent_33834 from localStorage:', e); 248 } 249 250 if (sessionStorage.getItem('rs_consent_given') === 'true') { 251 window.rs_consent_given = true; 252 return 'cmp'; 253 } 254 255 var urlParams = new URLSearchParams(window.location.search); 256 if (urlParams.get('rs_force_consent') === 'true') { 257 window.rs_consent_given = true; 258 return 'cmp'; 259 } 260 261 var cpToken = localStorage.getItem('cp_token') || localStorage.getItem('cp.token'); 262 if (cpToken && cpToken.split('.').length === 3) { 263 window.rs_cp_authenticated = true; 264 return 'contentpass'; 265 } 266 267 if (sessionStorage.getItem('rs_cp_authenticated') === 'true') { 268 window.rs_cp_authenticated = true; 269 return 'contentpass'; 270 } 271 } catch (e) { 272 console.error('[RS Script Blocker] Error checking existing consent:', e); 273 } 274 275 return false; 276 } 277 278 window.rs_consent_given = window.rs_consent_given || false; 279 window.rs_cp_authenticated = window.rs_cp_authenticated || false; 280 281 var consentStatus = checkExistingConsent(); 282 283 if (consentStatus === 'cmp') { 284 window.rs_consent_given = true; 285 window.rs_monitoring_mode = true; 286 return; 287 } 288 else if (consentStatus === 'contentpass') { 289 window.rs_cp_authenticated = true; 290 window.rs_monitoring_mode = false;
291 } 292 else { 293 window.rs_monitoring_mode = false; 294 } 295 296 window.RSScriptBlocker = { 297 initialized: true, 298 blockedRequests: [], 299 blockedDomains: [], 300 whitelistedDomains: ["rollingstone.de","cdn.privacy-mgmt.com","privacy-mgmt.com","localhost","stage.rollingstone.de","tags.tiqcdn.com","assets.adobedtm.com"], 301 originalFunctions: { 302 createElement: document.createElement, 303 appendChild: Element.prototype.appendChild, 304 insertBefore: Element.prototype.insertBefore, 305 fetch: window.fetch, 306 open: XMLHttpRequest.prototype.open, 307 Image: window.Image 308 } 309 }; 310 311 window.rs_blocked_scripts = window.rs_blocked_scripts || []; 312 window.rs_consent_given = window.rs_consent_given || false; 313 window.rs_blocking_start_time = new Date().getTime(); 314 315 window.rs_monitor_consent = function() { 316 if (!window.rs_consent_given && typeof window.__tcfapi === 'function') { 317 try { 318 if (!window.rs_tcfapi_in_progress) { 319 window.rs_tcfapi_in_progress = true; 320 window.__tcfapi('getTCData', 2, function(tcData, success) { 321 window.rs_tcfapi_in_progress = false; 322 if (success && (tcData.eventStatus === 'tcloaded' || tcData.eventStatus === 'useractioncomplete')) { 323 if (tcData.purpose && tcData.purpose.consents && tcData.purpose.consents[1]) { 324 window.rs_consent_given = true; 325 window.rs_load_blocked_scripts(['all']); 326 } 327 } 328 }); 329 } 330 } catch (e) { 331 window.rs_tcfapi_in_progress = false; 332 } 333 } 334 335 var cpToken = localStorage.getItem('cp_token') || localStorage.getItem('cp.token'); 336 if (cpToken && cpToken.split('.').length === 3) { 337 window.rs_load_blocked_scripts(['content']); 338 } 339 340 if (sessionStorage.getItem('rs_consent_given') === 'true') { 341 window.rs_load_blocked_scripts(['all']); 342 } 343 }; 344 345 /* window.rs_monitor_consent(); 346 window.rs_consent_monitor_interval = setInterval(window.rs_monitor_consent, 500); 347 348 setTimeout(function() { 349 if (window.rs_consent_monitor_interval) { 350 clearInterval(window.rs_consent_monitor_interval); 351 console.log('[RS Script Blocker] Stopped consent monitoring after timeout'); 352 } 353 }, 30000); */ 354 355 // Initialize categorized blocking patterns 356 window.RSScriptBlocker.blockingPatterns = { 357 all: ["https:\/\/functions.adnami.io\/api\/macro\/adsm.macro.rollingstone.de.js","https:\/\/macro.adnami.io\/macro\/gen\/adsm.macro.rmb.js","https:\/\/iqdigital-cdn.relevant-digital.com\/static\/tags\/67db0d51682253cc4e3e1dc6.js","https:\/\/iqdigital.demdex.net\/id","https:\/\/sync.mathtag.com\/sync\/img","https:\/\/acdn.adnxs.com\/ast\/ast.js","https:\/\/cm.everesttech.net\/cm\/dd","https:\/\/ib.adnxs.com\/getuid","https:\/\/ads.pubmatic.com\/AdServer\/js\/pwt\/","https:\/\/cm.g.doubleclick.net\/pixel","https:\/\/cdn.id5-sync.com\/api\/1.0\/id5-api.js","https:\/\/5baf1288cf.dl8.me","https:\/\/t.pubmatic.com\/wl","https:\/\/ad.linksynergy.com","https:\/\/click.linksynergy.com","click.linksynergy.com","linksynergy.com","https:\/\/adobedc.demdex.net\/ee\/v1\/identity\/acquire","https:\/\/match.adsrvr.org\/track\/cmf\/generic","https:\/\/dpm.demdex.net\/ibs:dpid=","https:\/\/s3.eu-central-1.amazonaws.com\/prod.iqdcontroller.iqdigital","https:\/\/www.google.com","https:\/\/play.google.com","https:\/\/magic.cool-captcha.de","https:\/\/playlist.megaphone.fm\/","https:\/\/playlist.megaphone.fm\/assets\/application-","https:\/\/player.megaphone.fm\/playlist\/","playlist.megaphone.fm","player.megaphone.fm","https:\/\/o22381.ingest.us.sentry.io","https:\/\/gew1-spclient.spotify.com\/","https:\/\/apresolve.spotify.com\/","https:\/\/open.spotify.com\/","https:\/\/embed-cdn.spotifycdn.com\/","https:\/\/player.simplecast.com","https:\/\/cdn.greenvideo.io\/players\/gv.js","https:\/\/cdn.greenvideo.io\/adapter\/player\/","https:\/\/embeds.greenvideo.io\/cv\/","https:\/\/media-api-prod.greenvideo.io\/api\/v1\/content\/","https:\/\/5baf1288cf.dl8.me\/","https:\/\/nextgen.kajomigenerator.de\/static\/js\/app_kajomi_helper.js","https:\/\/nextgen.kajomigenerator.de\/static\/js\/app_kajomi_iframe.js","https:\/\/asmusik.kjm6.de\/l\/867de433-316d-467e-a964-0e3cc4d14a3f.html","https:\/\/asmusik.kjm6.de\/l\/e2df3861-af53-49e2-8856-41cd5b130cbc.html","nextgen.kajomigenerator.de","kajomigenerator.de","kjm6.de","https:\/\/resources-production.la.welt.de\/loader\/la-loader-default.js","https:\/\/resources-production.la.welt.de\/loader\/la-commons.js","https:\/\/resources-production.la.welt.de\/la-hyper\/la-hyper.js","resources-production.la.welt.de","https:\/\/player.podigee-cdn.net","https:\/\/freiwillige-filmkontrolle.podigee.io","https:\/\/www.youtube.com","https:\/\/www.youtube.com\/embed\/","https:\/\/youtube.com","https:\/\/youtube.com\/embed\/","https:\/\/youtu.be","https:\/\/jnn-pa.googleapis.com","https:\/\/www.gstatic.
357com","https:\/\/widgets.outbrain.com\/outbrain.js","https:\/\/widgets.outbrain.com\/nanoWidget\/externals\/topics\/topics.html","https:\/\/widget-pixels.outbrain.com\/widget\/detect\/px.gif","tcheck.outbrainimg.com","mv.outbrain.com"], 358 advertising: ["https:\/\/functions.adnami.io\/api\/macro\/adsm.macro.rollingstone.de.js","https:\/\/macro.adnami.io\/macro\/gen\/adsm.macro.rmb.js","https:\/\/iqdigital-cdn.relevant-digital.com\/static\/tags\/67db0d51682253cc4e3e1dc6.js","https:\/\/iqdigital.demdex.net\/id","https:\/\/sync.mathtag.com\/sync\/img","https:\/\/acdn.adnxs.com\/ast\/ast.js","https:\/\/cm.everesttech.net\/cm\/dd","https:\/\/ib.adnxs.com\/getuid","https:\/\/ads.pubmatic.com\/AdServer\/js\/pwt\/","https:\/\/cm.g.doubleclick.net\/pixel","https:\/\/cdn.id5-sync.com\/api\/1.0\/id5-api.js","https:\/\/5baf1288cf.dl8.me","https:\/\/t.pubmatic.com\/wl","https:\/\/ad.linksynergy.com","https:\/\/click.linksynergy.com","click.linksynergy.com","linksynergy.com","https:\/\/adobedc.demdex.net\/ee\/v1\/identity\/acquire","https:\/\/match.adsrvr.org\/track\/cmf\/generic","https:\/\/dpm.demdex.net\/ibs:dpid=","https:\/\/s3.eu-central-1.amazonaws.com\/prod.iqdcontroller.iqdigital","https:\/\/www.google.com","https:\/\/play.google.com","https:\/\/magic.cool-captcha.de","https:\/\/playlist.megaphone.fm\/","https:\/\/playlist.megaphone.fm\/assets\/application-","https:\/\/player.megaphone.fm\/playlist\/","playlist.megaphone.fm","player.megaphone.fm","https:\/\/o22381.ingest.us.sentry.io","https:\/\/gew1-spclient.spotify.com\/","https:\/\/apresolve.spotify.com\/","https:\/\/open.spotify.com\/","https:\/\/embed-cdn.spotifycdn.com\/","https:\/\/player.simplecast.com","https:\/\/cdn.greenvideo.io\/players\/gv.js","https:\/\/cdn.greenvideo.io\/adapter\/player\/","https:\/\/embeds.greenvideo.io\/cv\/","https:\/\/media-api-prod.greenvideo.io\/api\/v1\/content\/","https:\/\/5baf1288cf.dl8.me\/","https:\/\/nextgen.kajomigenerator.de\/static\/js\/app_kajomi_helper.js","https:\/\/nextgen.kajomigenerator.de\/static\/js\/app_kajomi_iframe.js","https:\/\/asmusik.kjm6.de\/l\/867de433-316d-467e-a964-0e3cc4d14a3f.html","https:\/\/asmusik.kjm6.de\/l\/e2df3861-af53-49e2-8856-41cd5b130cbc.html","nextgen.kajomigenerator.de","kajomigenerator.de","kjm6.de","https:\/\/resources-production.la.welt.de\/loader\/la-loader-default.js","https:\/\/resources-production.la.welt.de\/loader\/la-commons.js","https:\/\/resources-production.la.welt.de\/la-hyper\/la-hyper.js","resources-production.la.welt.de","https:\/\/player.podigee-cdn.net","https:\/\/freiwillige-filmkontrolle.podigee.io","https:\/\/www.youtube.com","https:\/\/www.youtube.com\/embed\/","https:\/\/youtube.com","https:\/\/youtube.com\/embed\/","https:\/\/youtu.be","https:\/\/jnn-pa.googleapis.com","https:\/\/www.gstatic.com","https:\/\/widgets.outbrain.com\/outbrain.js","https:\/\/widgets.outbrain.com\/nanoWidget\/externals\/topics\/topics.html","https:\/\/widget-pixels.outbrain.com\/widget\/detect\/px.gif","tcheck.outbrainimg.com","mv.outbrain.com"], 359 content: [] }; 360 361 window.RSScriptBlocker.blockedDomains = []; 362 window.RSScriptBlocker.domainCategories = {}; 363 364 function processPatterns(patterns, category) { 365 patterns.forEach(function(pattern) { 366 try { 367 var domain = pattern; 368 369 if (domain.indexOf('://') !== -1) { 370 domain = domain.split('://')[1]; 371 } 372 373 if (domain.indexOf('/') !== -1) { 374 domain = domain.split('/')[0]; 375 } 376 if (domain.indexOf('/') !== -1) { 377 domain = domain.split('/')[0]; 378 } 379 380 if (window.RSScriptBlocker.blockedDomains.indexOf(domain) === -1) { 381 window.RSScriptBlocker.blockedDomains.push(domain); 382 } 383 384 window.RSScriptBlocker.domainCategories[domain] = category; 385 } catch (e) { 386 console.error('[RS Script Blocker] Error processing pattern:', pattern, e); 387 } 388 }); 389 } 390 391 processPatterns(window.RSScriptBlocker.blockingPatterns.advertising, 'advertising'); 392 processPatterns(window.RSScriptBlocker.blockingPatterns.content, 'content'); 393 394 function extractDomain(url) { 395 if (!url) return null; 396 397 try { 398 if (url.indexOf('//') === 0) { 399 url = window.location.protocol + url; 400 } else if (url.indexOf('/') === 0) { 401 return window.location.hostname; // Same-origin request 402 } 403 404 var domain = url; 405 406 if (domain.indexOf('://') !== -1) { 407 domain = domain.split('://')[1]; 408 } 409 410 if (domain.indexOf('/') !== -1) { 411 domain = domain.split('/')[0]; 412 } 413 414 if (domain.indexOf(':') !== -1) { 415 domain = domain.split(':')[0]; 416 } 417 418 return domain; 419 if (domain.indexOf(':') !== -1) { 420 domain = domain.split(':')[0]; 421 } 422 423 return domain; 424 } catch (e) { 425 return null; 426 } 427 } 428 429 function shouldBlockDomain(domain) { 430 if (!domain) return false;
431 432 for (var i = 0; i < window.RSScriptBlocker.whitelistedDomains.length; i++) { 433 var whitelistedDomain = window.RSScriptBlocker.whitelistedDomains[i]; 434 if (domain === whitelistedDomain || domain.endsWith('.' + whitelistedDomain)) { 435 return false; 436 } 437 } 438 439 var isBlockedDomain = false; 440 var domainCategory = null; 441 442 for (var i = 0; i < window.RSScriptBlocker.blockedDomains.length; i++) { 443 var blockedDomain = window.RSScriptBlocker.blockedDomains[i]; 444 if (domain === blockedDomain || domain.endsWith('.' + blockedDomain)) { 445 isBlockedDomain = true; 446 domainCategory = getDomainCategory(domain); 447 break; 448 } 449 } 450 451 if (!isBlockedDomain) { 452 return false; 453 } 454 455 if (window.rs_consent_given) { 456 return false; 457 } 458 459 if (window.rs_cp_authenticated) { 460 return domainCategory === 'advertising'; 461 } 462 463 return true; 464 } 465 466 function getDomainCategory(domain) { 467 468 if (!domain) { 469 return 'advertising'; 470 } 471 472 if (window.RSScriptBlocker.domainCategories[domain]) { 473 return window.RSScriptBlocker.domainCategories[domain]; 474 } 475 476 for (var blockedDomain in window.RSScriptBlocker.domainCategories) { 477 if (domain.endsWith('.' + blockedDomain) || domain.indexOf(blockedDomain) !== -1) { 478 return window.RSScriptBlocker.domainCategories[blockedDomain]; 479 } 480 } 481 482 /* if (domain.indexOf('megaphone.fm') !== -1 || 483 domain.indexOf('greenvideo.io') !== -1 || 484 domain.indexOf('kajomi') !== -1 || 485 domain.indexOf('kjm6.de') !== -1 || 486 domain.indexOf('la.welt.de') !== -1) { 487 return 'advertising'; 488 } */ 489 return 'advertising'; 490 } 491 492 var originalCreateElement = document.createElement; 493 document.createElement = function() { 494 var element = originalCreateElement.apply(document, arguments); 495 var tagName = arguments[0] && arguments[0].toLowerCase(); 496 497 if (tagName === 'script') { 498 var originalSetAttribute = element.setAttribute; 499 500 element.setAttribute = function(name, value) { 501 if (name.toLowerCase() === 'src') { 502 var domain = extractDomain(value); 503 504 if (domain && shouldBlockDomain(domain)) { 505 var category = getDomainCategory(domain); 506 507 window.RSScriptBlocker.blockedRequests.push({ 508 type: 'script', 509 url: value, 510 domain: domain, 511 category: category, 512 timestamp: new Date().getTime() 513 }); 514 515 originalSetAttribute.call(this, 'data-rs-src', value); 516 originalSetAttribute.call(this, 'data-rs-blocked', 'true'); 517 originalSetAttribute.call(this, 'data-rs-category', category); 518 originalSetAttribute.call(this, 'data-rs-pattern', domain); 519 originalSetAttribute.call(this, 'type', 'text/plain'); 520 521 element.blocked_src = value; 522 element.blocked_time = new Date().getTime(); 523 window.rs_blocked_scripts.push(element); 524 525 return; 526 } 527 } 528 529 return originalSetAttribute.apply(this, arguments); 530 }; 531 532 var initialSrc = element.getAttribute('src'); 533 if (initialSrc) { 534 var domain = extractDomain(initialSrc); 535 536 if (domain && shouldBlockDomain(domain)) { 537 var category = getDomainCategory(domain); 538 539 window.RSScriptBlocker.blockedRequests.push({ 540 type: 'script-initial-src', 541 url: initialSrc, 542 domain: domain, 543 category: category, 544 timestamp: new Date().getTime() 545 }); 546 547 element.setAttribute('data-rs-src', initialSrc); 548 element.setAttribute('data-rs-blocked', 'true'); 549 element.setAttribute('data-rs-category', category); 550 element.setAttribute('data-rs-pattern', domain); 551 element.setAttribute('type', 'text/plain'); 552 element.blocked_src = initialSrc; 553 element.blocked_time = new Date().getTime(); 554 window.rs_blocked_scripts.push(element); 555 } 556 } 557 } 558 559 return element; 560 }; 561 562 Element.prototype.appendChild = function(node) { 563 if (node.nodeName && node.nodeName.toLowerCase() === 'script') { 564 var src = node.getAttribute('src') || node.src; 565 if (src) { 566 var domain = extractDomain(src); 567 if (domain && shouldBlockDomain(domain) && !window.rs_consent_given) { 568 var category = getDomainCategory(domain); 569 570 window.RSScriptBlocker.blockedRequests.push({ 571 type: 'script-append', 572 url: src, 573 domain: domain, 574 category: category, 575 timestamp: new Date().getTime() 576 }); 577 node.setAttribute('data-rs-src', src); 578 node.setAttribute('data-rs-blocked', 'true'); 579 node.setAttribute('data-rs-category', category); 580 node.setAttribute('data-rs-pattern', domain); 581 node.removeAttribute('src'); 582 node.setAttribute('type', 'text/plain'); 583 node.blocked_src = src; 584 node.blocked_time = new Date().getTime(); 585 window.rs_blocked_scripts.push(node); 586 } 587 } else { 588 // Skip blocking for Yoast SEO schema.org structured data 589 var nodeClass = node.getAttribute('class') || ''; 590 var nodeType = node.getAttribute('type') || ''; 591 var isYoastSchema = nodeClass.indexOf('yo
591ast-schema-graph') !== -1 || 592 nodeType === 'application/ld+json'; 593 594 if (isYoastSchema) { 595 // Don't block Yoast schema - it's essential for SEO 596 return window.RSScriptBlocker.originalFunctions.appendChild.call(this, node); 597 } 598 599 var scriptId = node.getAttribute('id') || ''; 600 if (scriptId.indexOf('rs-contentpass') !== -1) { 601 return window.RSScriptBlocker.originalFunctions.appendChild.call(this, node); 602 } 603 604 var scriptContent = node.textContent || node.innerText || ''; 605 var containsBlockedDomain = false; 606 var blockedDomain = null; 607 608 for (var i = 0; i < window.RSScriptBlocker.blockedDomains.length; i++) { 609 var domain = window.RSScriptBlocker.blockedDomains[i]; 610 if (scriptContent.indexOf(domain) !== -1) { 611 containsBlockedDomain = true; 612 blockedDomain = domain; 613 break; 614 } 615 } 616 617 // Get the category for this domain 618 var category = getDomainCategory(blockedDomain); 619 620 // Check if we should block based on consent and authentication 621 // For 'content' category, also check ContentPass authentication 622 var shouldBlock = !window.rs_consent_given && 623 !(category === 'content' && window.rs_cp_authenticated === true); 624 625 if (containsBlockedDomain && shouldBlock) { 626 var category = getDomainCategory(blockedDomain); 627 window.RSScriptBlocker.blockedRequests.push({ 628 type: 'inline-script', 629 domain: blockedDomain, 630 category: category, 631 timestamp: new Date().getTime() 632 }); 633 node.setAttribute('data-rs-original-content', scriptContent); 634 node.setAttribute('data-rs-blocked', 'true'); 635 node.setAttribute('data-rs-category', category); 636 node.setAttribute('data-rs-pattern', blockedDomain); 637 node.setAttribute('type', 'text/plain'); 638 node.textContent = '/* Blocked inline script referencing ' + blockedDomain + ' */'; 639 node.blocked_content = scriptContent; 640 node.blocked_time = new Date().getTime(); 641 window.rs_blocked_scripts.push(node); 642 } 643 } 644 } 645 return window.RSScriptBlocker.originalFunctions.appendChild.call(this, node); 646 }; 647 648 // Override insertBefore to prevent blocked scripts from executing 649 Element.prototype.insertBefore = function(node, referenceNode) { 650 if (node.nodeName && node.nodeName.toLowerCase() === 'script') { 651 var src = node.getAttribute('src') || node.src; 652 if (src) { 653 var domain = extractDomain(src); 654 if (domain && shouldBlockDomain(domain) && !window.rs_consent_given) { 655 var category = getDomainCategory(domain); 656 657 window.RSScriptBlocker.blockedRequests.push({ 658 type: 'script-insert', 659 url: src, 660 domain: domain, 661 category: category, 662 timestamp: new Date().getTime() 663 }); 664 665 node.setAttribute('data-rs-src', src); 666 node.setAttribute('data-rs-blocked', 'true'); 667 node.setAttribute('data-rs-category', category); 668 node.setAttribute('data-rs-pattern', domain); 669 node.removeAttribute('src'); 670 node.setAttribute('type', 'text/plain'); 671 node.blocked_src = src; 672 node.blocked_time = new Date().getTime(); 673 window.rs_blocked_scripts.push(node); 674 } 675 } else { 676 // Skip blocking for Yoast SEO schema.org structured data 677 var nodeClass = node.getAttribute('class') || ''; 678 var nodeType = node.getAttribute('type') || ''; 679 var isYoastSchema = nodeClass.indexOf('yo
679ast-schema-graph') !== -1 || 680 nodeType === 'application/ld+json'; 681 682 if (isYoastSchema) { 683 // Don't block Yoast schema - it's essential for SEO 684 return window.RSScriptBlocker.originalFunctions.insertBefore.call(this, node, referenceNode); 685 } 686 687 // Don't block our own event handlers script 688 var scriptId = node.getAttribute('id') || ''; 689 if (scriptId.indexOf('rs-contentpass') !== -1) { 690 return window.RSScriptBlocker.originalFunctions.insertBefore.call(this, node, referenceNode); 691 } 692 693 var scriptContent = node.textContent || node.innerText || ''; 694 var containsBlockedDomain = false; 695 var blockedDomain = null; 696 697 for (var i = 0; i < window.RSScriptBlocker.blockedDomains.length; i++) { 698 var domain = window.RSScriptBlocker.blockedDomains[i]; 699 if (scriptContent.indexOf(domain) !== -1) { 700 containsBlockedDomain = true; 701 blockedDomain = domain; 702 break; 703 } 704 } 705 706 var category = getDomainCategory(blockedDomain); 707 708 // Check if we should block based on consent and authentication 709 // For 'content' category, also check ContentPass authentication 710 var shouldBlock = !window.rs_consent_given && 711 !(category === 'content' && window.rs_cp_authenticated === true); 712 713 if (containsBlockedDomain && shouldBlock) { 714 715 window.RSScriptBlocker.blockedRequests.push({ 716 type: 'inline-script', 717 domain: blockedDomain, 718 category: category, 719 timestamp: new Date().getTime() 720 }); 721 722 node.setAttribute('data-rs-original-content', scriptContent); 723 node.setAttribute('data-rs-blocked', 'true'); 724 node.setAttribute('data-rs-category', category); 725 node.setAttribute('data-rs-pattern', blockedDomain); 726 node.setAttribute('type', 'text/plain'); 727 node.textContent = '/* Blocked inline script referencing ' + blockedDomain + ' */'; 728 node.blocked_content = scriptContent; 729 node.blocked_time = new Date().getTime(); 730 window.rs_blocked_scripts.push(node); 731 } 732 } 733 } 734 return window.RSScriptBlocker.originalFunctions.insertBefore.call(this, node, referenceNode); 735 }; 736 737 // Override XMLHttpRequest to block network requests to blocked domains 738 XMLHttpRequest.prototype.open = function() { 739 var args = Array.prototype.slice.call(arguments); 740 var method = args[0]; 741 var url = args[1]; 742 743 if (url) { 744 var domain = extractDomain(url); 745 if (domain && shouldBlockDomain(domain) && !window.rs_consent_given) { 746 var category = getDomainCategory(domain); 747 748 window.RSScriptBlocker.blockedRequests.push({ 749 type: 'xhr', 750 url: url, 751 method: method, 752 domain: domain, 753 category: category, 754 timestamp: new Date().getTime() 755 }); 756 args[1] = 'about:blank'; 757 this._blockedUrl = url; 758 this._blockedDomain = domain; 759 this._blockedCategory = category; 760 } 761 } 762 return window.RSScriptBlocker.originalFunctions.open.apply(this, args); 763 }; 764 765 var originalSend = XMLHttpRequest.prototype.send; 766 XMLHttpRequest.prototype.send = function() { 767 if (this._blockedUrl) { 768 var xhr = this; 769 var originalOnReadyStateChange = xhr.onreadystatechange; 770 var originalOnLoad = xhr.onload; 771 var originalOnError = xhr.onerror; 772 xhr.onreadystatechange = function() { 773 if (originalOnReadyStateChange) { 774 try { 775 originalOnReadyStateChange.apply(xhr, arguments); 776 } catch (e) { 777 console.error('[RS Script Blocker] Error in blocked XHR onreadystatechange:', e); 778 } 779 } 780 }; 781 782 xhr.onload = function() { 783 if (originalOnLoad) { 784 try { 785 originalOnLoad.apply(xhr, arguments); 786 } catch (e) { 787 console.error('[RS Script Blocker] Error in blocked XHR onload handler:', e); 788 } 789 } 790 }; 791 792 xhr.onerror = function() { 793 console.logError('XHR', 'Suppressed error for blocked XHR', { 794 url: xhr._blockedUrl || 'unknown' 795 }); 796 }; 797 798 setTimeout(function() { 799 Object.defineProperty(xhr, 'readyState', {get: function() { return 4; }}); 800 Object.defineProperty(xhr, 'status', {get: function() { return 200; }}); 801 Object.defineProperty(xhr, 'responseText', {get: function() { return '/* Blocked by RS Script Blocker */'; }}
801); 802 Object.defineProperty(xhr, 'responseXML', {get: function() { return null; }}); 803 804 if (xhr.onreadystatechange) xhr.onreadystatechange(); 805 if (xhr.onload) xhr.onload(); 806 }, 10); 807 return; 808 } 809 return originalSend.apply(this, arguments); 810 }; 811 812 // Override fetch to block network requests to blocked domains 813 window.fetch = function() { 814 var args = Array.prototype.slice.call(arguments); 815 var input = args[0]; 816 var options = args[1] || {}; 817 var url = (typeof input === 'string') ? input : (input && input.url); 818 var method = (options.method || (typeof input !== 'string' && input.method) || 'GET').toUpperCase(); 819 820 if (url) { 821 var domain = extractDomain(url); 822 if (domain && shouldBlockDomain(domain) && !window.rs_consent_given) { 823 var category = getDomainCategory(domain); 824 825 window.RSScriptBlocker.blockedRequests.push({ 826 type: 'fetch', 827 url: url, 828 method: method, 829 domain: domain, 830 category: category, 831 timestamp: new Date().getTime() 832 }); 833 var contentType = 'application/javascript'; 834 if (url.match(/\.(json|jsonp)($|\?)/i)) { 835 contentType = 'application/json'; 836 } else if (url.match(/\.(html|htm)($|\?)/i)) { 837 contentType = 'text/html'; 838 } else if (url.match(/\.(xml)($|\?)/i)) { 839 contentType = 'application/xml'; 840 } else if (url.match(/\.(jpg|jpeg|png|gif|webp|svg)($|\?)/i)) { 841 contentType = 'image/png'; 842 return Promise.resolve(new Response(new Blob(), { 843 status: 200, 844 headers: {'Content-Type': contentType} 845 })); 846 } 847 var responseBody = '/* Blocked by RS Script Blocker */'; 848 if (contentType === 'application/json') { 849 responseBody = '{"blocked":true,"message":"Content blocked by RS Script Blocker"}'; 850 } else if (contentType === 'text/html') { 851 responseBody = '<!-- Content blocked by RS Script Blocker -->'; 852 } else if (contentType === 'application/xml') { 853 responseBody = '<' + '?xml version="1.0" encoding="UTF-8"?' + '><blocked>Content blocked by RS Script Blocker</blocked>'; 854 } 855 return Promise.resolve(new Response(responseBody, { 856 status: 200, 857 headers: {'Content-Type': contentType} 858 })); 859 } 860 } 861 return window.RSScriptBlocker.originalFunctions.fetch.apply(window, args); 862 }; 863 864 // Override Image constructor to block tracking pixels 865 window.Image = function() { 866 var image = new window.RSScriptBlocker.originalFunctions.Image(); 867 var originalSetAttribute = image.setAttribute; 868 869 image.setAttribute = function(name, value) { 870 if (name.toLowerCase() === 'src') { 871 var domain = extractDomain(value); 872 if (domain && shouldBlockDomain(domain) && !window.rs_consent_given) { 873 var category = getDomainCategory(domain); 874 875 window.RSScriptBlocker.blockedRequests.push({ 876 type: 'image-setAttribute', 877 url: value, 878 domain: domain, 879 category: category, 880 timestamp: new Date().getTime() 881 }); 882 originalSetAttribute.call(this, 'data-rs-src', value); 883 originalSetAttribute.call(this, 'data-rs-blocked', 'true'); 884 originalSetAttribute.call(this, 'data-rs-category', category); 885 return; 886 } 887 } 888 return originalSetAttribute.apply(this, arguments); 889 }; 890 891 // Check the initial src if it exists 892 if (image.src) { 893 var initialSrc = image.src; 894 var domain = extractDomain(initialSrc); 895 896 if (domain && shouldBlockDomain(domain) && !window.rs_consent_given) { 897 var category = getDomainCategory(domain); 898 899 window.RSScriptBlocker.blockedRequests.push({ 900 type: 'image-initial', 901 url: initialSrc, 902 domain: domain, 903 category: category, 904 timestamp: new Date().getTime() 905 }); 906 907 image.setAttribute('data-rs-src', initialSrc); 908 image.setAttribute('data-rs-blocked', 'true'); 909 image.setAttribute('data-rs-category', category); 910 image.setAttribute('data-rs-pattern', domain); 911 image.removeAttribute('src'); 912 } 913 } 914 915 return image; 916 }; 917 918 // Set up MutationObserver to catch dynamically added scripts 919 var observer = new MutationObserver(function(mutations) { 920 mutations.forEach(function(mutation) {
921 // Process added nodes 922 if (mutation.addedNodes && mutation.addedNodes.length > 0) { 923 for (var i = 0; i < mutation.addedNodes.length; i++) { 924 var node = mutation.addedNodes[i]; 925 926 if (node.nodeName && node.nodeName.toLowerCase() === 'script') { 927 var src = node.getAttribute('src') || node.src; 928 if (src) { 929 var domain = extractDomain(src); 930 if (domain && shouldBlockDomain(domain) && !window.rs_consent_given) { 931 var category = getDomainCategory(domain); 932 933 window.RSScriptBlocker.blockedRequests.push({ 934 type: 'dynamic-script', 935 url: src, 936 domain: domain, 937 category: category, 938 timestamp: new Date().getTime() 939 }); 940 941 node.setAttribute('data-rs-src', src); 942 node.setAttribute('data-rs-blocked', 'true'); 943 node.setAttribute('data-rs-category', category); 944 node.setAttribute('data-rs-pattern', domain); 945 node.removeAttribute('src'); 946 node.setAttribute('type', 'text/plain'); 947 948 node.blocked_src = src; 949 node.blocked_time = new Date().getTime(); 950 window.rs_blocked_scripts.push(node); 951 } 952 } else { 953 // Skip blocking for Yoast SEO schema.org structured data 954 var nodeClass = node.getAttribute('class') || ''; 955 var nodeType = node.getAttribute('type') || ''; 956 var isYoastSchema = nodeClass.indexOf('yoast-schema-graph') !== -1 || 957 nodeType === 'application/ld+json'; 958 959 if (isYoastSchema) { 960 continue; 961 } 962 963 var scriptId = node.getAttribute('id') || ''; 964 if (scriptId.indexOf('rs-contentpass') !== -1) { 965 continue; 966 } 967 968 var scriptContent = node.textContent || node.innerText || ''; 969 var containsBlockedDomain = false; 970 var blockedDomain = null; 971 972 for (var j = 0; j < window.RSScriptBlocker.blockedDomains.length; j++) { 973 var domain = window.RSScriptBlocker.blockedDomains[j]; 974 if (scriptContent.indexOf(domain) !== -1) { 975 containsBlockedDomain = true; 976 blockedDomain = domain; 977 break; 978 } 979 } 980 981 var category = getDomainCategory(blockedDomain); 982 983 // Check if we should block based on consent and authentication 984 // For 'content' category, also check ContentPass authentication 985 var shouldBlock = !window.rs_consent_given && 986 !(category === 'content' && window.rs_cp_authenticated === true); 987 988 if (containsBlockedDomain && shouldBlock) { 989 var category = getDomainCategory(blockedDomain); 990 991 window.RSScriptBlocker.blockedRequests.push({ 992 type: 'dynamic-inline-script', 993 domain: blockedDomain, 994 category: category, 995 timestamp: new Date().getTime() 996 }); 997 998 // Store the original content in data attributes 999 node.setAttribute('data-rs-original-content', scriptContent); 1000 node.setAttribute('data-rs-blocked', 'true'); 1001 node.setAttribute('data-rs-category', category); 1002 node.setAttribute('data-rs-pattern', blockedDomain); 1003 node.setAttribute('type', 'text/plain'); 1004 1005 // Check if content appears to be JSON (starts with { or [) 1006 var trimmedContent = scriptContent.trim(); 1007 if ((trimmedContent.startsWith('{') && trimmedContent.endsWith('}')) || 1008 (trimmedContent.startsWith('[') && trimmedContent.endsWith(']'))) { 1009 // For JSON content, preserve structure but make it non-executable 1010 // by wrapping in a JavaScript comment that can be parsed as JSON 1011 node.textContent = trimmedContent; 1012 } else { 1013 // For regular scripts, use comment replacement 1014 node.textContent = '/* Blocked inline script referencing ' + blockedDomain + ' */'; 1015 } 1016 1017 // Add to blocked scripts array for c
1017ompatibility 1018 node.blocked_content = scriptContent; 1019 node.blocked_time = new Date().getTime(); 1020 window.rs_blocked_scripts.push(node); 1021 } 1022 } 1023 } 1024 // Check if the node is an iframe element 1025 else if (node.nodeName && node.nodeName.toLowerCase() === 'iframe') { 1026 // Check if it has a src attribute 1027 var src = node.getAttribute('src') || node.src; 1028 if (src) { 1029 var domain = extractDomain(src); 1030 if (domain && shouldBlockDomain(domain) && !window.rs_consent_given) { 1031 var category = getDomainCategory(domain); 1032 1033 window.RSScriptBlocker.blockedRequests.push({ 1034 type: 'iframe', 1035 url: src, 1036 domain: domain, 1037 category: category, 1038 timestamp: new Date().getTime() 1039 }); 1040 1041 // Store the original src in data attributes 1042 node.setAttribute('data-rs-src', src); 1043 node.setAttribute('data-rs-blocked', 'true'); 1044 node.setAttribute('data-rs-category', category); 1045 node.setAttribute('data-rs-pattern', domain); 1046 1047 // Get original dimensions if available 1048 var originalWidth = node.getAttribute('width') || node.style.width || '100%'; 1049 var originalHeight = node.getAttribute('height') || node.style.height || '150px'; 1050 1051 // Simply remove the src attribute to prevent loading 1052 node.removeAttribute('src'); 1053 1054 // Preserve original dimensions 1055 node.style.width = originalWidth; 1056 node.style.height = originalHeight; 1057 node.style.maxWidth = '100%'; 1058 1059 // Create a placeholder container 1060 var placeholderContainer = document.createElement('div'); 1061 placeholderContainer.style.display = 'flex'; 1062 placeholderContainer.style.flexDirection = 'column'; 1063 placeholderContainer.style.alignItems = 'center'; 1064 placeholderContainer.style.justifyContent = 'center'; 1065 placeholderContainer.style.backgroundColor = '#f8f8f8'; 1066 placeholderContainer.style.border = '1px dashed #ccc'; 1067 placeholderContainer.style.padding = '20px'; 1068 placeholderContainer.style.color = '#666'; 1069 placeholderContainer.style.fontFamily = 'sans-serif'; 1070 placeholderContainer.style.textAlign = 'center'; 1071 placeholderContainer.style.width = '100%'; 1072 placeholderContainer.style.height = '100%'; 1073 placeholderContainer.style.boxSizing = 'border-box'; 1074 1075 // Create a title for the blocked content 1076 var placeholderTitle = document.createElement('div'); 1077 placeholderTitle.style.fontWeight = 'bold'; 1078 placeholderTitle.style.marginBottom = '10px'; 1079 placeholderTitle.textContent = 'Content Blocked'; 1080 placeholderContainer.appendChild(placeholderTitle); 1081 1082 // Create a text node with the blocked message 1083 var placeholderText = document.createElement('div'); 1084 placeholderText.textContent = 'Content from ' + domain + ' is blocked until consent is given'; 1085 placeholderContainer.appendChild(placeholderText); 1086 1087 // Add a button to reload the page if consent is already given but page hasn't reloaded 1088 if (window.rs_consent_given) { 1089 var reloadButton = document.createElement('button'); 1090 reloadButton.textContent = 'Reload Page to View Content'; 1091 reloadButton.style.marginTop = '10px'; 1092 reloadButton.style.padding = '5px 10px'; 1093 reloadButton.style.backgroundColor = '#007bff'; 1094 reloadButton.style.color = 'white'; 1095 reloadButton.style.border = 'none'; 1096 reloadButton.style.borderRadius = '3px'; 1097 reloadButton.style.cursor = 'pointer'; 1098 /* reloadButton.onclick = function() { window.location.reload(); }; */ 1099 placeholderContainer.appendChild(reloadButton); 1100 } 1101 while (node.firstChild) { 1102 node.removeChild(node.firstChild); 1103 } 1104 node.appendChild(placeholderContainer); 1105 node.blocked_src = src; 1106 node.blocked_time = new Date().getTime(); 1107 window.rs_blocked_scripts.push(node); 1108 } 1109 } 1110 } 1111 // Check for image elements 1112 else if (node.nodeName && node.nodeName.toLowerCase() === 'img') { 1113 var src = node.getAttribute('src') || node.src; 1114 if (src) { 1115 var domain = extractDomain(src); 1116 if (domain && shouldBlockDomain(domain) && !window.rs_consent_given) { 1117 var category = getDomainCategory(domain); 1118 1119 window.RSScriptBlocker.blockedRequests.push({ 1120 type: 'img-element', 1121 url: src, 1122 domain: domain, 1123 category: category, 1124 timestamp: new Date().getTime() 1125 }); 1126 node.setAttribute('data-rs-src', src); 1127 node.setAttribute('data-rs-blocked', 'true'); 1128 node.setAttribute('data-rs-category', category); 1129 node.setAttribute('data-rs-pattern', domain); 1130 node.removeAttribute('src'); 1131 } 1132 } 1133 } 1134 else if (node.nodeName && node.nodeName.toLowerCase() === 'link') { 1135 var href = node.getAttribute('href'); 1136 if (href) { 1137 var domain = extractDomain(href); 1138 if (domain && shouldBlockDomain(domain) && !window.rs_consent_given) { 1139 var category = getDomainCategory(domain); 1140 1141 window.RSScriptBlocker.blockedRequests.push({ 1142 type: 'link', 1143 url: href, 1144 domain: domain, 1145 category: category, 1146 timestamp: new Date().getTime() 1147 }); 1148 node.setAttribute('data-rs-href', href); 1149 node.setAttribute('data-rs-blocked', 'true'); 1150 node.setAttribute('data-rs-category', category); 1151 node.setAttribute('data-rs-pattern', domain); 1152 node.removeAttribute('href'); 1153 } 1154 } 1155 } 1156 } 1157 } 1158 }); 1159 }); 1160 1161 // Fetch API override 1162 var originalFetch = window.fetch; 1163 window.fetch = function(resource, options) { 1164 var url = (typeof resource === 'string') ? resource : resource.url; 1165 1166 // Use the existing domain checking functions instead of undefined isBlocked 1167 var domain = extractDomain(url); 1168 var shouldBlock = domain && shouldBlockDomain(domain) && !window.rs_consent_given; 1169 var matchedPattern = shouldBlock ? domain : null; 1170 1171 if (shouldBlock) { 1172 return new Promise(function(resolve) { 1173 resolve(new Response('', { 1174 status: 200, 1175 headers: { 'Content-Type': 'text/plain' } 1176 })); 1177 }); 1178 } 1179 1180 return originalFetch.apply(this, arguments); 1181 }; 1182 1183 observer.observe(document, { 1184 childList: true, 1185 subtree: true 1186 }); 1187 1188 })(); 1189 </script>
1189 1190 <meta name='robots' content='index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1' /> 1191
1191<script> 1192 // Block Tealium's consent-based reload 1193 (function() { 1194 // Wait for Tealium to load 1195 const checkTealium = setInterval(function() { 1196 if (window.utag && window.utag.gdpr) { 1197 clearInterval(checkTealium); 1198 1199 // Override Tealium's GDPR consent handler 1200 if (window.utag.gdpr.trackConsentChanges) { 1201 const original = window.utag.gdpr.trackConsentChanges; 1202 window.utag.gdpr.trackConsentChanges = function() { 1203 console.log('[RS] Blocked Tealium consent reload'); 1204 // Call original without allowing reload 1205 return; 1206 }; 1207 } 1208 1209 // Also override any reload methods Tealium might use 1210 if (window.utag.gdpr.doConsentRedirect) { 1211 window.utag.gdpr.doConsentRedirect = function() { 1212 console.log('[RS] Blocked Tealium consent redirect'); 1213 return false; 1214 }; 1215 } 1216 } 1217 }, 10); 1218 1219 // Failsafe: timeout after 5 seconds 1220 setTimeout(() => clearInterval(checkTealium), 5000); 1221 })(); 1222 </script>
1222 1223
1223<script type="text/javascript" id="contentpass-tealium-controller"> 1224 window.tealiumContentPassController = { 1225 authenticationComplete: false, 1226 isContentPassSubscriber: false, 1227 shouldLoadTealium: false, 1228 tealiumInitialized: false, 1229 1230 // Handle ContentPass authentication result 1231 handleAuthentication: function(isSubscriber) { 1232 1233 if (!this.authenticationComplete) { 1234 this.authenticationComplete = true; 1235 this.isContentPassSubscriber = isSubscriber; 1236 this.shouldLoadTealium = !isSubscriber; 1237 1238 if (this.shouldLoadTealium && !this.tealiumInitialized) { 1239 this.initializeTealium(); 1240 } else if (this.isContentPassSubscriber) { 1241 console.log('[CP-Tealium] User is a ContentPass subscriber, Tealium will not load'); 1242 } 1243 } 1244 }, 1245 1246 // Initialize Tealium by triggering the complete WordPress plugin flow 1247 initializeTealium: function() { 1248 if (this.tealiumInitialized) { 1249 return; 1250 } 1251 1252 this.tealiumInitialized = true; 1253 1254 // Trigger the server-side Tealium initialization 1255 // This will cause insertTealiumTag() and tealiumEncodedDataObject() to run 1256 var xhr = new XMLHttpRequest(); 1257 xhr.open('POST', 'https://www.rollingstone.de/wp-admin/admin-ajax.php', true); 1258 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); 1259 xhr.onreadystatechange = function() { 1260 if (xhr.readyState === 4) { 1261 if (xhr.status === 200) { 1262 try { 1263 var response = JSON.parse(xhr.responseText); 1264 if (response.success && response.data) { 1265 1266 // Inject the utag_data object first 1267 if (response.data.utag_data) { 1268 var dataScript = document.createElement('script'); 1269 dataScript.type = 'text/javascript'; 1270 dataScript.text = response.data.utag_data; 1271 document.head.appendChild(dataScript); 1272 } 1273 1274 // Then inject the Tealium tag 1275 if (response.data.tealium_tag) { 1276 var tempDiv = document.createElement('div'); 1277 tempDiv.innerHTML = response.data.tealium_tag; 1278 1279 // Find and execute any script elements 1280 var scripts = tempDiv.querySelectorAll('script'); 1281 1282 for (var i = 0; i < scripts.length; i++) { 1283 var script = scripts[i]; 1284 var newScript = document.createElement('script'); 1285 newScript.type = 'text/javascript'; 1286 1287 if (script.src) { 1288 newScript.src = script.src; 1289 newScript.async = script.async; 1290 } else if (script.innerHTML || script.textContent) { 1291 newScript.text = script.innerHTML || script.textContent; 1292 } 1293 document.head.appendChild(newScript); 1294 } 1295 } 1296 } else { 1297 console.error('[CP-Tealium] Server response error:', response); 1298 } 1299 } catch (e) { 1300 console.error('[CP-Tealium] Error parsing server response:', e, xhr.responseText); 1301 } 1302 } else { 1303 console.error('[CP-Tealium] Server request failed:', xhr.status, xhr.statusText); 1304 } 1305 } 1306 }; 1307 1308 xhr.send('action=rs_contentpass_init_tealium&nonce=b14dd8bd6b'); 1309 } 1310 }; 1311 1312 // Check if this is a page refresh and reset state 1313 if (performance.navigation && performance.navigation.type === performance.navigation.TYPE_RELOAD) { 1314 window.tealiumContentPassController.tealiumInitialized = false;
1315 window.tealiumContentPassController.authenticationComplete = false; 1316 } else if (performance.getEntriesByType && performance.getEntriesByType('navigation').length > 0) { 1317 var navEntry = performance.getEntriesByType('navigation')[0]; 1318 if (navEntry.type === 'reload') { 1319 window.tealiumContentPassController.tealiumInitialized = false; 1320 window.tealiumContentPassController.authenticationComplete = false; 1321 } 1322 } 1323 </script>
1323 1324 <link rel="preload" href="https://www.rollingstone.de/wp-content/themes/RS-Theme-2023/fonts/PublicoHeadline-Bold-Web.woff2" as="font" type="font/woff2" crossorigin> 1325<link rel="preload" href="https://www.rollingstone.de/wp-content/themes/RS-Theme-2023/fonts/Graphik-Semibold-Web.woff2" as="font" type="font/woff2" crossorigin> 1326 1327 <!-- This site is optimized with the Yoast SEO Premium plugin v25.9 (Yoast SEO v28.3) - https://yoast.com/product/yoast-seo-premium-wordpress/ --> 1328 <title>Rolling Stone Audio â¶ï¸ 1</title> 1329 <meta name="description" content="â¶ï¸ Jetzt reinhören: Die neusten Podcasts und Playlists vom Rolling Stone Deutschland. 1" /> 1330 <link rel="canonical" href="https://www.rollingstone.de/audio-post/second-song-von-neil-young-ein-spaetes-meisterwerk/" /> 1331 <meta property="og:locale" content="de_DE" /> 1332 <meta property="og:type" content="article" /> 1333 <meta property="og:title" content="Rolling Stone Audio â¶ï¸ âSecond Songâ von Neil Young: Ein spätes Meisterwerk?" /> 1334 <meta property="og:description" content="â¶ï¸ Jetzt reinhören: Die neusten Podcasts und Playlists vom Rolling Stone Deutschland." /> 1335 <meta property="og:url" content="https://www.rollingstone.de/audio-post/second-song-von-neil-young-ein-spaetes-meisterwerk/" /> 1336 <meta property="og:site_name" content="Rolling Stone" /> 1337 <meta property="article:publisher" content="https://www.facebook.com/rollingstonemagazin" /> 1338 <meta property="og:image" content="https://www.rollingstone.de/wp-content/uploads/2025/06/neil-young-gettyimages-2222655563-scaled-e1751274795954.webp" /> 1339 <meta property="og:image:width" content="2363" /> 1340 <meta property="og:image:height" content="1433" /> 1341 <meta property="og:image:type" content="image/webp" /> 1342 <meta name="twitter:card" content="summary_large_image" /> 1343 <meta name="twitter:site" content="@rollingstonede" /> 1344 <meta name="twitter:label1" content="Est. reading time" /> 1345 <meta name="twitter:data1" content="1 Minute" /> 1346
1346<script type="application/ld+json" class="yoast-schema-graph">{"@context":"https://schema.org","@graph":[{"@type":"Article","@id":"https://www.rollingstone.de/audio-post/second-song-von-neil-young-ein-spaetes-meisterwerk/#article","isPartOf":{"@id":"https://www.rollingstone.de/audio-post/second-song-von-neil-young-ein-spaetes-meisterwerk/"},"author":{"name":"Jan Jekal","@id":"https://www.rollingstone.de/#/schema/person/5e0362b2a9b306e0949ec0cc5a34342a"},"headline":"âSecond Songâ von Neil Young: Ein spätes Meisterwerk?","datePublished":"2026-09-25T06:32:43+02:00","mainEntityOfPage":{"@id":"https://www.rollingstone.de/audio-post/second-song-von-neil-young-ein-spaetes-meisterwerk/"},"wordCount":67,"publisher":{"@id":"https://www.rollingstone.de/#organization"},"image":{"@id":"https://www.rollingstone.de/audio-post/second-song-von-neil-young-ein-spaetes-meisterwerk/#primaryimage"},"thumbnailUrl":"https://www.rollingstone.de/wp-content/uploads/2025/06/neil-young-gettyimages-2222655563-scaled-e1751274795954.webp","keywords":["Neil Young","Neil Young and the Chrome Hearts","Chrome Hearts","Second Song"],"articleSection":["Musik","News"],"inLanguage":"de-DE","copyrightYear":"2026","copyrightHolder":{"@id":"https://www.rollingstone.de/#organization"}},{"@type":"WebPage","@id":"https://www.rollingstone.de/audio-post/second-song-von-neil-young-ein-spaetes-meisterwerk/","url":"https://www.rollingstone.de/audio-post/second-song-von-neil-young-ein-spaetes-meisterwerk/","name":"Rolling Stone Audio â¶ï¸ 1","isPartOf":{"@id":"https://www.rollingstone.de/#website"},"primaryImageOfPage":{"@id":"https://www.rollingstone.de/audio-post/second-song-von-neil-young-ein-spaetes-meisterwerk/#primaryimage"},"image":{"@id":"https://www.rollingstone.de/audio-post/second-song-von-neil-young-ein-spaetes-meisterwerk/#primaryimage"},"thumbnailUrl":"https://www.rollingstone.de/wp-content/uploads/2025/06/neil-young-gettyimages-2222655563-scaled-e1751274795954.webp","datePublished":"2026-09-25T06:32:43+02:00","description":"â¶ï¸ Jetzt reinhören: Die neusten Podcasts und Playlists vom Rolling Stone Deutschland. 1","breadcrumb":{"@id":"https://www.rollingstone.de/audio-post/second-song-von-neil-young-ein-spaetes-meisterwerk/#breadcrumb"},"inLanguage":"de-DE","potentialAction":[{"@type":"ReadAction","target":["https://www.rollingstone.de/audio-post/second-song-von-neil-young-ein-spaetes-meisterwerk/"]}]},{"@type":"ImageObject","inLanguage":"de-DE","@id":"https://www.rollingstone.de/audio-post/second-song-von-neil-young-ein-spaetes-meisterwerk/#primaryimage","url":"https://www.rollingstone.de/wp-content/uploads/2025/06/neil-young-gettyimages-2222655563-scaled-e1751274795954.webp","contentUrl":"https://www.rollingstone.de/wp-content/uploads/2025/06/neil-young-gettyimages-2222655563-scaled-e1751274795954.webp","width":2363,"height":1433,"caption":"Neil Young Live 2025"},{"@type":"BreadcrumbList","@id":"https://www.rollingstone.de/audio-post/second-song-von-neil-young-ein-spaetes-meisterwerk/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Startseite","item":"https://www.rollingstone.de/"},{"@type":"ListItem","position":2,"name":"Audio","item":"https://www.rollingstone.de/audio-post/"},{"@type":"ListItem","position":3,"name":"Musik","item":"https://www.rollingstone.de/musik/"},{"@type":"ListItem","position":4,"name":"âSecond Songâ von Neil Young: Ein spätes Meisterwerk?"}]},{"@type":"WebSite","@id":"https://www.rollingstone.de/#website","url":"https://www.rollingstone.de/","name":"Rolling Stone","description":"Das Musikmagazin: News, Live, Videos, Reviews","publisher":{"@id":"https://www.rollingstone.de/#organization"},"alternateName":"rollingstone","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://www.rollingstone.de/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de-DE"},{"@type":["Organization","Place"],"@id":"https://www.rollingstone.de/#organization","name":"Mediahouse Berlin GmbH","alternateName":"rollingstone","url":"https://www.rollingstone.de/","logo":{"@id":"https://www.rollingstone.de/audio-post/second-song-von-neil-young-ein-spaetes-meisterwerk/#local-main-organization-logo"},"image":{"@id":"https://www.rollingstone.de/audio-post/second-song-von-neil-young-ein-spaetes-meisterwerk/#local-main-organization-logo"},"sameAs":["https://www.facebook.com/rollingstonemagazin","https://x.com/rollingstonede","https://www.instagram.com/rollingstone_de/?hl=de","https://www.youtube.com/@rollingstoneonline","https://www.linkedin.com/company/rollingstonede/"],"address":{"@id":"https://www.rollingstone.de/audio-post/second-song-von-neil-young-ein-spaetes-meisterwerk/#local-main-place-address"},"geo":{"@type":"GeoCoordinates","latitude":"52.4933809","longitude":"13.3888653"},"telephone":[],"openingHoursSpecification":[{"@type":"OpeningHoursSpecification","dayOfWeek":["Monday","Tuesday","Wednesday","Thursday","Frid
1346ay","Saturday","Sunday"],"opens":"09:00","closes":"17:00"}]},{"@type":"Person","@id":"https://www.rollingstone.de/#/schema/person/5e0362b2a9b306e0949ec0cc5a34342a","name":"Jan Jekal","image":{"@type":"ImageObject","inLanguage":"de-DE","@id":"https://www.rollingstone.de/wp-content/uploads/2021/11/17/15/jan-jekal-104x104.jpg","url":"https://www.rollingstone.de/wp-content/uploads/2021/11/17/15/jan-jekal-104x104.jpg","contentUrl":"https://www.rollingstone.de/wp-content/uploads/2021/11/17/15/jan-jekal-104x104.jpg","caption":"Jan Jekal"},"url":"https://www.rollingstone.de/author/jan-jekal/"},{"@type":"PostalAddress","@id":"https://www.rollingstone.de/audio-post/second-song-von-neil-young-ein-spaetes-meisterwerk/#local-main-place-address","streetAddress":"Mediahouse Berlin GmbH","addressLocality":"Berlin","postalCode":"10961","addressRegion":"Germany","addressCountry":"DE"},{"@type":"ImageObject","inLanguage":"de-DE","@id":"https://www.rollingstone.de/audio-post/second-song-von-neil-young-ein-spaetes-meisterwerk/#local-main-organization-logo","url":"https://www.rollingstone.de/wp-content/uploads/2023/11/cropped-favicon-rs-2023.png","contentUrl":"https://www.rollingstone.de/wp-content/uploads/2023/11/cropped-favicon-rs-2023.png","width":512,"height":512,"caption":"Mediahouse Berlin GmbH"}]}</script>
1346 1347 <meta name="geo.placename" content="Berlin" /> 1348 <meta name="geo.position" content="52.4933809;13.3888653" /> 1349 <meta name="geo.region" content="Germany" /> 1350 <!-- / Yoast SEO Premium plugin. --> 1351 1352 1353 <meta name="referrer" content="origin-when-cross-origin" /> 1354
1354<script> 1355 window.IQDTracker = { 1356 loadedAds: new Set(), 1357 allPlacements: new Set(), 1358 viewportAds: new Set(), 1359 nonViewportAds: new Set(), 1360 adPositions: { 1361 visible: null, 1362 belowFold: null 1363 }, 1364 dynamicAdStats: { 1365 numberOfParagraphs: 0, 1366 placedAds: [], 1367 deviceType: '' 1368 }, 1369 contentLoaded: false, 1370 debugMode: false, 1371 cmsConfig: null, 1372 logQueue: [], 1373 maxQueueSize: 20, 1374 loggingEndpoint: '/wp-admin/admin-ajax.php', 1375 pageVisitEvents: [], 1376 pageUrl: window.location.href, 1377 referrerUrl: document.referrer, 1378 hasLoggedPageVisit: false, 1379 viewportEntryTimestamps: {}, 1380 viewportExitTimestamps: {}, 1381 viewportDwellTime: {}, 1382 userInteractions: [], 1383 adPerformance: {}, 1384 logType: null, 1385 initialLogSent: false, 1386 eventLogQueue: [], 1387 isExiting: false, 1388 pageVisitId: null, 1389 eventCounter: 0, 1390 1391 initializeTracking: function() { 1392 this.viewportDwellTime = {}; 1393 this.viewportEntryTimestamps = {}; 1394 this.viewportExitTimestamps = {}; 1395 this.pageLoadTimestamp = new Date().toISOString(); 1396 this._initialViewportAds = null; 1397 this.trackingStartTime = new Date().toISOString(); 1398 this.maxScrollPosition = 0; 1399 this.viewabilityTimers = {}; 1400 1401 this.allPlacements = new Set(); 1402 this.viewportAds = new Set(); 1403 this.nonViewportAds = new Set(); 1404 this.adPerformance = {}; 1405 this.userInteractions = []; 1406 this.pageVisitEvents = []; 1407 this.dynamicAdStats = { 1408 numberOfParagraphs: 0, 1409 placedAds: [], 1410 deviceType: '' 1411 }; 1412 window.addEventListener('scroll', () => { 1413 this.maxScrollPosition = Math.max(this.maxScrollPosition, window.scrollY); 1414 }); 1415 1416 this.setupUnloadHandler(); 1417 this.setupEnhancedViewportTracking(); 1418 this.monitorCreativeChanges(); 1419 this.trackAdPopulation(); 1420 this.setupInactivityBackup(); 1421 this.captureInitialViewportState(); 1422 this.initConsoleListener(); 1423 }, 1424 1425 generateEventId: function() { 1426 this.eventCounter++; 1427 return `evt_${Date.now()}_${this.eventCounter}`; 1428 }, 1429 1430 getPageVisitId: function() { 1431 if (!this.pageVisitId) { 1432 this.pageVisitId = `pv_${Date.now()}_${Math.random().toString(36).substring(2, 10)}`; 1433 } 1434 return this.pageVisitId; 1435 }, 1436 1437 initializePlacements: function() { 1438 document.querySelectorAll('.iqdcontainer').forEach(container => { 1439 const placement = container.dataset.placement; 1440 this.allPlacements.add(placement); 1441 }); 1442 }, 1443 1444 logCmsConfig: function(config) { 1445 this.cmsConfig = this.sanitizeData(config); 1446 this.log('CMS_CONFIG', 'CMS configuration loaded', { 1447 config: this.cmsConfig, 1448 timestamp: new Date().toISOString() 1449 }); 1450 }, 1451 1452 1453 collectAllAdContainers: function() { 1454 const containers = document.querySelectorAll('.iqdcontainer'); 1455 const result = []; 1456 const browserInfo = this.getBrowserInfo(); 1457 const currentDeviceType = browserInfo.deviceType; 1458
1459 containers.forEach(container => { 1460 const placement = container.dataset.placement; 1461 const containerDeviceType = container.dataset.device; 1462 if (containerDeviceType && containerDeviceType !== currentDeviceType) { 1463 return; 1464 } 1465 const rect = container.getBoundingClientRect(); 1466 const isInViewport = ( 1467 rect.top >= 0 && 1468 rect.left >= 0 && 1469 rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && 1470 rect.right <= (window.innerWidth || document.documentElement.clientWidth) 1471 ); 1472 if (isInViewport) { 1473 this.viewportAds.add(placement); 1474 } else { 1475 this.nonViewportAds.add(placement); 1476 } 1477 1478 if (placement === 'pos_1') { 1479 const pos1Tiles = container.querySelectorAll('#iqadtile20, #iqadtile21, #iqadtile1'); 1480 1481 if (pos1Tiles.length > 0) { 1482 pos1Tiles.forEach(tileElement => { 1483 const tileId = tileElement.id; 1484 const trackingId = this.pos1TileMapping[tileId]; 1485 1486 if (trackingId) { 1487 const performanceData = this.adPerformance[trackingId] || {}; 1488 const tileRect = tileElement.getBoundingClientRect(); 1489 const isTileInViewport = ( 1490 tileRect.top >= 0 && 1491 tileRect.left >= 0 && 1492 tileRect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && 1493 tileRect.right <= (window.innerWidth || document.documentElement.clientWidth) 1494 ); 1495 1496 result.push({ 1497 id: trackingId, 1498 parent_placement: placement, 1499 tile_id: tileId, 1500 device: containerDeviceType || currentDeviceType, 1501 viewport_init: !!performanceData.viewport_init, 1502 viewport_registration: !!performanceData.viewport_registration, 1503 is_dynamic: this.isDynamicPlacement(trackingId), 1504 ad_requested: performanceData.ad_requested || false, 1505 ad_delivered: performanceData.delivered || this.isAdDelivered(tileElement) || false, 1506 ad_clicked: performanceData.clicked || false, 1507 time_in_viewport: this.viewportDwellTime[trackingId] || 0, 1508 request_time: performanceData.request_time || null, 1509 load_time: performanceData.load_time || null, 1510 position: { 1511 top: Math.round(tileRect.top + window.scrollY), 1512 left: Math.round(tileRect.left + window.scrollX) 1513 }, 1514 in_viewport: isTileInViewport, 1515 viewability_periods: performanceData.viewability_periods || [] 1516 }); 1517 } 1518 }); 1519 } 1520 } 1521 1522 const performanceData = this.adPerformance[placement] || {}; 1523 1524 result.push({ 1525 id: placement, 1526 tile_id: container.querySelector('[id]')?.id || null, 1527 device: containerDeviceType || currentDeviceType, 1528 /* initially_in_viewport: this._initialViewportAds?.includes(placement) || false, */ 1529 viewport_init: !!performanceData.viewport_init, 1530 viewport_registration: !!performanceData.viewport_registration, 1531 is_dynamic: this.isDynamicPlacement(placement), 1532 ad_requested: performanceData.ad_requested || false, 1533 ad_delivered: performanceData.delivered || this.isAdDelivered(container) || false, 1534 ad_clicked: performanceData.clicked || false, 1535 time_in_viewport: this.viewportDwellTime[placement] || 0, 1536 request_time: performanceData.request_time || null, 1537 load_time: performanceData.load_time || null, 1538 position: { 1539 top: Math.round(rect.top + window.scrollY), 1540 left: Math.round(rect.left + window.scrollX) 1541 }, 1542 in_viewport: isInViewport, 1543 viewability_periods: performanceData.viewability_periods || [] 1544 }); 1545 }); 1546 1547 return result; 1548 }, 1549 1550 isAdDelivered: function(container) { 1551 if (!container) return false;
1552 1553 if (container.classList.contains('iqdad')) { 1554 return true; 1555 } 1556 1557 const directChildren = container.children; 1558 for (let i = 0; i < directChildren.length; i++) { 1559 if (directChildren[i].classList.contains('iqdad')) { 1560 return true; 1561 } 1562 } 1563 1564 const tileElements = container.querySelectorAll('[id^="iqadtile"]'); 1565 for (let i = 0; i < tileElements.length; i++) { 1566 if (tileElements[i].classList.contains('iqdad')) { 1567 return true; 1568 } 1569 } 1570 1571 return false; 1572 }, 1573 1574 calculateViewability: function(placement) { 1575 if (!this.viewportDwellTime[placement]) return 0; 1576 const pageLoadTime = this.getPageLoadTime(); 1577 const totalTimeOnPage = new Date() - pageLoadTime; 1578 if (totalTimeOnPage <= 0) return 0; 1579 1580 return Math.min(100, Math.round((this.viewportDwellTime[placement] / totalTimeOnPage) * 100)); 1581 }, 1582 1583 getPageLoadTime: function() { 1584 return this.pageLoadTimestamp || this.trackingStartTime; 1585 }, 1586 1587 isDynamicPlacement: function(placement) { 1588 if (!this.dynamicAdStats || !this.dynamicAdStats.placedAds) return false; 1589 1590 return this.dynamicAdStats.placedAds.some(ad => ad.placement === placement); 1591 }, 1592 1593 log: function(type, message, data = null) { 1594 const eventId = this.generateEventId(); 1595 const pageVisitId = this.getPageVisitId(); 1596 const cleanData = this.sanitizeData({ 1597 message: message, 1598 ...(data || {}), 1599 userAgent: navigator.userAgent, 1600 viewport: { 1601 width: window.innerWidth, 1602 height: window.innerHeight 1603 } 1604 }); 1605 1606 const placementValue = data && data.placement ? data.placement : null; 1607 const event = { 1608 event_id: eventId, 1609 page_visit_id: pageVisitId, 1610 event_type: type, 1611 timestamp: new Date().toISOString(), 1612 data: cleanData 1613 }; 1614 1615 if (placementValue) { 1616 event.placement = placementValue; 1617 } 1618 1619 this.pageVisitEvents.push(event); 1620 return eventId; 1621 1622 }, 1623 1624 captureInitialViewportState: function() { 1625 this.viewportAds = new Set(); 1626 this.nonViewportAds = new Set(); 1627 this._initialViewportAds = []; 1628 const containers = document.querySelectorAll('.iqdcontainer'); 1629 containers.forEach(container => { 1630 const placement = container.dataset.placement; 1631 this.allPlacements.add(placement); 1632 const rect = container.getBoundingClientRect(); 1633 const isInViewport = ( 1634 rect.top >= 0 && 1635 rect.left >= 0 && 1636 rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && 1637 rect.right <= (window.innerWidth || document.documentElement.clientWidth) 1638 ); 1639 1640 if (isInViewport) { 1641 this.viewportAds.add(placement); 1642 } else { 1643 this.nonViewportAds.add(placement); 1644 } 1645 }); 1646 this._initialViewportAds = Array.from(this.viewportAds); 1647 1648 return this._initialViewportAds; 1649 }, 1650 1651 monitorCreativeChanges: function() { 1652 // Create a MutationObserver to track content changes in ad containers 1653 const creativeObserver = new MutationObserver((mutations) => { 1654 mutations.forEach(mutation => { 1655 if (mutation.type === 'childList' || mutation.type === 'attributes') { 1656 const container = mutation.target.closest('.iqdcontainer'); 1657 if (!container) return; 1658 1659 const placement = container.dataset.placement; 1660 if (!placement) return; 1661 1662 // Check if this mutation represents a creative being added 1663 const hasNewCreative = this.checkForNewCreative(mutation, container); 1664 1665 if (hasNewCreative) { 1666 // Creative has been added or significantly changed 1667 this.captureCreativeInfo(container, placement); 1668 } 1669 } 1670 }); 1671 }); 1672 1673 // Start observing all ad containers 1674 document.querySelectorAll('.iqdcontainer').forEach(container => { 1675 creativeObserver.observe(container, { 1676 childList: true, 1677 subtree: true, 1678 attributes: true, 1679 attributeFilter: ['src', 'style', 'data-google-query-id', 'data-asm-pushed'] 1680 }); 1681 }); 1682
1683 // Also setup a periodic check for containers added later 1684 setInterval(() => { 1685 document.querySelectorAll('.iqdcontainer').forEach(container => { 1686 if (!container.dataset.observed) { 1687 container.dataset.observed = 'true'; 1688 creativeObserver.observe(container, { 1689 childList: true, 1690 subtree: true, 1691 attributes: true, 1692 attributeFilter: ['src', 'style', 'data-google-query-id', 'data-asm-pushed'] 1693 }); 1694 1695 // Check if it already has content 1696 const placement = container.dataset.placement; 1697 this.captureCreativeInfo(container, placement); 1698 } 1699 }); 1700 }, 2000); 1701 }, 1702 1703 checkForNewCreative: function(mutation, container) { 1704 // Check if container class was updated to indicate ad status 1705 if (container.classList.contains('iqdad') && !container.dataset.adClassDetected) { 1706 container.dataset.adClassDetected = 'true'; 1707 return true; 1708 } 1709 1710 if (container.classList.contains('iqdnoad') && !container.dataset.noAdClassDetected) { 1711 container.dataset.noAdClassDetected = 'true'; 1712 return true; 1713 } 1714 1715 return false; 1716 }, 1717 1718 captureCreativeInfo: function(container, placement) { 1719 if (!container || !placement) return; 1720 1721 setTimeout(() => { 1722 if (placement === 'pos_1') { 1723 // Find all pos_1 tiles within this container 1724 const pos1Tiles = container.querySelectorAll('#iqadtile20, #iqadtile21, #iqadtile1'); 1725 1726 // If we found any of the special tiles, process them individually 1727 if (pos1Tiles.length > 0) { 1728 pos1Tiles.forEach(tileElement => { 1729 const tileId = tileElement.id; 1730 const trackingId = this.pos1TileMapping[tileId]; 1731 1732 if (trackingId) { 1733 const isFilled = this.isAdDelivered(tileElement); 1734 const isEmptyByClass = tileElement.classList.contains('iqdnoad'); 1735 1736 if (isFilled || isEmptyByClass) { 1737 if (!this.adPerformance[trackingId]) { 1738 this.adPerformance[trackingId] = { 1739 viewport_init: false, 1740 viewport_registration: false, 1741 ad_requested: false, 1742 delivered: false, 1743 clicked: false, 1744 time_in_viewport: 0, 1745 request_count: 0, 1746 fill_count: 0, 1747 viewability_periods: [], 1748 placement_id: placement, 1749 tile_id: tileId 1750 }; 1751 } 1752 1753 if (isFilled && !this.adPerformance[trackingId].fill_verified) { 1754 this.adPerformance[trackingId].fill_count = (this.adPerformance[trackingId].fill_count || 0) + 1; 1755 this.adPerformance[trackingId].fill_verified = true; 1756 this.adPerformance[trackingId].delivered = true; 1757 this.adPerformance[trackingId].load_time = new Date().toISOString(); 1758 } else if (isEmptyByClass && !this.adPerformance[trackingId].unfill_verified) { 1759 this.adPerformance[trackingId].unfill_verified = true; 1760 this.adPerformance[trackingId].delivered = false;
1761 } 1762 1763 this.adPerformance[trackingId].fillStatus = isFilled ? 'filled' : 'unfilled'; 1764 this.adPerformance[trackingId].fill_verification_source = 'dom'; 1765 1766 const eventData = { 1767 event_type: 'CREATIVE_RENDER', 1768 placement: trackingId, 1769 parent_placement: placement, 1770 tile_id: tileId, 1771 is_delivered: isFilled, 1772 timestamp: new Date().toISOString() 1773 }; 1774 1775 this.sendLogs('event', eventData); 1776 } 1777 } 1778 }); 1779 } 1780 } 1781 const isFilled = this.isAdDelivered(container); 1782 const isEmptyByClass = container.classList.contains('iqdnoad'); 1783 1784 if (isFilled || isEmptyByClass) { 1785 if (!this.adPerformance[placement]) { 1786 this.adPerformance[placement] = { 1787 viewport_init: false, 1788 viewport_registration: false, 1789 ad_requested: false, 1790 delivered: false, 1791 clicked: false, 1792 time_in_viewport: 0, 1793 request_count: 0, 1794 fill_count: 0, 1795 viewability_periods: [] 1796 }; 1797 } 1798 1799 if (isFilled && !this.adPerformance[placement].fill_verified) { 1800 this.adPerformance[placement].fill_count = (this.adPerformance[placement].fill_count || 0) + 1; 1801 this.adPerformance[placement].fill_verified = true; 1802 this.adPerformance[placement].delivered = true; 1803 this.adPerformance[placement].load_time = new Date().toISOString(); 1804 } else if (isEmptyByClass && !this.adPerformance[placement].unfill_verified) { 1805 this.adPerformance[placement].unfill_verified = true; 1806 this.adPerformance[placement].delivered = false; 1807 } 1808 1809 this.adPerformance[placement].fillStatus = isFilled ? 'filled' : 'unfilled'; 1810 this.adPerformance[placement].fill_verification_source = 'dom'; 1811 1812 const eventData = { 1813 event_type: 'CREATIVE_RENDER', 1814 placement: placement, 1815 is_delivered: isFilled, 1816 timestamp: new Date().toISOString() 1817 }; 1818 1819 this.sendLogs('event', eventData); 1820 } 1821 }, 100); 1822 }, 1823 1824 trackAdPopulation: function() { 1825 const tracker = this; // Store reference to IQDTracker 1826 1827 // Create a mapping for pos_1 tile IDs 1828 this.pos1TileMapping = { 1829 'iqadtile20': 'pos_1_tile20', 1830 'iqadtile21': 'pos_1_tile21', 1831 'iqadtile1': 'pos_1_tile1' 1832 }; 1833 1834 window.addEventListener('message', (event) => { 1835 if (typeof event.data === 'string' && event.data.startsWith('iq_set_tile_')) { 1836 const tileId = event.data.replace('iq_set_tile_', ''); 1837 const processedTiles = new Set(); 1838 1839 document.querySelectorAll('.iqdcontainer').forEach(container => { 1840 const tile = container.querySelector(`#${tileId}`); 1841 if (tile) { 1842 const adContainer = tile.closest('.iqdcontainer'); 1843 if (adContainer) { 1844 const placementId = adContainer.dataset.placement; 1845 1846 // Only process each tile once 1847 if (tileId && !processedTiles.has(tileId)) { 1848 processedTiles.add(tileId); 1849 1850 // Check if this is one of the pos_1 special tiles 1851 let trackingId = tileId; 1852 if (placementId === 'pos_1' && this.pos1TileMapping[tileId]) { 1853 trackingId = this.pos1TileMapping[tileId]; 1854 } 1855 1856 // Use the tile ID or special tracking ID as the key for tracking 1857 if (!tracker.adPerformance[trackingId]) { 1858 tracker.adPerformance[trackingId] = { 1859 viewport_init: false, 1860 viewport_registration: false, 1861 ad_requested: false, 1862 delivered: false, 1863 clicked: fal
1863se, 1864 time_in_viewport: 0, 1865 request_count: 0, 1866 viewability_periods: [], 1867 placement_id: placementId, // Store reference to parent placement 1868 tile_id: tileId // Store the actual tile ID 1869 }; 1870 } 1871 1872 // Mark as requested 1873 tracker.adPerformance[trackingId].ad_requested = true; 1874 tracker.adPerformance[trackingId].request_time = new Date().toISOString(); 1875 tracker.adPerformance[trackingId].request_count = 1876 (tracker.adPerformance[trackingId].request_count || 0) + 1; 1877 1878 } 1879 } 1880 } 1881 }); 1882 } 1883 }); 1884 1885 // Also set up DOM mutation observer to catch non-event-based populations 1886 const populationObserver = new MutationObserver((mutations) => { 1887 mutations.forEach(mutation => { 1888 if (mutation.type === 'attributes' && 1889 (mutation.attributeName === 'class' || mutation.attributeName === 'data-google-query-id')) { 1890 1891 const element = mutation.target; 1892 let container = null; 1893 1894 // Find the container this element belongs to 1895 if (element.classList.contains('iqdcontainer')) { 1896 container = element; 1897 } else { 1898 container = element.closest('.iqdcontainer'); 1899 } 1900 1901 if (container) { 1902 const placement = container.dataset.placement; 1903 if (!placement) return; 1904 // Check if this mutation indicates an ad population 1905 const hasIqdAdClass = element.classList.contains('iqdad') || 1906 container.classList.contains('iqdad'); 1907 const hasGoogleQueryId = element.hasAttribute('data-google-query-id') || 1908 container.querySelector('[data-google-query-id]') !== null; 1909 1910 if ((hasIqdAdClass || hasGoogleQueryId) && 1911 !container.dataset.populationLogged) { 1912 1913 // Mark as logged to prevent duplicates 1914 container.dataset.populationLogged = 'true'; 1915 1916 // Record population 1917 const now = new Date(); 1918 const eventData = { 1919 event_type: 'AD_POPULATED', 1920 placement: placement, 1921 population_source: hasIqdAdClass ? 'iqdad_class' : 'google_query_id', 1922 timestamp: now.toISOString() 1923 }; 1924 1925 /* // Log locally 1926 this.log('AD_POPULATED', `Ad populated: ${placement}`, eventData); 1927 1928 // Send event log 1929 this.sendLogs('event', eventData); 1930 */ 1931 // Capture creative info 1932 this.captureCreativeInfo(container, placement); 1933 1934 } 1935 } 1936 } 1937 }); 1938 }); 1939 1940 // Observe document for class changes 1941 populationObserver.observe(document.body, { 1942 attributes: true, 1943 attributeFilter: ['class', 'data-google-query-id'], 1944 subtree: true 1945 }); 1946 }, 1947 1948 1949 setupEnhancedViewportTracking: function() { 1950 if (!this.viewabilityTimers) { 1951 this.viewabilityTimers = {}; 1952 } 1953 const viewabilityThreshold = 0.5; 1954 1955 const observer = new IntersectionObserver((entries) => {
1956 entries.forEach(entry => { 1957 const container = entry.target; 1958 const placement = container.dataset.placement; 1959 1960 if (!placement) return; 1961 1962 this.trackPlacementViewport(placement, entry); 1963 1964 // Special handling for pos_1 tiles 1965 if (placement === 'pos_1') { 1966 // Find all pos_1 tiles within this container 1967 const pos1Tiles = container.querySelectorAll('#iqadtile20, #iqadtile21, #iqadtile1'); 1968 1969 // If we found any of the special tiles, track them individually 1970 if (pos1Tiles.length > 0) { 1971 pos1Tiles.forEach(tileElement => { 1972 const tileId = tileElement.id; 1973 const trackingId = this.pos1TileMapping[tileId]; 1974 1975 if (trackingId) { 1976 // Create a custom entry object for the tile 1977 const tileRect = tileElement.getBoundingClientRect(); 1978 const isTileInViewport = ( 1979 tileRect.top >= 0 && 1980 tileRect.left >= 0 && 1981 tileRect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && 1982 tileRect.right <= (window.innerWidth || document.documentElement.clientWidth) 1983 ); 1984 1985 const tileEntry = { 1986 isIntersecting: isTileInViewport, 1987 intersectionRatio: isTileInViewport ? 1.0 : 0.0, 1988 target: tileElement 1989 }; 1990 1991 this.trackPlacementViewport(trackingId, tileEntry); 1992 } 1993 }); 1994 } 1995 } 1996 }); 1997 }, { 1998 threshold: [0, 0.25, 0.5, 0.75, 1.0], 1999 rootMargin: '0px' 2000 }); 2001 2002 const containers = document.querySelectorAll('.iqdcontainer'); 2003 document.querySelectorAll('.iqdcontainer').forEach(container => { 2004 observer.observe(container); 2005 }); 2006 2007 this.viewportObserver = observer; 2008 2009 setInterval(() => { 2010 document.querySelectorAll('.iqdcontainer').forEach(container => { 2011 if (!container.dataset.observing) { 2012 observer.observe(container); 2013 container.dataset.observing = 'true'; 2014 } 2015 }); 2016 }, 1000); 2017 2018 return observer; 2019 }, 2020 trackPlacementViewport: function(placementId, entry) { 2021 if (entry.isIntersecting) { 2022 /* console.log(`[IQDTracker] Element ${placementId} is intersecting with ratio: ${entry.intersectionRatio}`); */ 2023 if (!this.adPerformance[placementId]) { 2024 this.adPerformance[placementId] = { 2025 viewport_init: false, 2026 viewport_registration: false, 2027 ad_requested: false, 2028 delivered: false,
2029 clicked: false, 2030 time_in_viewport: 0, 2031 viewability_periods: [] 2032 }; 2033 } 2034 2035 this.trackViewportEntry(placementId); 2036 2037 if (entry.intersectionRatio >= 0.5) { 2038 if (!this.viewabilityTimers[placementId]) { 2039 this.viewabilityTimers[placementId] = setTimeout(() => { 2040 if (this.adPerformance[placementId]) { 2041 this.adPerformance[placementId].viewport_registration = true; 2042 } 2043 }, 1000); 2044 } 2045 } 2046 2047 if (entry.target && !entry.target.dataset.loaded && 2048 this.adPositions && this.adPositions.belowFold && 2049 this.adPositions.belowFold.includes(placementId)) { 2050 entry.target.dataset.loaded = 'true'; 2051 } 2052 } else { 2053 this.trackViewportExit(placementId); 2054 2055 if (this.viewabilityTimers && this.viewabilityTimers[placementId]) { 2056 clearTimeout(this.viewabilityTimers[placementId]); 2057 delete this.viewabilityTimers[placementId]; 2058 } 2059 } 2060 }, 2061 2062 trackViewportEntry: function(placement) { 2063 const now = new Date(); 2064 const timestamp = now.toISOString(); 2065 const eventId = this.generateEventId(); 2066 2067 if (!this.adPerformance[placement]) { 2068 this.adPerformance[placement] = { 2069 viewport_init: false, 2070 viewport_registration: false, 2071 ad_requested: false, 2072 delivered: false, 2073 clicked: false, 2074 time_in_viewport: 0, 2075 viewability_periods: [] 2076 }; 2077 } 2078 2079 if (!this.viewportEntryTimestamps[placement]) { 2080 this.viewportAds.add(placement); 2081 this.viewportEntryTimestamps[placement] = timestamp; 2082 2083 this.adPerformance[placement].viewport_init = true; 2084 this.adPerformance[placement].first_viewport_entry = timestamp; 2085 2086 if (!this.adPerformance[placement]) { 2087 this.adPerformance[placement] = {}; 2088 } 2089 2090 if (!this.adPerformance[placement].viewability_periods) { 2091 this.adPerformance[placement].viewability_periods = []; 2092 } 2093 2094 this.adPerformance[placement].viewability_periods.push({ 2095 entry: timestamp, 2096 exit: null, 2097 entry_event_id: eventId 2098 }); 2099 2100 } else { 2101 this.viewportEntryTimestamps[placement] = timestamp; 2102 if (this.adPerformance[placement].viewability_periods) { 2103 this.adPerformance[placement].viewability_periods.push({ 2104 entry: timestamp, 2105 exit: null 2106 }); 2107 } 2108 } return eventId; 2109 }, 2110 2111 trackViewportExit: function(placement) { 2112 if (!this.viewportEntryTimestamps[placement]) return; 2113 2114 const now = new Date();
2115 const exitTime = now.toISOString(); 2116 this.viewportExitTimestamps[placement] = exitTime; 2117 const entryTime = new Date(this.viewportEntryTimestamps[placement]); 2118 const dwellTimeMs = now - entryTime; 2119 2120 if (!this.viewportDwellTime[placement]) { 2121 this.viewportDwellTime[placement] = 0; 2122 } 2123 2124 if (this.adPerformance[placement]) { 2125 this.adPerformance[placement].time_in_viewport = this.viewportDwellTime[placement]; 2126 2127 if (dwellTimeMs > 0 && dwellTimeMs < 3600000) { 2128 this.viewportDwellTime[placement] += dwellTimeMs; 2129 2130 if (this.adPerformance[placement] && 2131 this.adPerformance[placement].viewability_periods && 2132 this.adPerformance[placement].viewability_periods.length > 0) { 2133 const periods = this.adPerformance[placement].viewability_periods; 2134 for (let i = periods.length - 1; i >= 0; i--) { 2135 if (!periods[i].exit) { 2136 periods[i].exit = exitTime; 2137 periods[i].duration_ms = dwellTimeMs; 2138 break; 2139 } 2140 } 2141 } 2142 } 2143 } 2144 }, 2145 2146 trackAdInteraction: function(placement, interactionType, details = {}) { 2147 const now = new Date(); 2148 const timestamp = now.toISOString(); 2149 const eventData = { 2150 event_type: 'AD_INTERACTION', 2151 interaction: { 2152 placement: placement, 2153 type: interactionType, 2154 timestamp: timestamp, 2155 details: details 2156 } 2157 }; 2158 this.userInteractions.push(eventData.interaction); 2159 this.log('AD_INTERACTION', `User ${interactionType} on ${placement}`, eventData); 2160 this.sendLogs('event', eventData); 2161 }, 2162 2163 logDynamicAdSetup: function(stats) { 2164 this.dynamicAdStats = this.sanitizeData(stats); 2165 const creationTime = new Date().toISOString(); 2166 if (stats.placedAds && Array.isArray(stats.placedAds)) { 2167 stats.placedAds.forEach(ad => { 2168 const placement = ad.placement; 2169 if (!this.adPerformance[placement]) { 2170 this.adPerformance[placement] = { 2171 creationTime: creationTime, 2172 isDynamic: true, 2173 position: ad.position, 2174 paragraphIndex: parseInt(ad.position.match(/paragraph (\d+)/)?.[1] || '0', 10), 2175 fillStatus: 'pending', 2176 viewability_periods: [] 2177 }; 2178 } else { 2179 this.adPerformance[placement].creationTime = creationTime; 2180 this.adPerformance[placement].isDynamic = true; 2181 this.adPerformance[placement].position = ad.position; 2182 this.adPerformance[placement].paragraphIndex = parseInt(ad.position.match(/paragraph (\d+)/)?.[1] || '0', 10); 2183 } 2184 }); 2185 } 2186 2187 this.log('DYNAMIC_ADS', 'Dynamic ad setup completed', { 2188 stats: { 2189 numberOfParagraphs: this.dynamicAdStats.numberOfParagraphs, 2190 deviceType: this.dynamicAdStats.deviceType, 2191 numberOfAdsPlaced: this.dynamicAdStats.placedAds?.length || 0, 2192 timestamp: creationTime 2193 } 2194 }); 2195 }, 2196 2197 initConsoleListener: function() { 2198 if (!this.consoleLogListenerInitialized) { 2199 this.consoleLogListenerInitialized = true; 2200 2201 const originalConsoleLog = console.log; 2202 2203 const self = this; 2204 console.log = function(...args) { 2205 originalConsoleLog.apply(console, args); 2206 2207 if (args.length > 0 && typeof args[0] === 'string') { 2208 const logMessage = args[0]; 2209 2210 const renderMatch = logMessage.match(/\[FFA\] in render\(\) (iqadtile\d+)/i); 2211 if (renderMatch) { 2212 const tileId = renderMatch[1]; 2213 originalConsoleLog.apply(console, [`[IQDTracker] Detected ad request for tile: ${tileId}`]); 2214 2215 const tileContainer = document.querySelector(`[id="${tileId}"]`); 2216 if (tileContainer) { 2217 const adContainer = tileContainer.closest('.iqdcontainer'); 2218 if (adContainer) { 2219 const placementId = adContainer.dataset.placement; 2220 if (placementId) { 2221 if (!self.adPerformance[placementId]) { 2222 self.adPerformance[placementId] = { 2223 viewport_init: false, 2224 viewport_registration: false, 2225 ad_requested: false, 2226 delivered: false, 2227 clicked: fal
2227se, 2228 time_in_viewport: 0, 2229 request_count: 0, 2230 viewability_periods: [] 2231 }; 2232 } 2233 2234 // Mark as requested 2235 self.adPerformance[placementId].ad_requested = true; 2236 self.adPerformance[placementId].request_time = new Date().toISOString(); 2237 self.adPerformance[placementId].request_count = 2238 (self.adPerformance[placementId].request_count || 0) + 1; 2239 2240 originalConsoleLog.apply(console, [ 2241 `[IQDTracker] Ad request detected for placement ${placementId} via console log (count: ${self.adPerformance[placementId].request_count})` 2242 ]); 2243 } 2244 } 2245 } 2246 } 2247 } 2248 }; 2249 } 2250 }, 2251 2252 detectAdDelivery: function(container) { 2253 if (!container) return false; 2254 return container.classList.contains('iqdad'); 2255 }, 2256 2257 trackAdPerformance: function(placement, metrics) { 2258 // Add debug info 2259 console.group(`[IQDTracker] trackAdPerformance for ${placement}`); 2260 2261 if (!this.adPerformance[placement]) { 2262 this.adPerformance[placement] = { 2263 request_count: 0, 2264 fill_count: 0, 2265 view_count: 0, 2266 click_count: 0, 2267 viewability_periods: [] 2268 }; 2269 } 2270 2271 const previousState = JSON.parse(JSON.stringify(this.adPerformance[placement])); 2272 2273 // IMPORTANT: Store data in consistent format 2274 this.adPerformance[placement] = { 2275 ...this.adPerformance[placement], 2276 ...metrics, 2277 lastUpdated: new Date().toISOString() 2278 }; 2279 2280 // Standardize: Always set both requestTime and request_time 2281 if (metrics.requestTime && !this.adPerformance[placement].request_time) { 2282 this.adPerformance[placement].request_time = metrics.requestTime; 2283 } 2284 if (metrics.request_time && !this.adPerformance[placement].requestTime) { 2285 this.adPerformance[placement].requestTime = metrics.request_time; 2286 } 2287 2288 if (metrics.status === 'requested') { 2289 this.adPerformance[placement].request_count++; 2290 this.adPerformance[placement].ad_requested = true; 2291 this.adPerformance[placement].request_time = this.adPerformance[placement].request_time || new Date().toISOString(); 2292 this.adPerformance[placement].requestTime = this.adPerformance[placement].requestTime || new Date().toISOString(); 2293 } 2294 if (metrics.status === 'loaded' || metrics.fillStatus === 'filled') { 2295 this.adPerformance[placement].delivered = true; 2296 } else if (metrics.status === 'failed' || metrics.fillStatus === 'unfilled') { 2297 this.adPerformance[placement].delivered = false;
2298 } 2299 const containerElement = document.querySelector(`.iqdcontainer[data-placement="${placement}"]`); 2300 if (containerElement) { 2301 const hasIqdAdClass = containerElement.classList.contains('iqdad'); 2302 const hasIqdNoAdClass = containerElement.classList.contains('iqdnoad'); 2303 2304 if (hasIqdAdClass && !this.adPerformance[placement].fill_verified) { 2305 this.adPerformance[placement].fill_count++; 2306 this.adPerformance[placement].fill_verified = true; 2307 this.adPerformance[placement].fillStatus = 'filled'; 2308 this.adPerformance[placement].delivered = true; 2309 this.adPerformance[placement].fill_verification_source = 'dom'; 2310 2311 } else if (hasIqdNoAdClass && !this.adPerformance[placement].unfill_verified) { 2312 this.adPerformance[placement].unfill_verified = true; 2313 this.adPerformance[placement].fillStatus = 'unfilled'; 2314 this.adPerformance[placement].delivered = false; 2315 this.adPerformance[placement].fill_verification_source = 'dom'; 2316 } 2317 } 2318 if (metrics.status === 'impressed') { 2319 this.adPerformance[placement].view_count++; 2320 } 2321 2322 if (this.adPerformance[placement].request_count > 0) { 2323 this.adPerformance[placement].fill_rate = 2324 (this.adPerformance[placement].fill_count / this.adPerformance[placement].request_count) * 100; 2325 } 2326 2327 const changes = {}; 2328 Object.keys(this.adPerformance[placement]).forEac
2328h(key => { 2329 if (JSON.stringify(previousState[key]) !== JSON.stringify(this.adPerformance[placement][key])) { 2330 changes[key] = { 2331 from: previousState[key], 2332 to: this.adPerformance[placement][key] 2333 }; 2334 } 2335 }); 2336 console.groupEnd(); 2337 }, 2338 2339 prepareSessionSummary: function() { 2340 try { 2341 const sessionDuration = this.getSessionDuration(); 2342 let pageLoadTime = null; 2343 2344 try { 2345 pageLoadTime = performance.timing ? 2346 (performance.timing.loadEventEnd - performance.timing.navigationStart) : null; 2347 } catch (e) { 2348 console.error('[IQDTracker] Error getting page load time:', e); 2349 } 2350 2351 const adContainers = this.collectAllAdContainers(); 2352 const placementMetrics = {}; 2353 adContainers.forEach(container => { 2354 placementMetrics[container.id] = { 2355 time_in_viewport: container.time_in_viewport, 2356 viewport_init: container.viewport_init, 2357 viewport_registration: container.viewport_registration, 2358 ad_requested: container.ad_requested, 2359 delivered: container.ad_delivered, 2360 clicked: container.ad_clicked, 2361 request_time: container.request_time, 2362 load_time: container.load_time, 2363 is_dynamic: container.is_dynamic, 2364 viewability_periods: container.viewability_periods || [] 2365 }; 2366 }); 2367 2368 const consentData = this.cmpConsentData || {}; 2369 2370 return { 2371 session: { 2372 id: this.getSessionId(), 2373 duration_ms: sessionDuration, 2374 page_url: this.pageUrl, 2375 referrer_url: this.referrerUrl, 2376 page_load_time_ms: pageLoadTime, 2377 timestamp_start: this.getSessionStartTime(), 2378 timestamp_end: new Date().toISOString(), 2379 device: this.getBrowserInfo().deviceType, 2380 browser: this.getBrowserInfo().userAgent 2381 }, 2382 viewport_activity: { 2383 initial_viewport: this.getInitialViewportAds(), 2384 max_scroll_depth: this.calculateScrollDepth(), 2385 /* total_view_time_ms: totalViewTime, 2386 average_view_time_ms: totalAdsViewed > 0 ? (totalViewTime / totalAdsViewed) : 0 */ 2387 }, 2388 ad_performance: { 2389 total_placements: this.allPlacements.size, 2390 dynamic_placements: this.countDynamicPlacements(), 2391 static_placements: this.allPlacements.size - this.countDynamicPlacements() 2392 }, 2393 consent: { 2394 gdprApplies: consentData.gdprApplies, 2395 tcString: consentData.tcString, 2396 eventStatus: consentData.eventStatus, 2397 purpose: consentData.purpose, 2398 vendor: consentData.vendor 2399 }, 2400 ad_containers: adContainers, 2401 placement_metrics: placementMetrics, 2402 cms_data: this.cmsConfig || {} 2403 }; 2404 } catch (error) { 2405 console.error('[IQDTracker] Error preparing session summary:', error); 2406 return { 2407 session: {
2408 id: this.getSessionId() || 'error', 2409 duration_ms: 0, 2410 page_url: this.pageUrl || window.location.href, 2411 timestamp_end: new Date().toISOString() 2412 }, 2413 error: { 2414 message: error.message, 2415 stack: error.stack 2416 } 2417 }; 2418 } 2419 }, 2420 2421 calculateVisibleViewTime: function(placement) { 2422 const periods = this.adPerformance[placement]?.viewability_periods || []; 2423 let visibleTime = 0; 2424 2425 periods.forEach(period => { 2426 if (period.duration_ms && period.duration_ms >= 1000) { 2427 visibleTime += period.duration_ms; 2428 } 2429 }); 2430 2431 return visibleTime; 2432 }, 2433 2434 getSessionStartTime: function() { 2435 if (this.pageVisitEvents.length > 0) { 2436 return this.pageVisitEvents[0].timestamp; 2437 } 2438 return this.trackingStartTime || 2439 new Date(new Date().getTime() - this.getSessionDuration()).toISOString(); 2440 }, 2441 2442 countInteractionsForPlacement: function(placement) { 2443 return this.userInteractions.filter(interaction => 2444 interaction.placement === placement 2445 ).length; 2446 }, 2447 2448 getViewableContainers: function() { 2449 const viewableContainers = []; 2450 2451 try { 2452 this.allPlacements.forEach(placement => { 2453 const performanceData = this.adPerformance[placement] || {}; 2454 const hasEnoughViewTime = performanceData.viewability_periods && 2455 performanceData.viewability_periods.some(period => 2456 period.duration_ms >= 1000 2457 ); 2458 const hasFilled = performanceData.fillStatus === 'filled'; 2459 2460 if (hasEnoughViewTime && hasFilled) { 2461 viewableContainers.push(placement); 2462 } 2463 }); 2464 } catch (error) { 2465 console.error('[IQDTracker] Error getting viewable containers:', error); 2466 }; 2467 return viewableContainers; 2468 }, 2469 2470 getNonViewableContainers: function() { 2471 const nonViewableContainers = []; 2472 2473 try { 2474 this.allPlacements.forEach(placement => { 2475 const performanceData = this.adPerformance[placement] || {}; 2476 const hasEnoughViewTime = performanceData.viewability_periods && 2477 performanceData.viewability_periods.some(period => 2478 period.duration_ms >= 1000 2479 ); 2480 2481 const notFilled = performanceData.fillStatus !== 'filled'; 2482 2483 if (hasEnoughViewTime && notFilled) { 2484 nonViewableContainers.push(placement); 2485 } 2486 }); 2487 } catch (error) { 2488 console.error('[IQDTracker] Error getting non-viewable containers:', error); 2489 } 2490 2491 return nonViewableContainers; 2492 }, 2493 2494 getInitialViewportAds: function() { 2495 if (this._initialViewportAds) { 2496 return this._initialViewportAds; 2497 } 2498 for (let i = 0; i < this.pageVisitEvents.length; i++) { 2499 const event = this.pageVisitEvents[i]; 2500 if (event.event_type === 'VIEWPORT_INIT' && event.data && event.data.initialVisible) { 2501 this._initialViewportAds = event.data.initialVisible; 2502 return this._initialViewportAds; 2503 } 2504 } 2505 return Array.from(this.viewportAds); 2506 }, 2507 2508 countDynamicPlacements: function() { 2509 let count = 0;
2510 this.allPlacements.forEach(placement => { 2511 if (this.isDynamicPlacement(placement)) { 2512 count++; 2513 } 2514 }); 2515 return count; 2516 }, 2517 2518 getViewportEventsForPlacement: function(placement) { 2519 const entries = []; 2520 const exits = []; 2521 if (this.adPerformance[placement]?.viewability_periods) { 2522 this.adPerformance[placement].viewability_periods.forEach(period => { 2523 entries.push(period.entry); 2524 if (period.exit) exits.push(period.exit); 2525 }); 2526 } 2527 2528 return { entries, exits }; 2529 }, 2530 2531 calculateScrollDepth: function() { 2532 try { 2533 if (!document.body || !document.documentElement) { 2534 console.warn('[IQDTracker] document.body or document.documentElement is null'); 2535 return { 2536 document_height_px: 0, 2537 max_scroll_px: 0, 2538 max_scroll_pct: 0 2539 }; 2540 } 2541 const bodyScrollHeight = document.body ? document.body.scrollHeight : 0; 2542 const docScrollHeight = document.documentElement ? document.documentElement.scrollHeight : 0; 2543 const bodyOffsetHeight = document.body ? document.body.offsetHeight : 0; 2544 const docOffsetHeight = document.documentElement ? document.documentElement.offsetHeight : 0; 2545 2546 const docHeight = Math.max(bodyScrollHeight, docScrollHeight, bodyOffsetHeight, docOffsetHeight, 1); 2547 const viewportHeight = window.innerHeight || 0; 2548 const maxScrollY = Math.max(docHeight - viewportHeight, 0); 2549 const maxScrolled = this.maxScrollPosition || 0; 2550 2551 return { 2552 document_height_px: docHeight, 2553 max_scroll_px: maxScrolled, 2554 max_scroll_pct: maxScrollY > 0 ? (maxScrolled / maxScrollY) * 100 : 0 2555 }; 2556 } catch (error) { 2557 console.error('[IQDTracker] Error calculating scroll depth:', error); 2558 return { 2559 document_height_px: 0, 2560 max_scroll_px: 0, 2561 max_scroll_pct: 0, 2562 error: error.message 2563 }; 2564 } 2565 }, 2566 2567 getSessionDuration: function() { 2568 if (this.pageVisitEvents.length === 0) return 0; 2569 let earliestTime = new Date(this.pageVisitEvents[0].timestamp); 2570 let latestTime = earliestTime; 2571 this.pageVisitEvents.forEach(event => { 2572 const eventTime = new Date(event.timestamp); 2573 if (eventTime < earliestTime) earliestTime = eventTime; 2574 if (eventTime > latestTime) latestTime = eventTime; 2575 }); 2576 2577 return latestTime - earliestTime; 2578 }, 2579 2580 sanitizeData: function(obj) { 2581 const seen = new WeakSet(); 2582 return JSON.parse(JSON.stringify(obj, (key, value) => { 2583 if (value instanceof Node) return '[DOM Node]'; 2584 if (typeof value === 'function') return '[Function]'; 2585 if (typeof value === 'object' && value !== null) { 2586 if (seen.has(value)) { 2587 return '[Circular]'; 2588 } 2589 seen.add(value); 2590 } 2591 return value; 2592 })); 2593 }, 2594 2595 2596 setupInactivityBackup: function() { 2597 const INACTIVITY_THRESHOLD_MS = 3 * 60 * 1000; 2598 const CHECK_INTERVAL_MS = 30000; 2599 2600 let lastActivityTime = Date.now(); 2601 let backupSent = false;
2602 2603 const resetActivityTimer = () => { 2604 const currentTime = Date.now(); 2605 const timeSinceLastActivity = currentTime - lastActivityTime; 2606 2607 if (timeSinceLastActivity > 10000) { 2608 backupSent = false; 2609 } 2610 2611 lastActivityTime = currentTime; 2612 }; 2613 2614 const activityEvents = ['mousedown', 'mousemove', 'keypress', 'scroll', 'touchstart', 'click']; 2615 activityEvents.forEach(eventType => { 2616 document.addEventListener(eventType, resetActivityTimer, { passive: true }); 2617 }); 2618 2619 resetActivityTimer(); 2620 2621 if (this._inactivityInterval) { 2622 clearInterval(this._inactivityInterval); 2623 } 2624 2625 this._inactivityInterval = setInterval(() => { 2626 const inactiveDuration = Date.now() - lastActivityTime; 2627 2628 if (inactiveDuration >= INACTIVITY_THRESHOLD_MS && !backupSent) { 2629 2630 try { 2631 const sendResult = this.sendLogs('inactivity_backup'); 2632 backupSent = true; 2633 } catch (error) { 2634 console.error('[IQDTracker] Error sending inactivity backup:', error); 2635 } 2636 } 2637 }, CHECK_INTERVAL_MS); 2638 2639 const cleanupInactivityTimer = () => { 2640 if (this._inactivityInterval) { 2641 clearInterval(this._inactivityInterval); 2642 } 2643 }; 2644 2645 window.addEventListener('beforeunload', cleanupInactivityTimer); 2646 window.addEventListener('unload', cleanupInactivityTimer); 2647 2648 return this._inactivityInterval; 2649 }, 2650 2651 sendInactivityBackup: function() { 2652 try { 2653 2654 const exitLog = { 2655 event_id: this.generateEventId(), 2656 page_visit_id: this.getPageVisitId(), 2657 timestamp: new Date().toISOString(), 2658 session_id: this.getSessionId(), 2659 page_url: this.pageUrl, 2660 referrer_url: this.referrerUrl, 2661 browser_info: this.getBrowserInfo(), 2662 log_type: 'inactivity_backup', 2663 session_summary: this.prepareSessionSummary(), 2664 ad_containers: this.collectAllAdContainers(), 2665 viewability: { 2666 max_scroll_depth: this.calculateScrollDepth(), 2667 viewport_times: this.viewportDwellTime, 2668 verified_viewable: this.getViewableContainers(), 2669 verified_non_viewable: this.getNonViewableContainers() 2670 }, 2671 cms_config: this.cmsConfig 2672 }; 2673 2674 try { 2675 exitLog.session_summary = this.prepareSessionSummary(); 2676 } catch (error) { 2677 console.error('[IQDTracker] Error preparing session summary:', error); 2678 exitLog.session_summary_error = error.message; 2679 } 2680 2681 try { 2682 localStorage.setItem('iqd_inactivity_backup', JSON.stringify(exitLog)); 2683 } catch (error) { 2684 console.error('[IQDTracker] Failed to save inactivity backup to localStorage:', error); 2685 } 2686 } catch (error) { 2687 console.error('[IQDTracker] Error sending inactivity backup:', error); 2688 } 2689 }, 2690 setupCMPConsentTracking: function() { 2691 if (typeof window.__tcfapi === 'function') { 2692 try { 2693 window.__tcfapi('addEventListener', 2, (tcData, success) => { 2694 if (success) { 2695 this.cmpConsentData = this.sanitizeData(tcData); 2696 2697 // Log the consent data 2698 this.log('CMP_CONSENT', 'CMP consent data received', { 2699 eventStatus: tcData.eventStatus, 2700 gdprApplies: tcData.gdprApplies, 2701 timestamp: new Date().toISOString(), 2702 tcString: tcData.tcString, 2703 purpose: tcData.purpose, 2704 vendor: tcData.vendor, 2705 listenerId: tcData.listenerId 2706 }); 2707 2708 // Send the consent data to the server 2709 this.sendLogs('consent', { 2710 eventStatus: tcData.eventStatus, 2711 gdprApplies: tcData.gdprApplies, 2712 tcString: tcData.tcString, 2713 purpose: tcData.purpose, 2714 vendor: tcData.vendor, 2715 timestamp: new Date().toISOString() 2716 }); 2717 } else { 2718 } 2719 }); 2720 2721 // Also get the current consent data 2722 window.__tcfapi('getTCData', 2, (tcData, success) => { 2723 if (success) { 2724 this.cmpConsentData = this.sanitizeData(tcData); 2725 2726 this.log('CMP_CONSENT_INITIAL', 'Initial CMP consent data', { 2727 gdprApplies: tcData.gdprApplies, 2728 timestamp: new Date().toISOString(), 2729 tcString: tcData.tcString, 2730 purpose: tcData.purpose, 2731 vendor: tcData.vendor 2732 }); 2733 2734 this.sendLogs('consent_initial', { 2735 gdprApplies: tcData.gdprApplies, 2736 tcString: tcData.tcString, 2737 purpose: tcData.purpose, 2738 vendor: tcData.vendor, 2739 timestamp: new Date().toISOString() 2740 }); 2741 } else { 2742 console.error('[IQDTracker] Failed to get current CMP consent data'); 2743 } 2744 }); 2745 } catch (error) { 2746 console.error('[IQDTracker] Error setting up CMP consent tracking:', error); 2747 } 2748 } else { 2749 console.warn('[IQDTracker] __tcfapi not available, CMP consent tracking not initialized'); 2750 2751 2752 setTimeout(() => { 2753 if (typeof window.__tcfapi === 'function') { 2754 this.setupCMPConsentTracking(); 2755 } else { 2756 console.warn('[IQDTracker] __tcfapi still not available after delay'); 2757 } 2758 }, 2000); 2759 } 2760 }, 2761 2762 sendLogs: async function(logType = 'exit_summary', customData = null, isUnload = false) { 2763 try { 2764 const validLogTypes = ['exit_summary', 'inactivity_backup', 2765 'stored_exit_summary', 'recovered_exit_summary']; 2766 2767 if (!validLogTypes.includes(logType)) { 2768 return false;
2769 } 2770 2771 const logEventId = this.generateEventId(); 2772 const sessionId = this.getSessionId(); 2773 const pageVisitId = this.getPageVisitId(); 2774 2775 let pageVisit; 2776 2777 if (customData && customData.event_id && customData.page_visit_id) { 2778 pageVisit = customData; 2779 } else { 2780 pageVisit = { 2781 event_id: logEventId, 2782 page_visit_id: pageVisitId, 2783 metadata: { 2784 timestamp: new Date().toISOString(), 2785 session_id: sessionId, 2786 page_url: this.pageUrl, 2787 referrer_url: this.referrerUrl, 2788 browser_info: this.getBrowserInfo(), 2789 log_type: logType 2790 } 2791 }; 2792 } 2793 const logIdentifier = `${sessionId}_${pageVisitId}_${logEventId}`; 2794 if (logType === 'exit_summary' || logType === 'inactivity_backup') { 2795 const sentLogIds = this.getSentLogIds(); 2796 const pageVisitSent = sentLogIds.some(id => id.includes(`${sessionId}_${pageVisitId}_`)); 2797 2798 if (pageVisitSent) { 2799 return false; 2800 } 2801 } 2802 if (logType === 'exit_summary' || 2803 logType === 'inactivity_backup' || 2804 logType === 'stored_exit_summary' || 2805 logType === 'recovered_exit_summary') { 2806 2807 if (!pageVisit.session_summary) { 2808 try { 2809 pageVisit.session_summary = this.prepareSessionSummary(); 2810 } catch (summaryError) { 2811 console.error('[IQDTracker] Error preparing session summary:', summaryError); 2812 pageVisit.session_summary_error = summaryError.message; 2813 } 2814 } 2815 2816 if (!pageVisit.ad_containers) { 2817 try { 2818 pageVisit.ad_containers = this.collectAllAdContainers(); 2819 pageVisit.viewability = { 2820 max_scroll_depth: this.calculateScrollDepth(), 2821 viewport_times: this.viewportDwellTime, 2822 verified_viewable: this.getViewableContainers(), 2823 verified_non_viewable: this.getNonViewableContainers() 2824 }; 2825 } catch (containerError) { 2826 console.error('[IQDTracker] Error collecting ad containers:', containerError); 2827 } 2828 } 2829 } 2830 2831 // For custom event data 2832 if (logType === 'event' && customData) { 2833 pageVisit.event_data = customData; 2834 if (customData.placement) { 2835 pageVisit.placement = customData.placement; 2836 } 2837 } 2838 2839 // Include CMS config if available 2840 if (this.cmsConfig) { 2841 pageVisit.cms_config = this.cmsConfig; 2842 } 2843 if (this.cmpConsentData) { 2844 pageVisit.consent = { 2845 gdprApplies: this.cmpConsentData.gdprApplies, 2846 tcString: this.cmpConsentData.tcString, 2847 eventStatus: this.cmpConsentData.eventStatus 2848 }; 2849 } 2850 2851 const currentNonce = window.adLoggingNonce || ''; 2852 2853 // Use sendBeacon for exit logs when available 2854 if ((logType === 'exit_summary' || isUnload) && navigator.sendBeacon) { 2855 try { 2856 const formData = new FormData(); 2857 formData.append('action', 'ad_performance_log'); 2858 formData.append('nonce', currentNonce); 2859 formData.append('log_data', JSON.stringify(pageVisit)); 2860 2861 const beaconSent = navigator.sendBeacon(this.loggingEndpoint, formData); 2862 2863 if (beaconSent) { 2864 this.addSentLogId(logIdentifier); 2865 } else { 2866 this.storeLogForRetry(pageVisit); 2867 } 2868 2869 return beaconSent; 2870 } catch (beaconError) { 2871 console.error('[IQDTracker] Beacon error:', beaconError); 2872 this.storeLogForRetry(pageVisit); 2873 return false;
2874 } 2875 } 2876 try { 2877 const formData = new FormData(); 2878 formData.append('action', 'ad_performance_log'); 2879 formData.append('nonce', currentNonce); 2880 formData.append('log_data', JSON.stringify(pageVisit)); 2881 2882 const response = await fetch(this.loggingEndpoint, { 2883 method: 'POST', 2884 credentials: 'same-origin', 2885 body: formData 2886 }); 2887 2888 if (!response.ok) { 2889 console.error(`[IQDTracker] HTTP error: ${response.status} ${response.statusText}`); 2890 try { 2891 const responseText = await response.text(); 2892 console.error(`[IQDTracker] Response text:`, responseText); 2893 } catch (e) {} 2894 2895 if (logType !== 'event' && logType !== 'periodic_backup') { 2896 this.storeLogForRetry(pageVisit); 2897 } 2898 2899 return false; 2900 } 2901 2902 let result; 2903 try { 2904 result = await response.json(); 2905 } catch (jsonError) { 2906 console.error(`[IQDTracker] Error parsing JSON response:`, jsonError); 2907 try { 2908 const responseText = await response.text(); 2909 console.error(`[IQDTracker] Raw response:`, responseText); 2910 } catch (e) {} 2911 return false; 2912 } 2913 2914 if (!result || !result.success) { 2915 console.error(`[IQDTracker] Server reported failure:`, result); 2916 return false; 2917 } 2918 if (logType === 'exit_summary' || 2919 logType === 'inactivity_backup' || 2920 logType === 'recovered_exit_summary') { 2921 this.addSentLogId(logIdentifier); 2922 } 2923 return true; 2924 } catch (error) { 2925 console.error('[IQDTracker] Error sending log:', error); 2926 2927 if (logType !== 'event' && logType !== 'periodic_backup') { 2928 this.storeLogForRetry(pageVisit); 2929 } 2930 2931 return false; 2932 } 2933 } catch (error) { 2934 console.error('[IQDTracker] Critical error in sendLogs:', error); 2935 return false; 2936 } 2937 }, 2938 2939 storeLogForRetry: function(logData) { 2940 try { 2941 const EXIT_LOG_STORAGE_KEY = 'iqd_pending_exit_log'; 2942 logData.retry_timestamp = new Date().toISOString(); 2943 2944 localStorage.setItem(EXIT_LOG_STORAGE_KEY, JSON.stringify(logData)); 2945 } catch (error) { 2946 console.error('[IQDTracker] Failed to store log for retry:', error); 2947 } 2948 }, 2949 2950 2951 calculateFillRateSummary: function() { 2952 let totalPlacements = this.allPlacements.size; 2953 let filledPlacements = 0; 2954
2955 this.allPlacements.forEach(placement => { 2956 const container = document.querySelector(`.iqdcontainer[data-placement="${placement}"]`); 2957 if (container && container.classList.contains('iqdad')) { 2958 filledPlacements++; 2959 } 2960 }); 2961 2962 return { 2963 total_placements: totalPlacements, 2964 filled_placements: filledPlacements, 2965 fill_rate: totalPlacements > 0 ? (filledPlacements / totalPlacements) * 100 : 0 2966 }; 2967 }, 2968 2969 formatDynamicAdInfo: function() { 2970 if (!this.dynamicAdStats) { 2971 return { 2972 numberOfParagraphs: 0, 2973 deviceType: this.getBrowserInfo().deviceType, 2974 placements: [] 2975 }; 2976 } 2977 const placements = this.dynamicAdStats.placedAds.map(ad => { 2978 const performanceData = this.adPerformance[ad.placement] || {}; 2979 2980 return { 2981 id: ad.placement, 2982 position: ad.position, 2983 fill_status: performanceData.fillStatus || 'pending', 2984 time_in_viewport: this.viewportDwellTime[ad.placement] || 0 2985 }; 2986 }); 2987 2988 return { 2989 numberOfParagraphs: this.dynamicAdStats.numberOfParagraphs, 2990 deviceType: this.dynamicAdStats.deviceType, 2991 placements: placements 2992 }; 2993 }, 2994 2995 getBrowserInfo: function() { 2996 return { 2997 userAgent: navigator.userAgent, 2998 language: navigator.language, 2999 viewport: { 3000 width: window.innerWidth, 3001 height: window.innerHeight 3002 }, 3003 deviceType: window.innerWidth < 1280 ? "mobile" : "desktop" 3004 }; 3005 }, 3006 3007 getSessionId: function() { 3008 if (!this._sessionId) { 3009 this._sessionId = this.getCookie('ad_session_id'); 3010 if (!this._sessionId) { 3011 this._sessionId = 'ad_' + Math.random().toString(36).substring(2) + Date.now(); 3012 this.setCookie('ad_session_id', this._sessionId, 1); 3013 } 3014 } 3015 return this._sessionId; 3016 }, 3017 3018 setCookie: function(name, value, days) { 3019 let expires = ""; 3020 if (days) { 3021 const date = new Date(); 3022 date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); 3023 expires = "; expires=" + date.toUTCString(); 3024 } 3025 document.cookie = name + "=" + encodeURIComponent(value) + expires + "; path=/"; 3026 }, 3027 3028 getCookie: function(name) { 3029 const nameEQ = name + "="; 3030 const ca = document.cookie.split(';'); 3031 for(let i = 0; i < ca.length; i++) { 3032 let c = ca[i]; 3033 while (c.charAt(0) === ' ') c = c.substring(1, c.length); 3034 if (c.indexOf(nameEQ) === 0) return decodeURIComponent(c.substring(nameEQ.length, c.length)); 3035 } 3036 return null; 3037 }, 3038 3039 getSentLogIds: function() { 3040 try { 3041 const sentLogsJson = localStorage.getItem('iqd_sent_log_ids') || '[]'; 3042 return JSON.parse(sentLogsJson); 3043 } catch (error) { 3044 console.error('[IQDTracker] Error reading sent log IDs:', error); 3045 return []; 3046 } 3047 }, 3048 3049 addSentLogId: function(logId) { 3050 try {
3051 const sentLogIds = this.getSentLogIds(); 3052 if (!sentLogIds.includes(logId)) { 3053 sentLogIds.push(logId); 3054 3055 if (sentLogIds.length > 50) { 3056 sentLogIds.shift(); 3057 } 3058 3059 localStorage.setItem('iqd_sent_log_ids', JSON.stringify(sentLogIds)); 3060 } 3061 } catch (error) { 3062 console.error('[IQDTracker] Error saving sent log ID:', error); 3063 } 3064 }, 3065 3066 setupUnloadHandler: function() { 3067 const EXIT_LOG_STORAGE_KEY = 'iqd_pending_exit_log'; 3068 let exitLogAttempted = false; 3069 3070 const handlePageExit = () => { 3071 if (exitLogAttempted) { 3072 return; 3073 } 3074 3075 exitLogAttempted = true; 3076 3077 try { 3078 const exitLog = { 3079 event_id: this.generateEventId(), 3080 page_visit_id: this.getPageVisitId(), 3081 metadata: { 3082 timestamp: new Date().toISOString(), 3083 session_id: this.getSessionId(), 3084 page_url: this.pageUrl, 3085 referrer_url: this.referrerUrl, 3086 browser_info: this.getBrowserInfo(), 3087 log_type: 'exit_summary' 3088 } 3089 }; 3090 3091 try { 3092 exitLog.session_summary = this.prepareSessionSummary(); 3093 } catch (error) { 3094 console.error('[IQDTracker] Error preparing session summary:', error); 3095 exitLog.session_summary_error = error.message; 3096 } 3097 3098 try { 3099 exitLog.ad_containers = this.collectAllAdContainers(); 3100 exitLog.viewability = { 3101 max_scroll_depth: this.calculateScrollDepth(), 3102 viewport_times: this.viewportDwellTime, 3103 verified_viewable: this.getViewableContainers(), 3104 verified_non_viewable: this.getNonViewableContainers() 3105 }; 3106 } catch (error) { 3107 console.error('[IQDTracker] Error collecting ad containers:', error); 3108 } 3109 3110 if (this.cmsConfig) { 3111 exitLog.cms_config = this.cmsConfig; 3112 } 3113 3114 if (this.cmpConsentData) { 3115 exitLog.consent = { 3116 gdprApplies: this.cmpConsentData.gdprApplies, 3117 tcString: this.cmpConsentData.tcString, 3118 eventStatus: this.cmpConsentData.eventStatus, 3119 purpose: this.cmpConsentData.purpose, 3120 vendor: this.cmpConsentData.vendor 3121 }; 3122 } 3123 3124 // Pass the exitLog object directly to sendLogs instead of letting it create a new one 3125 const sendResult = this.sendLogs('exit_summary', exitLog, true); 3126 3127 } catch (error) { 3128 console.error('[IQDTracker] Error in exit handler:', error); 3129 } 3130 }; 3131 window.addEventListener('beforeunload', handlePageExit); 3132 window.addEventListener('unload', handlePageExit); 3133 3134 }, 3135 3136 setupClickTracking: function() { 3137 3138 // Track direct clicks on ad containers or their children 3139 document.addEventListener('click', (event) => { 3140 // Find the closest ad container to the clicked element 3141 const adContainer = event.target.closest('.iqdcontainer'); 3142 3143 if (adContainer) { 3144 const placement = adContainer.dataset.placement; 3145 3146 if (placement) { 3147 this.recordAdClick(placement, event); 3148 } 3149 } 3150 }); 3151 3152 window.addEventListener('blur', () => { 3153 setTimeout(() => { 3154 if (document.activeElement && document.activeElement.tagName === 'IFRAME') { 3155 const iframe = document.activeElement; 3156 const adContainer = iframe.closest('.iqdcontainer'); 3157 3158 if (adContainer) { 3159 const placement = adContainer.dataset.placement; 3160 if (placement) { 3161 this.recordAdClick(placement, { target: iframe }); 3162 } 3163 } 3164 } 3165 }, 100); 3166 }); 3167 3168 window.addEventListener('message', (event) => { 3169 try { 3170 let data = event.data; 3171 if (typeof data === 'string') { 3172 try { 3173 data = JSON.parse(data); 3174 } catch (e) { 3175 } 3176 } 3177 3178 const isAdClick = 3179 (typeof data === 'object' && data !== null && 3180 (data.type === 'click' || data.action === 'click' || data.adClick || 3181 data.event === 'click' || data.eventType === 'click')) || 3182 (typeof data === 'string' && 3183 (data.includes('click') || data.includes('adClick') || 3184 data.includes('ad_click') || data.includes('creative_click'))); 3185 3186 if (isAdClick) { 3187 3188 const iframes = document.querySelectorAll('iframe'); 3189 for (let i = 0; i < iframes.length; i++) { 3190 if (iframes[i].contentWindow === event.source) { 3191 const adContainer = iframes[i].closest('.iqdcontainer'); 3192 if (adContainer) { 3193 const placementId = adContainer.dataset.placement; 3194 3195 if (placementId) { 3196 this.recordAdClick(placementId, { 3197 target: iframes[i], 3198 messageData: data 3199 }); 3200 } 3201 } 3202 break; 3203 } 3204 } 3205 } 3206 } catch (error) { 3207 } 3208 }); 3209 3210 if (window.navigation && typeof window.navigation.addEventListener === 'function') { 3211 window.navigation.addEventListener('navigate', (event) => { 3212 if (event.navigationType === 'push' || event.navigationType === 'replace') { 3213 const activeElement = document.activeElement; 3214 if (activeElement) { 3215 const adContainer = activeElement.closest('.iqdcontainer'); 3216 if (adContainer) { 3217 const placement = adContainer.dataset.placement; 3218 if (placement) { 3219 this.recordAdClick(placement, { 3220 target: activeElement, 3221 navigationType: event.navigationType, 3222 destination: event.destination?.url 3223 }); 3224 } 3225 } 3226 } 3227 } 3228 }); 3229 } 3230 3231 const observeIframes = () => { 3232 document.querySelectorAll('.iqdcontainer iframe').forEach(iframe => { 3233 if (!iframe.dataset.clickMonitored) { 3234 iframe.dataset.clickMonitored = 'true'; 3235 3236 iframe.addEventListener('load', () => { 3237 try { 3238 const iframeDoc = iframe.contentDocument || iframe.contentWindow.document; 3239 3240 if (iframeDoc) { 3241 const adContainer = iframe.closest('.iqdcontainer'); 3242 if (adContainer) { 3243 const placement = adContainer.dataset.placement; 3244 if (placement) { 3245 3246 iframeDoc.addEventListener('click', () => { 3247 this.recordAdClick(placement, { target: iframe }); 3248 }); 3249 } 3250 } 3251 } 3252 } catch (error) { 3253 // Cross-origin iframe, can't access content directly 3254 // Already handled by other methods 3255 } 3256 }); 3257 } 3258 }); 3259 }; 3260 3261 observeIframes(); 3262 setInterval(observeIframes, 2000); 3263 }, 3264 recordAdClick: function(placement, eventData) { 3265 if (this.adPerformance[placement]) { 3266 this.adPerformance[placement].clicked = true; 3267 this.adPerformance[placement].click_count = (this.adPerformance[placement].click_count || 0) + 1; 3268 this.adPerformance[placement].last_click_time = new Date().toISOString(); 3269 } else { 3270 this.adPerformance[placement] = { 3271 clicked: true, 3272 click_count: 1, 3273 last_click_time: new Date().toISOString() 3274 }; 3275 } 3276
3277 const clickDetails = { 3278 timestamp: new Date().toISOString() 3279 }; 3280 3281 if (eventData) { 3282 if (eventData.clientX !== undefined && eventData.clientY !== undefined) { 3283 clickDetails.x = eventData.clientX; 3284 clickDetails.y = eventData.clientY; 3285 } 3286 3287 if (eventData.target) { 3288 clickDetails.target_element = eventData.target.tagName; 3289 clickDetails.target_class = eventData.target.className; 3290 } 3291 3292 if (eventData.messageData) { 3293 clickDetails.message_data = eventData.messageData; 3294 } 3295 3296 if (eventData.navigationType) { 3297 clickDetails.navigation_type = eventData.navigationType;
3298 clickDetails.destination = eventData.destination; 3299 } 3300 } 3301 3302 this.trackAdInteraction(placement, 'click', clickDetails); 3303 3304 if (placement === 'pos_1') { 3305 const adContainer = document.querySelector(`.iqdcontainer[data-placement="${placement}"]`); 3306 if (adContainer) { 3307 const pos1Tiles = adContainer.querySelectorAll('#iqadtile20, #iqadtile21, #iqadtile1'); 3308 3309 // If we have a target element, check if the click was on a specific tile 3310 if (eventData && eventData.target) { 3311 pos1Tiles.forEach(tileElement => { 3312 if (tileElement.contains(eventData.target) || tileElement === eventData.target) { 3313 const tileId = tileElement.id; 3314 const trackingId = this.pos1TileMapping[tileId]; 3315 3316 if (trackingId) { 3317 3318 if (this.adPerformance[trackingId]) { 3319 this.adPerformance[trackingId].clicked = true; 3320 this.adPerformance[trackingId].click_count = (this.adPerformance[trackingId].click_count || 0) + 1; 3321 this.adPerformance[trackingId].last_click_time = new Date().toISOString(); 3322 } else { 3323 this.adPerformance[trackingId] = { 3324 clicked: true, 3325 click_count: 1, 3326 last_click_time: new Date().toISOString() 3327 }; 3328 } 3329
3330 clickDetails.parent_placement = placement; 3331 clickDetails.tile_id = tileId; 3332 this.trackAdInteraction(trackingId, 'click', clickDetails); 3333 } 3334 } 3335 }); 3336 } 3337 } 3338 } 3339 }, 3340 }; 3341 3342 IQDTracker.setupUnloadHandler(); 3343 IQDTracker.setupClickTracking(); 3344 IQDTracker.setupCMPConsentTracking(); 3345 </script>
3345 3346 3347
3347<script> 3348 var winW = window.innerWidth || window.document.documentElement.clientWidth || window.document.body.clientWidth; 3349 var aView = winW > 1279 ? "d" : "m"; 3350 3351 function isDesktop() { 3352 var width = (window.innerWidth > 0) ? window.innerWidth : screen.width; 3353 return width >= 1280; 3354 } 3355 3356 function isMobileOrTablet() { 3357 return !isDesktop(); 3358 } 3359 3360 function isTablet() { 3361 return isMobileOrTablet() && window.outerWidth >= 480 && window.hasOwnProperty('orientation'); 3362 } 3363 3364 function isMobile() { 3365 return isMobileOrTablet() && !isTablet(); 3366 } 3367 3368 function getPlatform() { 3369 if (isDesktop()) { 3370 return 'desktop'; 3371 } 3372 if (isTablet()) { 3373 return 'tablet'; 3374 } 3375 return 'mobile'; 3376 } 3377 3378 function IQSLoader(url) { 3379 var script = document.createElement("script"); 3380 script.type = "text/javascript"; 3381 script.src = url; 3382 document.getElementsByTagName("head")[0].appendChild(script); 3383 } 3384 3385 var iqd_mode = (function() { 3386 var dm = window.location.href.toLowerCase(); 3387 return (dm.indexOf('iqdeployment=') > 1) ? 3388 dm.split('iqdeployment=')[1].split('&')[0] : 'live'; 3389 })(); 3390 3391 if (isDesktop()) { 3392 IQSLoader("https://s3.eu-central-1.amazonaws.com/prod.iqdcontroller.iqdigital/cdn_rollingstone/" + iqd_mode + "/iqadcontroller.js.gz"); 3393 } else { 3394 IQSLoader("https://s3.eu-central-1.amazonaws.com/prod.iqdcontroller.iqdigital/cdn_rollingstone_mob/" + iqd_mode + "/iqadcontroller.js.gz"); 3395 } 3396 </script>
3396 3397 3398
3398<script> 3399 (function () { 3400 window.AdController = { 3401 i: null, 3402 f: false, 3403 n: false, 3404 setPageInfo: function (i) { 3405 window.AdController.i = i; 3406 }, 3407 stage: function () { 3408 window.AdController.s = true; 3409 }, 3410 initialize: function () { 3411 window.AdController.n = true; 3412 }, 3413 render: function (n, c) { 3414 window.AdController.q.push([n, c]); 3415 }, 3416 finalize: function () { 3417 window.AdController.f = true; 3418 }, 3419 ready: function (callback) { 3420 window.AdController.r = callback; 3421 }, 3422 startLoadCycle: function () { 3423 window.AdController.c.push(['startLoadCycle']); 3424 }, 3425 reload: function (p, t) { 3426 window.AdController.c.push(['reload', p, t]); 3427 }, 3428 reinitialize: function (i) { 3429 window.AdController.c.push(['reinitialize', i]); 3430 } 3431 }; 3432 })(); 3433 3434 var cmsObject = {"$handle":"index","level2":"audio","level3":"","level4":"","isWrapperApp":false,"keywords":"audio","tma":"","platform":"desktop"}; 3435 3436 cmsObject.platform = getPlatform(); 3437 if (window.IQDTracker) { 3438 IQDTracker.logCmsConfig(cmsObject); 3439 } 3440 if (!AdController._initialized) { 3441 AdController.setPageInfo(cmsObject); 3442 try { 3443 AdController.stage(); 3444 } catch (e) {} 3445 AdController.initialize(); 3446 } else { 3447 (function checkDOMReadyState(c) { 3448 try { 3449 if (AdController.getRenderController().isReady()) { 3450 AdController.reinitialize(cmsObject); 3451 } 3452 } catch (e) { 3453 if (c < 50) { 3454 c++; 3455 setTimeout(function() { 3456 checkDOMReadyState(c); 3457 }, 100); 3458 } 3459 } 3460 })(0); 3461 } 3462 </script>
3462 3463 3464
3464<script> 3465 if (window.AdController) { 3466 const originalRender = window.AdController.render; 3467 window.AdController.render = function(placement, callback) { 3468 const startTime = performance.now(); 3469 3470 if (window.IQDTracker) { 3471 window.IQDTracker.trackAdPerformance(placement, { 3472 requestTime: new Date().toISOString(), 3473 status: 'requested' 3474 }); 3475 } 3476 const wrappedCallback = function(success, data) { 3477 const loadTime = performance.now() - startTime; 3478 3479 if (window.IQDTracker) { 3480 window.IQDTracker.trackAdPerformance(placement, { 3481 fillStatus: success ? 'filled' : 'unfilled', 3482 loadTimeMs: loadTime, 3483 adData: success ? data : null, 3484 status: success ? 'loaded' : 'failed' 3485 }); 3486 } 3487 if (typeof callback === 'function') { 3488 callback(success, data); 3489 } 3490 }; 3491 return originalRender.call(this, placement, wrappedCallback); 3492 }; 3493 } 3494 </script>
3494 3495 3496
3497<script> 3498 const setupEnhancedObserver = function() { 3499 const observer = new IntersectionObserver((entries) => { 3500 entries.forEach(entry => { 3501 const container = entry.target; 3502 const placement = container.dataset.placement; 3503 3504 if (IQDTracker.initialLogSent) { 3505 if (entry.isIntersecting) { 3506 IQDTracker.trackViewportEntry(placement); 3507 3508 if (!container.dataset.loaded && 3509 IQDTracker.adPositions.belowFold && 3510 IQDTracker.adPositions.belowFold.includes(placement)) { 3511 AdController.render(placement); 3512 container.dataset.loaded = 'true'; 3513 } 3514 } else { 3515 IQDTracker.trackViewportExit(placement); 3516 } 3517 } 3518 }); 3519 }, { 3520 threshold: [0, 0.25, 0.5, 0.75, 1], 3521 rootMargin: '50px' 3522 }); 3523 document.querySelectorAll('.iqdcontainer').forEach(container => { 3524 observer.observe(container); 3525 }); 3526 3527 return observer; 3528 }; 3529 3530 document.addEventListener('DOMContentLoaded', function() { 3531 IQDTracker.initializeTracking(); 3532 IQDTracker.initializePlacements(); 3533 const observer = setupEnhancedObserver(); 3534 setTimeout(() => { 3535 IQDTracker.captureInitialViewportState(); 3536 }, 100); 3537 setTimeout(setupAdInteractionTracking, 1500); 3538 3539 setTimeout(() => { 3540 if (window.IQDTracker && typeof window.IQDTracker.logAdContainers === 'function') { 3541 window.IQDTracker.logAdContainers(); 3542 } 3543 3544 if (window.IQDTracker) { 3545 window.IQDTracker.monitorCreativeChanges(); 3546 window.IQDTracker.trackAdPopulation(); 3547 3548 if (window.location.search.includes('iqdebug=true')) { 3549 window.IQDTracker.debugMode = true; 3550 3551 const originalLog = window.IQDTracker.log; 3552 window.IQDTracker.log = function(type, message, data) { 3553 return originalLog.call(this, type, message, data); 3554 }; 3555 } 3556 } 3557 }, 1000); 3558 }); 3559 const setupAdInteractionTracking = function() { 3560 document.querySelectorAll('.iqdcontainer').forEach(container => { 3561 const placement = container.dataset.placement; 3562 3563 container.addEventListener('click', (event) => { 3564 if (window.IQDTracker) { 3565 window.IQDTracker.trackAdInteraction(placement, 'click', { 3566 clientX: event.clientX, 3567 clientY: event.clientY, 3568 target: event.target.tagName 3569 }); 3570 } 3571 }); 3572 }); 3573 }; 3574 </script>
3574 3575 3576 <link rel="alternate" type="application/rss+xml" title="Rolling Stone » Feed" href="https://www.rollingstone.de/feed/" /> 3577<link rel="alternate" type="application/rss+xml" title="Rolling Stone » Kommentar-Feed" href="https://www.rollingstone.de/comments/feed/" />
3578<script>console.log("[CP-Tealium] Prevented normal Tealium initialization, waiting for ContentPass authentication");</script>
3578<link rel="alternate" title="oEmbed (JSON)" type="application/json+oembed" href="https://www.rollingstone.de/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fwww.rollingstone.de%2Faudio-post%2Fsecond-song-von-neil-young-ein-spaetes-meisterwerk%2F" /> 3579<link rel="alternate" title="oEmbed (XML)" type="text/xml+oembed" href="https://www.rollingstone.de/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fwww.rollingstone.de%2Faudio-post%2Fsecond-song-von-neil-young-ein-spaetes-meisterwerk%2F&format=xml" /> 3580 3581 <style id="wp-img-auto-sizes-contain-inline-css"> 3582img:is([sizes=auto i],[sizes^="auto," i]){contain-intrinsic-size:3000px 1500px} 3583/*# sourceURL=wp-img-auto-sizes-contain-inline-css */ 3584</style> 3585<style id="wp-emoji-styles-inline-css"> 3586 3587 img.wp-smiley, img.emoji { 3588 display: inline !important; 3589 border: none !important; 3590 box-shadow: none !important; 3591 height: 1em !important; 3592 width: 1em !important; 3593 margin: 0 0.07em !important; 3594 vertical-align: -0.1em !important; 3595 background: none !important; 3596 padding: 0 !important; 3597 } 3598/*# sourceURL=wp-emoji-styles-inline-css */ 3599</style> 3600 3601 3602<link rel='stylesheet' id='asmb-advertorial-builder-styles-css' href='https://www.rollingstone.de/wp-content/plugins/asmb-advertorial-builder/css/style-rs.css?ver=1.0.0' media='all' /> 3603<link rel='stylesheet' id='custom-ad-banner-css-css' href='https://www.rollingstone.de/wp-content/plugins/cms-banner-article/css/cms-article-banner.css?ver=1.0' media='all' /> 3604<link rel='stylesheet' id='contact-form-7-css' href='https://www.rollingstone.de/wp-content/plugins/contact-form-7/includes/css/styles.css?ver=6.1.7' media='all' /> 3605<link rel='stylesheet' id='embed-consent-css' href='https://www.rollingstone.de/wp-content/plugins/ms-wppl-embed-consent/dist/styles/embed-consent.min.css?ver=1790680314' media='all' /> 3606<link rel='stylesheet' id='wp-bootstrap-starter-bootstrap-css-css' href='https://www.rollingstone.de/wp-content/themes/RS-Theme-2023/inc/assets/css/bootstrap.min.css?ver=7.1' media='all' /> 3607<link rel='stylesheet' id='wp-bootstrap-starter-style-css' href='https://www.rollingstone.de/wp-content/themes/RS-Theme-2023/style.css?ver=1790680314' media='all' /> 3608<link rel='stylesheet' id='atkp-styles-css' href='https://www.rollingstone.de/wp-content/plugins/affiliate-toolkit-starter/dist/style.css?ver=3.9.0' media='all' /> 3609<style id="atkp-styles-inline-css"> 3610/* Begin (global) */ 3611.atkp-container a, .atkp-container a:visited { color: #2271b1} 3612.atkp-container a:hover { color: #111} 3613 .atkp-moreoffersinfo a, .atkp-moreoffersinfo a:visited { color: #2271b1} .atkp-moreoffersinfo a:hover { color: #2271b1;} 3614.atkp-listprice { color: #808080 !important; } 3615.atkp-saleprice { color: #00000 !important; } 3616.atkp-savedamount { color: #8b0000 !important; } 3617.atkp-ribbon span { background: #E47911 !important; } 3618.atkp-box { background-color:#ffff; border: 1px solid #ececec; border-radius: 5px; color: #111 } 3619.atkp-box .atkp-predicate-highlight1, .atkp-box .atkp-predicate-highlight2, .atkp-box .atkp-predicate-highlight3 {border-radius: 5px 5px 0 0;} 3620.atkp-button { 3621 margin: 0 auto; 3622 padding: 5px 15px;font-size:14px; 3623 display: inline-block; 3624 background-color: #f0c14b; 3625 border: 1px solid #f0c14b; 3626 color: #111 !important; 3627 font-weight: 400; 3628 -webkit-border-radius: 5px; 3629 border-radius: 5px; 3630 -webkit-transition: all 0.3s ease-in-out; 3631 -moz-transition: all 0.3s ease-in-out; 3632 transition: all 0.3s ease-in-out; 3633 text-decoration: none !important; 3634 } 3635 3636 .atkp-button:hover { 3637 background-color: #f7dfa5; 3638 text-decoration: none; 3639 } 3640.atkp-secondbutton { 3641 margin: 0 auto; 3642 padding: 5px 15px; 3643 display: inline-block; 3644 background-color: #f0c14b; 3645 border: 1px solid #f0c14b; 3646 color: #333333 !important; 3647 font-weight: 400; 3648 -webkit-border-radius: 5px; 3649 border-radius: 5px; 3650 -webkit-transition: all 0.3s ease-in-out; 3651 -moz-transition: all 0.3s ease-in-out; 3652 transition: all 0.3s ease-in-out; 3653 text-decoration: none !important; 3654 } 3655 3656 .atkp-secondbutton:hover { 3657 background-color: #f7dfa5; 3658 text-decoration: none; 3659 } 3660 .atkp-producttable-button a { 3661 width: 100%; 3662 padding-left: 0px; 3663 padding-right: 0px; 3664 } 3665/* End (global) */ 3666 3667/* Begin (#3013275) */ 3668.atkp-template-3013275 .atkp-title { 3669 color: #000; 3670} 3671 3672.affiliate-reviews-button-container { 3673 display: flex; 3674 flex-direction: column;
3675 align-items: flex-start; 3676} 3677 3678.main-button-wrapper { 3679 margin-bottom: 0.5rem; 3680 width: 100%; 3681} 3682 3683.asmb-button-tertiary { 3684 display: inline-block; 3685} 3686 3687.weitere-angebote-wrapper { 3688 position: relative; 3689 display: block; 3690} 3691 3692.weitere-angebote-toggle { 3693 position: relative; 3694 display: inline-flex; 3695 flex-direction: column; 3696 cursor: pointer; 3697 color: #0073aa; 3698 text-decoration: underline; 3699} 3700 3701.weitere-angebote-toggle:hover .asmb-moreoffers-flyout, 3702.weitere-angebote-toggle:focus-within .asmb-moreoffers-flyout { 3703 display: block; 3704} 3705 3706 3707.asmb-moreoffers-flyout { 3708 display: none; 3709 position: absolute; 3710 top: 100%; 3711 left: 0; 3712 z-index: 20; 3713 background: #fff; 3714 border: 1px solid #ccc; 3715 padding: 0.75rem 1rem; 3716 min-width: 420px; 3717 box-shadow: 0 2px 6px rgba(0,0,0,0.2); 3718 pointer-events: auto; 3719} 3720 3721.asmb-moreoffers-flyout ul { 3722 list-style: none; 3723 padding: 0; 3724 margin: 0; 3725} 3726 3727.asmb-moreoffers-flyout li { 3728 margin: 0.25rem 0; 3729} 3730 3731.asmb-alt-offer { 3732 text-decoration: none; 3733 color: #000; 3734 font-weight: 500; 3735} 3736 3737.asmb-alt-offer:hover { 3738 text-decoration: underline; 3739} 3740 3741.asmb-offers-list { 3742 display: flex; 3743 flex-direction: column; 3744 gap: 0; 3745} 3746 3747.asmb-offer-row { 3748 display: flex;
3749 align-items: flex-start; 3750 justify-content: space-between; 3751 padding: 0.5rem 0.75rem; 3752 border-bottom: 1px solid #eee; 3753 transition: background 0.2s ease; 3754 gap: 1rem; 3755} 3756 3757.asmb-offer-row:last-child { 3758 border-bottom: none; 3759} 3760 3761.asmb-offer-row a { 3762 display: flex; 3763 justify-content: space-between; 3764 align-items: center; 3765 width: 100%; 3766 text-decoration: none; 3767 color: #000; 3768} 3769 3770.asmb-offer-shop { 3771 display: flex; 3772 align-items: center; 3773 flex: 1; 3774} 3775 3776.asmb-offer-shop img { 3777 max-height: 18px; 3778 width: auto; 3779 vertical-align: middle; 3780} 3781 3782.asmb-offer-details { 3783 display: flex; 3784 flex-direction: column; 3785 align-items: flex-start; 3786 text-align: left; 3787 flex: 1; 3788 min-width: 0; 3789} 3790 3791.asmb-offer-title { 3792 font-style: italic; 3793 font-size: 0.875rem; 3794 color: #333; 3795 margin-bottom: 0.25rem; 3796 word-break: break-word; 3797 white-space: normal; 3798 overflow-wrap: break-word; 3799} 3800 3801.asmb-offer-price { 3802 font-weight: bold; 3803 font-size: 1rem; 3804 white-space: nowrap; 3805} 3806 3807.asmb-offer-row:hover { 3808 background-color: #f9f9f9; 3809} 3810 3811/* End (#3013275) */ 3812 3813/* Begin (#3007301) */ 3814/* Ensure button and toggle line are stacked vertically */ 3815.affiliate-reviews-button-container { 3816 display: flex; 3817 flex-direction: column; 3818 align-items: flex-start; 3819} 3820 3821/* Optional: make button full-width or keep inline */ 3822.main-button-wrapper { 3823 margin-bottom: 0.5rem; 3824 width: 100%; 3825} 3826 3827.asmb-button-tertiary { 3828 display: inline-block; 3829} 3830 3831/* Toggle line */ 3832.weitere-angebote-wrapper { 3833 position: relative; 3834 display: block; 3835} 3836 3837/* Line styling */ 3838.weitere-angebote-toggle { 3839 position: relative; 3840 display: inline-flex; 3841 flex-direction: column; 3842 cursor: pointer; 3843 color: #0073aa; 3844 text-decoration: underline; 3845} 3846 3847/* Flyout logic: only show when hovering the text */ 3848.weitere-angebote-toggle:hover .asmb-moreoffers-flyout, 3849.weitere-angebote-toggle:focus-within .asmb-moreoffers-flyout { 3850 display: block; 3851} 3852 3853 3854.asmb-moreoffers-flyout { 3855 display: none; 3856 position: absolute; 3857 top: 100%; 3858 left: 0; 3859 z-index: 20; 3860 background: #fff; 3861 border: 1px solid #ccc; 3862 padding: 0.75rem 1rem; 3863 min-width: 420px; 3864 box-shadow: 0 2px 6px rgba(0,0,0,0.2); 3865 pointer-events: auto; 3866} 3867 3868.asmb-moreoffers-flyout ul { 3869 list-style: none; 3870 padding: 0; 3871 margin: 0; 3872} 3873 3874.asmb-moreoffers-flyout li { 3875 margin: 0.25rem 0; 3876} 3877 3878.asmb-alt-offer { 3879 text-decoration: none; 3880 color: #000; 3881 font-weight: 500; 3882} 3883 3884.asmb-alt-offer:hover { 3885 text-decoration: underline; 3886} 3887 3888/* Styled offers list inside the flyout */ 3889.asmb-offers-list { 3890 display: flex; 3891 flex-direction: column; 3892 gap: 0; 3893} 3894 3895/* One offer row */ 3896.asmb-offer-row { 3897 display: flex;
3898 align-items: flex-start; 3899 justify-content: space-between; 3900 padding: 0.5rem 0.75rem; 3901 border-bottom: 1px solid #eee; 3902 transition: background 0.2s ease; 3903 gap: 1rem; 3904} 3905 3906.asmb-offer-row:last-child { 3907 border-bottom: none; 3908} 3909 3910.asmb-offer-row a { 3911 display: flex; 3912 justify-content: space-between; 3913 align-items: center; 3914 width: 100%; 3915 text-decoration: none; 3916 color: #000; 3917} 3918 3919/* Left: shop logo */ 3920.asmb-offer-shop { 3921 display: flex; 3922 align-items: center; 3923 flex: 1; 3924} 3925 3926.asmb-offer-shop img { 3927 max-height: 18px; 3928 width: auto; 3929 vertical-align: middle; 3930} 3931 3932.asmb-offer-details { 3933 display: flex; 3934 flex-direction: column; 3935 align-items: flex-start; 3936 text-align: left; 3937 flex: 1; 3938 min-width: 0; 3939} 3940 3941/* Title styling (above the price) */ 3942.asmb-offer-title { 3943 font-style: italic; 3944 font-size: 0.875rem; 3945 color: #333; 3946 margin-bottom: 0.25rem; 3947 word-break: break-word; /* Break long words */ 3948 white-space: normal; /* Allow wrapping */ 3949 overflow-wrap: break-word; /* Safely wrap */ 3950} 3951 3952/* Adjust existing price styling */ 3953.asmb-offer-price { 3954 font-weight: bold; 3955 font-size: 1rem; 3956 white-space: nowrap; 3957} 3958 3959/* Hover effect */ 3960.asmb-offer-row:hover { 3961 background-color: #f9f9f9; 3962} 3963 3964/* End (#3007301) */ 3965 3966/* Begin (#2817927) */ 3967/* Ensure button and toggle line are stacked vertically */ 3968.affiliate-reviews-button-container { 3969 display: flex; 3970 flex-direction: column; 3971 align-items: flex-start; 3972} 3973 3974/* Optional: make button full-width or keep inline */ 3975.main-button-wrapper { 3976 margin-bottom: 0.5rem; 3977 width: 100%; 3978} 3979 3980.asmb-button-tertiary { 3981 display: inline-block; 3982} 3983 3984/* Toggle line */ 3985.weitere-angebote-wrapper { 3986 position: relative; 3987 display: block; 3988} 3989 3990/* Line styling */ 3991.weitere-angebote-toggle { 3992 position: relative; 3993 display: inline-flex; 3994 flex-direction: column; 3995 cursor: pointer; 3996 color: #0073aa; 3997 text-decoration: underline; 3998} 3999 4000/* Flyout logic: only show when hovering the text */ 4001.weitere-angebote-toggle:hover .asmb-moreoffers-flyout, 4002.weitere-angebote-toggle:focus-within .asmb-moreoffers-flyout { 4003 display: block; 4004} 4005 4006 4007.asmb-moreoffers-flyout { 4008 display: none; 4009 position: absolute; 4010 top: 100%; 4011 left: 0; 4012 z-index: 20; 4013 background: #fff; 4014 border: 1px solid #ccc; 4015 padding: 0.75rem 1rem; 4016 min-width: 420px; 4017 box-shadow: 0 2px 6px rgba(0,0,0,0.2); 4018 pointer-events: auto; 4019} 4020 4021.asmb-moreoffers-flyout ul { 4022 list-style: none; 4023 padding: 0; 4024 margin: 0; 4025} 4026 4027.asmb-moreoffers-flyout li { 4028 margin: 0.25rem 0; 4029} 4030 4031.asmb-alt-offer { 4032 text-decoration: none; 4033 color: #000; 4034 font-weight: 500; 4035} 4036 4037.asmb-alt-offer:hover { 4038 text-decoration: underline; 4039} 4040 4041/* Styled offers list inside the flyout */ 4042.asmb-offers-list { 4043 display: flex; 4044 flex-direction: column; 4045 gap: 0; 4046} 4047 4048/* One offer row */ 4049.asmb-offer-row { 4050 display: flex;
4051 align-items: flex-start; 4052 justify-content: space-between; 4053 padding: 0.5rem 0.75rem; 4054 border-bottom: 1px solid #eee; 4055 transition: background 0.2s ease; 4056 gap: 1rem; 4057} 4058 4059.asmb-offer-row:last-child { 4060 border-bottom: none; 4061} 4062 4063.asmb-offer-row a { 4064 display: flex; 4065 justify-content: space-between; 4066 align-items: center; 4067 width: 100%; 4068 text-decoration: none; 4069 color: #000; 4070} 4071 4072/* Left: shop logo */ 4073.asmb-offer-shop { 4074 display: flex; 4075 align-items: center; 4076 flex: 1; 4077} 4078 4079.asmb-offer-shop img { 4080 max-height: 18px; 4081 width: auto; 4082 vertical-align: middle; 4083} 4084 4085.asmb-offer-details { 4086 display: flex; 4087 flex-direction: column; 4088 align-items: flex-start; 4089 text-align: left; 4090 flex: 1; 4091 min-width: 0; 4092} 4093 4094/* Title styling (above the price) */ 4095.asmb-offer-title { 4096 font-style: italic; 4097 font-size: 0.875rem; 4098 color: #333; 4099 margin-bottom: 0.25rem; 4100 word-break: break-word; /* Break long words */ 4101 white-space: normal; /* Allow wrapping */ 4102 overflow-wrap: break-word; /* Safely wrap */ 4103} 4104 4105/* Adjust existing price styling */ 4106.asmb-offer-price { 4107 font-weight: bold; 4108 font-size: 1rem; 4109 white-space: nowrap; 4110} 4111 4112/* Hover effect */ 4113.asmb-offer-row:hover { 4114 background-color: #f9f9f9; 4115} 4116 4117/* End (#2817927) */ 4118 4119/*# sourceURL=atkp-styles-inline-css */ 4120</style> 4121<link rel='stylesheet' id='wp-paginate-css' href='https://www.rollingstone.de/wp-content/plugins/wp-paginate/css/wp-paginate.css?ver=2.2.6' media='screen' />
4122<script id="jquery-core-js" src="https://www.rollingstone.de/wp-includes/js/jquery/jquery.min.js?ver=3.7.1"></script>
vendor: 1 bytes, line 4122
4122
4123<script id="jquery-migrate-js" src="https://www.rollingstone.de/wp-includes/js/jquery/jquery-migrate.min.js?ver=3.4.1"></script>
vendor: 1 bytes, line 4123
4123
4124<script id="embed-consent-js-extra"> 4125var embedConsentLocalizeData = {"embedPurposesIds":{"social":{"id":"6857e3f218ed9345125a6b81"},"personalised-ads-profile":{"id":"5e87957425406127fbb306e0"},"store-information":{"id":"5e87957425406127fbb306ea"},"political-ad":{"id":"691456e1c4e953f5e15e33c1"}},"embedProvidersIds":{"apple":"5e7ad27bbc0b7f163bab59e0","amazon":"6436c0caecd808049c69ac2b","deezer":"642e9d19836558e89372481f","facebook":"5ee91b9593fc094b59242e25","instagram":"5e717c8e69966540e4554f05","mixcloud":"5e7ad2a66ec88916348949d1","soundcloud":"5e7179e49a0b5040d5750812","spotify":"5e7f6927b8e05c111d01b40f","twitch":"5ec85c9cb8e05c4a2002f42e","threads":"64f98e53f82fce06c7570736","twitter":"5e71760b69966540e4554f01","vimeo":"5eac148d4bfee33e7280d13b","youtube":"5e7ac3fae30e7d1bc1ebf5e8","megaphone":"6038246685166e27b7322911","coolcaptcha":"6698d32a15d4970501a7e1ad","simplecast":"677e8c15097951070f44b335","tiktok":"66bf0638533c8806ed124849"},"privacyManagerId":"1319079","privacyManagerRevokeId":"1319080","platform":"bz","platformGroup":"bz","politicalAdPurposeId":"691456e1c4e953f5e15e33c1"}; 4126//# sourceURL=embed-consent-js-extra 4127</script>
vendor: 1 bytes, line 4127
4127
4128<script id="embed-consent-js" src="https://www.rollingstone.de/wp-content/plugins/ms-wppl-embed-consent/dist/embed-consent.min.js?ver=1790680314"></script>
vendor: 1 bytes, line 4128
4128
4129<script id="theme-main-js" src="https://www.rollingstone.de/wp-content/themes/RS-Theme-2023/main.js?ver=1790680314"></script>
4129 4130<link rel="https://api.w.org/" href="https://www.rollingstone.de/wp-json/" /><link rel="EditURI" type="application/rsd+xml" title="RSD" href="https://www.rollingstone.de/xmlrpc.php?rsd" /> 4131<meta name="generator" content="WordPress 7.1" /> 4132<link rel='shortlink' href='https://www.rollingstone.de/?p=3193085' /> 4133<!-- Stream WordPress user activity plugin v4.3.0 --> 4134<link rel="pingback" href="https://www.rollingstone.de/xmlrpc.php"> <style type="text/css"> 4135 #page-sub-header { background: #fff; } 4136 </style> 4137
4137<script>window.adLoggingNonce = "7b6d8aed6f";</script>
4137<link rel="icon" href="https://www.rollingstone.de/wp-content/uploads/2023/11/cropped-favicon-rs-2023-32x32.png" sizes="32x32" /> 4138<link rel="icon" href="https://www.rollingstone.de/wp-content/uploads/2023/11/cropped-favicon-rs-2023-192x192.png" sizes="192x192" /> 4139<link rel="apple-touch-icon" href="https://www.rollingstone.de/wp-content/uploads/2023/11/cropped-favicon-rs-2023-180x180.png" /> 4140<meta name="msapplication-TileImage" content="https://www.rollingstone.de/wp-content/uploads/2023/11/cropped-favicon-rs-2023-270x270.png" />
4141<script type="text/javascript" id="nicole"> 4142 var utag_data={ 4143 "page_id" : "rs_3193085", 4144"page_index" : 1, 4145"page_age" : 7, 4146"page_platform" : "desktop", 4147"page_path" : "audio-post\/second-song-von-neil-young-ein-spaetes-meisterwerk", 4148"page_type" : "audio-post", 4149"page_channel1" : "audio-post", 4150"page_channel2" : "second-song-von-neil-young-ein-spaetes-meisterwerk", 4151"page_channel3" : "", 4152"page_pathname4" : "", 4153"page_pathname5" : "", 4154"page_anchor" : "second-song-von-neil-young-ein-spaetes-meisterwerk", 4155"page_kicker" : "Ein alter Mann blickt auf sein Leben zur\u00fcck, begleitet von einer kongenialen Band", 4156"page_headline" : "\u201eSecond Song\u201c von Neil Young: Ein sp\u00e4tes Meisterwerk?", 4157"page_publication_date" : "2026-09-25", 4158"page_publication_time" : "06:32", 4159"page_modification_date" : "2026-09-25", 4160"page_modification_time" : "06:32", 4161"page_estimatedreadingtime" : 0, 4162"page_word_count" : 58, 4163"page_language" : "de_DE", 4164"page_taxonomy" : ["Neil Young","Neil Young and the Chrome Hearts","Chrome Hearts","Second Song"], 4165"page_taxonomy_genre" : false, 4166"page_taxonomy_categories" : ["Musik","News"], 4167"page_is_live_article" : false, 4168"page_is_evergreen" : false, 4169"page_has_ads" : true, 4170"page_has_affiliate" : false, 4171"page_has_embeds" : true, 4172"page_has_gallery" : false, 4173"page_has_iat" : false, 4174"page_has_image_opener" : true, 4175"page_has_partnerwidget" : false, 4176"page_has_taboola" : true, 4177"page_has_teaser_rotation" : false, 4178"page_has_video" : false, 4179"page_has_video_opener" : false, 4180"page_is_us_partner_content" : "", 4181 4182 }; 4183 </script>
4183</head> 4184 4185 4186<body class="wp-singular audio-post-template-default single single-audio-post postid-3193085 wp-theme-RS-Theme-2023 group-blog"> 4187 4188 4189 <div id="page" class="site asmb-page-width"> 4190 <div id="content"> 4191 4192 <!-- Ad pos_header desktop --> 4193 <div class="asmb-iqd-full-width asmb-iqd-desktop"> 4194 <div class="iqdcontainer" data-placement="pos_header" data-device="desktop"></div> 4195 </div> 4196 <!-- End Ad pos_header desktop --> 4197 4198 <!-- Ad pos_header mobile --> 4199 <div class="asmb-iqd-full-width asmb-iqd-mobile"> 4200 <div class="iqdcontainer" data-placement="pos_header" data-device="mobile"></div> 4201 </div> 4202 <!-- End Ad pos_header mobile --> 4203 <!-- Ad sticky Banner --> 4204 <div class="asmb-sticker-header-ad-helper"> 4205 <div class="asmb-iqd-sticky-header asmb-iqd-full-width asmb-iqd-mobile"> 4206 <div class="iqdcontainer" data-placement="pos_header_out" data-device="mobile"></div> 4207 </div> 4208 </div> 4209 <header class="asmb-header-container"> 4210 <!-- End Ad sticky Banner --> 4211 <div class="asmb-navbar-container"> 4212 <nav class="asmb-navbar-mega" aria-label="Hauptnavigation Desktop"> 4213 <div class="asmb-navbar-top-container"> 4214 <div class="asmb-navbar-top-logo-container"> 4215 <a href="https://www.rollingstone.de/" aria-label="Zurück zur ROLLING STONE Startseite"> 4216 <img src="https://www.rollingstone.de/wp-content/uploads/2025/03/rs-logo-2025.svg" alt="Rolling Stone"> 4217 </a> 4218 </div> 4219 </div> 4220 <div class="asmb-navbar-bottom-container asmb-double-border-top asmb-border-bottom"> 4221 <div class="asmb-navbar-menu-container"> 4222 <div class="asmb-navbar-main-menu"> 4223 <div class="menu-main-container"><ul id="menu-main" class="menu"><li id="menu-item-2671231" class="menu-item menu-item-type-taxonomy menu-item-object-category current-audio-post-ancestor current-menu-parent current-audio-post-parent menu-item-has-children menu-item-2671231"><a href="https://www.rollingstone.de/musik/">Musik</a><span class="asmb-navbar-arrows"></span> 4224<ul class="sub-menu"> 4225 <li id="menu-item-2672961" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-2672961"><a href="https://www.rollingstone.de/musik/titelstorys/">Titelstorys</a><span class="asmb-navbar-arrows"></span></li> 4226 <li id="menu-item-2671237" class="menu-item menu-item-type-taxonomy menu-item-object-category current-audio-post-ancestor current-menu-parent current-audio-post-parent menu-item-2671237"><a href="https://www.rollingstone.de/musik/musik-news/">News</a><span class="asmb-navbar-arrows"></span></li> 4227 <li id="menu-item-2671239" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-2671239"><a href="https://www.rollingstone.de/musik/musik-features/">Features</a><span class="asmb-navbar-arrows"></span></li> 4228 <li id="menu-item-2671275" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2671275"><a href="/reviews/">Reviews</a><span class="asmb-navbar-arrows"></span></li> 4229 <li id="menu-item-2671235" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-2671235"><a href="https://www.rollingstone.de/musik/musik-listen/">Rankings</a><span class="asmb-navbar-arrows"></span></li> 4230</ul> 4231</li> 4232<li id="menu-item-2671241" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-has-children menu-item-2671241"><a href="https://www.rollingstone.de/film-serie/">Film & Serie</a><span class="asmb-navbar-arrows"></span> 4233<ul class="sub-menu"> 4234 <li id="menu-item-2671245" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-2671245"><a href="https://www.rollingstone.de/film-serie/film-serien-news/">News</a><span class="asmb-navbar-arrows"></span></li> 4235 <li id="menu-item-2672963" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-2672963"><a href="https://www.rollingstone.de/film-serie/film-serien-features/">Features</a><span class="asmb-navbar-arrows"></span></li> 4236 <li id="menu-item-2671243" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-2671243"><a href="https://www.rollingstone.de/film-serie/film-serien-reviews/">Reviews</a><span class="asmb-navbar-arrows"></span></li> 4237 <li id="menu-item-2671247" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-2671247"><a href="https://www.rollingstone.de/film-serie/film-serien-listen/">Rankings</a><span class="asmb-navbar-arrows"></span></li> 4238</ul> 4239</li> 4240<li id="menu-item-2671249" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-has-children menu-item-2671249"><a href="https://www.rollingstone.de/kultur-politik/">Kultur & Politik</a><span class="asmb-navbar-arrows"></span> 4241<ul class="sub-menu"> 4242 <li id="menu-item-2671251" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-2671251"><a href="https://www.rollingstone.de/kultur-politik/kultur-politik-features/">Features</a><span class="asmb-navbar-arrows"></span></li> 4243 <li id="menu-item-2671253" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-2671253"><a href="https://www.rollingstone.de/kultur-politik/kultur-politik-bucher/">Bücher</a><span class="asmb-navbar-arrows"></span></li> 4244</ul> 4245</li> 4246<li id="menu-item-2671255" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-has-children menu-item-2671255"><a href="https://www.rollingstone.de/meinung/">Meinung</a><span class="asmb-navbar-arrows"></span> 4247<ul class="sub-menu"> 4248 <li id="menu-item-2671257" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-2671257"><a href="https://www.rollingstone.de/meinung/meinung-kolumnen/">Kolumnen</a><span class="asmb-navbar-arrows"></span></li> 4249 <li id="menu-item-2671259" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2671259"><a href="/wohnzimmer">Wohnzimmer</a><span class="asmb-navbar-arrows"></span></li> 4250</ul> 4251</li> 4252<li id="menu-item-2671261" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-has-children menu-item-2671261"><a href="https://www.rollingstone.de/live/">Live</a><span class="asmb-navbar-arrows"></span> 4253<ul class="sub-menu"> 4254 <li id="menu-item-2671265" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-2671265"><a href="https://www.rollingstone.de/live/live-konzerte/">Konzerte</a><span class="asmb-navbar-arrows"></span></li> 4255 <li id="menu-item-2671267" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-2671267"><a href="https://www.rollingstone.de/live/live-festivals/">Festivals</a><span class="asmb-navbar-arrows"></span></li> 4256 <li id="menu-item-2671263" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-2671263"><a href="https://www.rollingstone.de/live/live-galerien/">Galerien</a><span class="asmb-navbar-arrows"></span></li> 4257 <li id="menu-item-2671269" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2671269"><a href="/alle-konzerte-in/">Tourdaten</a><span class="asmb-navbar-arrows"></span></li> 4258 <li id="menu-item-2841593" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-2841593"><a href="https://www.rollingstone.de/live/rs-praesentiert/">RS präsentiert</a><span class="asmb-navbar-arrows"></span></li> 4259 <li id="menu-item-2945367" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2945367"><a target="_blank" href="https://rollingstone-beach.de/de/">RS Beach</a><span class="asmb-navbar-arrows"></span></li> 4260 <li id="menu-item-2714745" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2714745"><a target="_blank" href="https://rollingstone.reservix.de/">Ticket-Shop</a><span class="asmb-navbar-arrows"></span></li> 4261</ul> 4262</li> 4263<li id="menu-item-2671271" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2671271"><a href="/video/">Video</a><span class="asmb-navbar-arrows"></span></li> 4264<li id="menu-item-2671273" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2671273"><a href="/audio/">Audio</a><span class="asmb-navbar-arrows"></span></li> 4265<li id="menu-item-2671287" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-has-children menu-item-2671287"><a href="#">Mehr</a><span class="asmb-navbar-arrows"></span> 4266<ul class="sub-menu"> 4267 <li id="menu-item-2671283" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-2671283"><a href="https://www.rollingstone.de/rs-empfiehlt/">RS Empfiehlt</a><span class="asmb-navbar-arrows"></span></li> 4268 <li id="menu-item-2671285" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2671285"><a target="_blank" href="https://www.musik-magazine.de/rolling-stone-kat/shop/">Magazin-Shop</a><span class="asmb-navbar-arrows"></span></li> 4269 <li id="menu-item-3057739" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-3057739"><a href="https://www.rollingstone.de/kooperationen/">Kooperationen</a><span class="asmb-navbar-arrows"></span></li> 4270</ul> 4271</li> 4272<li id="menu-item-3185679" class="typo-color-primary menu-strong menu-item menu-item-type-custom menu-item-object-custom menu-item-3185679"><a target="_blank" href="https://www.musik-magazine.de/rollingstone">Abo</a><span class="asmb-navbar-arrows"></span></li> 4273</ul></div> </div> 4274 </div> 4275 <button class="asmb-search-bar-icon" aria-label="Suchformular öffnen"><i class="icon-magnifying-glass"></i></button> 4276 </div> 4277 </nav> 4278 <nav class="asmb-navbar-small" aria-label="Hauptnavigation Desktop angepinnt und Mobil"> 4279 <div class="asmb-navbar-bottom-container asmb-double-border-top asmb-border-bottom"> 4280 <div class="asmb-navbar-icon-container"> 4281 <button class="asmb-burger-button" aria-label="Hauptnavigation öffnen"> 4282 <i class="icon-bars"></i> 4283 <i class="icon-xmark is-hidden"></i> 4284 </button> 4285 <button class="asmb-search-bar-icon" aria-label="Suchformular öffnen"> 4286 <i class="icon-magnifying-glass"></i> 4287 </button> 4288 </div> 4289 <a class="asmb-navbar-small-logo-container" aria-label="Zurück zur ROLLING STONE Startseite" href="https://www.rollingstone.de"> 4290 <img class="asmb-navbar-small-logo" src="https://www.rollingstone.de/wp-content/themes/RS-Theme-2023/images/RS-Logo-2025-small.svg" alt="ROLLING STONE Deutschland L
4290ogo"> 4291 </a> 4292 </div> 4293 <div class="asmb-navbar-menu-container"> 4294 <div class="asmb-navbar-main-menu"> 4295 <div class="asmb-navbar-main-menu-helper-container"> 4296 <div class="asmb-navbar-main-menu-helper"> 4297 <div class="menu-main-container"><ul id="menu-main-1" class="menu"><li class="menu-item menu-item-type-taxonomy menu-item-object-category current-audio-post-ancestor current-menu-parent current-audio-post-parent menu-item-has-children menu-item-2671231"><a href="https://www.rollingstone.de/musik/">Musik</a> 4298<ul class="sub-menu"> 4299 <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-2672961"><a href="https://www.rollingstone.de/musik/titelstorys/">Titelstorys</a></li> 4300 <li class="menu-item menu-item-type-taxonomy menu-item-object-category current-audio-post-ancestor current-menu-parent current-audio-post-parent menu-item-2671237"><a href="https://www.rollingstone.de/musik/musik-news/">News</a></li> 4301 <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-2671239"><a href="https://www.rollingstone.de/musik/musik-features/">Features</a></li> 4302 <li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2671275"><a href="/reviews/">Reviews</a></li> 4303 <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-2671235"><a href="https://www.rollingstone.de/musik/musik-listen/">Rankings</a></li> 4304</ul> 4305</li> 4306<li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-has-children menu-item-2671241"><a href="https://www.rollingstone.de/film-serie/">Film & Serie</a> 4307<ul class="sub-menu"> 4308 <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-2671245"><a href="https://www.rollingstone.de/film-serie/film-serien-news/">News</a></li> 4309 <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-2672963"><a href="https://www.rollingstone.de/film-serie/film-serien-features/">Features</a></li> 4310 <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-2671243"><a href="https://www.rollingstone.de/film-serie/film-serien-reviews/">Reviews</a></li> 4311 <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-2671247"><a href="https://www.rollingstone.de/film-serie/film-serien-listen/">Rankings</a></li> 4312</ul> 4313</li> 4314<li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-has-children menu-item-2671249"><a href="https://www.rollingstone.de/kultur-politik/">Kultur & Politik</a> 4315<ul class="sub-menu"> 4316 <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-2671251"><a href="https://www.rollingstone.de/kultur-politik/kultur-politik-features/">Features</a></li> 4317 <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-2671253"><a href="https://www.rollingstone.de/kultur-politik/kultur-politik-bucher/">Bücher</a></li> 4318</ul> 4319</li> 4320<li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-has-children menu-item-2671255"><a href="https://www.rollingstone.de/meinung/">Meinung</a> 4321<ul class="sub-menu"> 4322 <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-2671257"><a href="https://www.rollingstone.de/meinung/meinung-kolumnen/">Kolumnen</a></li> 4323 <li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2671259"><a href="/wohnzimmer">Wohnzimmer</a></li> 4324</ul> 4325</li> 4326<li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-has-children menu-item-2671261"><a href="https://www.rollingstone.de/live/">Live</a> 4327<ul class="sub-menu"> 4328 <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-2671265"><a href="https://www.rollingstone.de/live/live-konzerte/">Konzerte</a></li> 4329 <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-2671267"><a href="https://www.rollingstone.de/live/live-festivals/">Festivals</a></li> 4330 <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-2671263"><a href="https://www.rollingstone.de/live/live-galerien/">Galerien</a></li> 4331 <li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2671269"><a href="/alle-konzerte-in/">Tourdaten</a></li> 4332 <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-2841593"><a href="https://www.rollingstone.de/live/rs-praesentiert/">RS präsentiert</a></li> 4333 <li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2945367"><a target="_blank" href="https://rollingstone-beach.de/de/">RS Beach</a></li> 4334 <li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2714745"><a target="_blank" href="https://rollingstone.reservix.de/">Ticket-Shop</a></li> 4335</ul> 4336</li> 4337<li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2671271"><a href="/video/">Video</a></li> 4338<li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2671273"><a href="/audio/">Audio</a></li> 4339<li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-has-children menu-item-2671287"><a href="#">Mehr</a> 4340<ul class="sub-menu"> 4341 <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-2671283"><a href="https://www.rollingstone.de/rs-empfiehlt/">RS Empfiehlt</a></li> 4342 <li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2671285"><a target="_blank" href="https://www.musik-magazine.de/rolling-stone-kat/shop/">Magazin-Shop</a></li> 4343 <li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-3057739"><a href="https://www.rollingstone.de/kooperationen/">Kooperationen</a></li> 4344</ul> 4345</li> 4346<li class="typo-color-primary menu-strong menu-item menu-item-type-custom menu-item-object-custom menu-item-3185679"><a target="_blank" href="https://www.musik-magazine.de/rollingstone">Abo</a></li> 4347</ul></div> <div class="asmb-search-bar-container is-mobile"> 4348 <form role="search" method="get" class="search-form" action="https://www.rollingstone.de/"> 4349 <button type="submit" id="suchenBtn1" class="asmb-search-bar-icon" aria-label="Suche starten"> 4350 <i class="icon-magnifying-glass typo-color-black"></i> 4351 </button> 4352 <label for="searchBar1" hidden>Suche:</label> 4353 <input type="search" id="searchBar1" class="search-field form-control" placeholder="Suche nac
4353h ..." aria-label="Suchbegriff eingeben" value="" name="s" title="Search for:"> 4354 <button type="button" class="asmb-search-bar-close" aria-label="Suchformular schlieÃen"> 4355 <i class="icon-xmark"></i> 4356 </button> 4357</form> 4358 </div> 4359 <div class="asmb-modal-helper"></div> 4360 </div> 4361 </div> 4362 </div> 4363 4364 </div> 4365 </nav> 4366 </div> 4367 </header> 4368 <div class="asmb-header-container-helper"></div> 4369 <div class="asmb-search-bar-container is-hidden"> 4370 <form role="search" method="get" class="search-form" action="https://www.rollingstone.de/"> 4371 <button type="submit" id="suchenBtn2" class="asmb-search-bar-icon" aria-label="Suche starten"> 4372 <i class="icon-magnifying-glass typo-color-black"></i> 4373 </button> 4374 <label for="searchBar2" hidden>Suche:</label> 4375 <input type="search" id="searchBar2" class="search-field form-control" placeholder="Suche nach ..." aria-label="Suchbegriff eingeben" value="" name="s" title="Search for:"> 4376 <button type="button" class="asmb-search-bar-close" aria-label="Suchformular schlieÃen"> 4377 <i class="icon-xmark"></i> 4378 </button> 4379</form> 4380 </div> 4381 4382 <!-- AD pos_1 desktop --> 4383 <div class="asmb-iqd-full-width asmb-iqd-desktop margin-m"> 4384 <div class="iqdcontainer" data-placement="pos_1" data-device="desktop"></div> 4385 </div> 4386 <!-- END pos_1 desktop --> 4387 4388<section id="primary" class="asmb-article-content"> 4389 <div id="main" role="main"> 4390 4391 4392 4393<article id="post-3193085" class="asmb-article asmb-article-post asmb-content-area post-3193085 audio-post type-audio-post status-publish has-post-thumbnail hentry category-musik category-musik-news tag-neil-young tag-neil-young-and-the-chrome-hearts tag-chrome-hearts tag-second-song"> 4394 4395 <section id="asmb-article-header" class="asmb-article-header"> 4396 <div class="asmb-article-header-content"> 4397 <nav class="asmb-article-breadcrumb"><a class="headline-xs" href="https://www.rollingstone.de">Home</a> <span>âº</span> <a class="headline-xs" href="https://www.rollingstone.de/audio-post/">Audio</a></nav> <!-- Custom column header --> 4398 <h1 class="asmb-article-title headline-single-article typo-color-black weight-700">âSecond Songâ von Neil Young: Ein spätes Meisterwerk?</h1> <div class="asmb-article-excerpt-container"> 4399 <h2 class="asmb-article-excerpt headline-single-article headline-ml font-primary weight-400">Ein alter Mann blickt auf sein Leben zurück, begleitet von einer kongenialen Band</h2> </div> 4400 <div class="asmb-article-meta-container"> 4401 <div class="asmb-article-author-container"> 4402 <span class="asmb-article-author-byline headline-xs font-primary typo-color-black typo-uppercase letter-spacing-m">von </span> 4403 <a class="asmb-article-author-name headline-xs font-primary typo-color-black typo-uppercase letter-spacing-m" href="https://www.rollingstone.de/author/jan-jekal/" rel="author" title="Jan Jekal" itemprop="author"> 4404 Jan Jekal </a> 4405 4406 4407 <time class="headline-xs font-kicker asmb-article-author-date typo-color-grey" datetime="2026-09-25T03:32:43"> 4408 25.09.2026 </time> 4409 </div> 4410 4411 <div class="asmb-article-header-social"> 4412 <span class="headline-xxs typo-uppercase typo-color-black">Artikel Teilen</span> 4413 4414<section class="asmb-sharing-widget"> 4415 <div class="asmb-sharing-container"> 4416 <a target="_blank" class="asmb-share-button share-facebook" aria-label="Teile diesen Beitrag auf Facebook" href="https://www.facebook.com/sharer/sharer.php?u=https://www.rollingstone.de/audio-post/second-song-von-neil-young-ein-spaetes-meisterwerk/" title="Bei Facebook teilen"><i class="icon-facebook"></i></a> 4417 <a target="_blank" class="asmb-share-button share-instagram" aria-label="Teile diesen Beitrag auf WhatsApp" href="whatsapp://send?text=Dieser%20Artikel%20interessiert%20dich%20bestimmt%3A%0D%0Ahttps://www.rollingstone.de/audio-post/second-song-von-neil-young-ein-spaetes-meisterwerk/" title="Bei WhatsApp teilen"><i class="icon-whatsapp"></i></a> 4418 <a target="_blank" class="asmb-share-button share-twitter" aria-label="Teile diesen Beitrag auf X" href="https://twitter.com/intent/tweet?url=https://www.rollingstone.de/audio-post/second-song-von-neil-young-ein-spaetes-meisterwerk/&text=âSecond Songâ von Neil Young: Ein spätes Meisterwerk?&via=" title="Tweeten"><i class="icon-x-twitter"></i></a> 4419 <a target="_blank" class="asmb-share-button share-mail" aria-label="Teile diesen Beitrag auf per Mail" href="mailto:?subject=Toller%20Artikel%20auf%20Musikexpress.de&body=Dieser%20Artikel%20interessiert%20dich%20bestimmt%3A%0D%0Ahttps://www.rollingstone.de/audio-post/second-song-von-neil-young-ein-spaetes-meisterwerk/" title="Per Mail teilen"><i class="icon-envelope"></i></a> 4420 </div> 4421</section> </div> 4422 </div> 4423 <aside class="asmb-article-header-preferences headline-xs font-primary typo-color-black typo-uppercase letter-spacing-m"> 4424 <img src="https://www.rollingstone.de/wp-content/themes/RS-Theme-2023/images/google-bevorzugen-icon.svg" alt="Icon um Rolling Stone bei der Google-Suche zu bevorzugen"> 4425 <a href="https://www.google.com/preferences/source?q=rollingstone.de" target="_blank">ROLLING STONE bei Google bevorzugen</a> 4426 </aside> 4427 </div> 4428 4429 <div class="asmb-article-teaser-image"> 4430 <div class="asmb-article-teaser-image-container"> 4431 <figure class="asmb-article-post-image-container"> 4432 <div class="asmb-article-teaser-image-content"> 4433 <img width="2363" height="1433" src="https://www.rollingstone.de/wp-content/uploads/2025/06/neil-young-GettyImages-2222655563.jpg" class="attachment-xl size-xl landscape wp-post-image" alt="Neil Young Live 2025" decoding="async" fetchpriority="high" srcset="https://www.rollingstone.de/wp-content/uploads/2025/06/neil-young-gettyimages-2222655563-scaled-e1751274795954.webp 2363w, https://www.rollingstone.de/wp-content/uploads/2025/06/neil-young-gettyimages-2222655563-scaled-e1751274795954-577x350.webp 577w, https://www.rollingstone.de/wp-content/uploads/2025/06/neil-young-gettyimages-2222655563-scaled-e1751274795954-1024x621.webp 1024w, https://www.rollingstone.de/wp-content/uploads/2025/06/neil-young-gettyimages-2222655563-scaled-e1751274795954-768x466.webp 768w, https://www.rollingstone.de/wp-content/uploads/2025/06/neil-young-gettyimages-2222655563-scaled-e1751274795954-1536x931.webp 1536w, https://www.rollingstone.de/wp-content/uploads/2025/06/neil-young-gettyimages-2222655563-scaled-e1751274795954-2048x1242.webp 2048w, https://www.rollingstone.de/wp-content/uploads/2025/06/neil-young-gettyimages-2222655563-scaled-e1751274795954-500x303.webp 500w, https://www.rollingstone.de/wp-content/uploads/2025/06/neil-young-gettyimages-2222655563-scaled-e1751274795954-992x602.webp 992w, https://www.rollingstone.de/wp-content/uploads/2025/06/neil-young-gettyimages-2222655563-scaled-e1751274795954-1800x1092.webp 1800w" sizes="(min-width: 768px) and (min-resolution: 192dpi) 768px, (min-width: 768px) and (max-resolution: 191dpi) 1024px, (min-width: 600px) 500px, (max-width: 599px) and (min-resolution: 192dpi) 250px, (max-width: 599px) and (max-resolution: 191dpi) 500px" /> </div>
4434 <figcaption class="asmb-article-caption-container"> 4435 <p class="asmb-article-caption"> 4436 <span class="asmb-article-image-caption" aria-label="Bildunterschrift" data-caption-type="main">Neil Young Live 2025</span> 4437 4438 4439 <span class="asmb-article-credits-container" aria-label="Bildnachweise" data-caption-type="credits"> 4440 <span class="asmb-article-credits" data-credit-type="label">Foto: </span> 4441 <span class="asmb-article-credits" data-credit-type="source"">Redferns.</span> 4442 <span class="asmb-article-credits" data-credit-type="author">Jim Dyson.</span> 4443 <span class="asmb-article-credits" data-credit-type="rights">All rights reserved.</span> 4444 </span> 4445 </p> 4446 </figcaption> 4447 </figure> 4448 </div> 4449 </div> 4450 4451 4452 </section><!-- .asmb-article-header --> 4453 4454 <!-- Article banner widget --> 4455 <!-- --> 4456 4457 <!-- Ad pos_1 mobile --> 4458 <div class="asmb-iqd-full-width asmb-iqd-mobile margin-m"> 4459 <div class="iqdcontainer" data-placement="pos_1" data-device="mobile"></div> 4460 </div> 4461 4462 <!-- End Ad pos_1 mobile --> 4463 4464 <section id="asmb-article-content-area" class="asmb-article-content-area"> 4465 <div class="row"> 4466 <div class="asmb-article-copy-text-container col-12"> 4467 <div class="asmb-article-content-container"> 4468 <!-- Widget Empfehlungen der Redaktion --> 4469 4470<div class="asmb-article-recommendation-container"> 4471 <div class="asmb-headline-recommendation-container"> 4472 <img src="https://www.rollingstone.de/wp-content/uploads/2024/12/rs-badge-recommendation.png" alt="ROLLING STONE Badge"> 4473 <div class="asmb-headline asmb-headline-recommendation headline-ml font-ultra typo-color-primary typo-uppercase line-height-110 letter-spacing-l"><span>Empfehlungen der <span>Redaktion</span></div> 4474 </div> 4475 <div class="row"> 4476 <div class="asmb-sidebar-item col-12"> 4477<article class="asmb-teaser asmb-teaser-text-recommendation post-2942697 post type-post status-publish format-standard has-post-thumbnail hentry category-musik category-musik-news tag-beatles tag-john-lennon tag-i-am-the-walrus"> 4478 <a href="https://www.rollingstone.de/songanalyse-wovon-handelt-i-am-the-walrus-von-den-beatles-2942697/"> 4479 <div class="teaser-text-container"> 4480 <div class="teaser-title"> 4481 <div class="asmb-headline headline-s font-headline typo-color-black weight-700"> 4482 <span> 4483 </span> 4484 Songanalyse: Wovon handelt âI Am the Walrusâ von den Beatles? </div> 4485 </div> 4486 </div> 4487 </a> 4488</article></div><div class="asmb-sidebar-item col-12"> 4489<article class="asmb-teaser asmb-teaser-text-recommendation post-2882959 post type-post status-publish format-standard has-post-thumbnail hentry category-musik category-musik-news tag-acdc tag-iron-maiden tag-satanic-panic"> 4490 <a href="https://www.rollingstone.de/satanic-panic-der-fruehen-1980er-jahre-kultur-phaenomen-mit-musikalischen-schauplaetzen-2882959/"> 4491 <div class="teaser-text-container"> 4492 <div class="teaser-title"> 4493 <div class="asmb-headline headline-s font-headline typo-color-black weight-700">
4494 <span> 4495 </span> 4496 âSatanic Panicâ der frühen 1980er-Jahre: Kultur-Phänomen mit musikalischen Schauplätzen </div> 4497 </div> 4498 </div> 4499 </a> 4500</article></div><div class="asmb-sidebar-item col-12"> 4501<article class="asmb-teaser asmb-teaser-text-recommendation post-2882953 post type-post status-publish format-standard has-post-thumbnail hentry category-musik category-musik-news tag-asmr"> 4502 <a href="https://www.rollingstone.de/was-ist-asmr-in-der-musik-eine-umfassende-erklaerung-2882953/"> 4503 <div class="teaser-text-container"> 4504 <div class="teaser-title"> 4505 <div class="asmb-headline headline-s font-headline typo-color-black weight-700"> 4506 <span> 4507 </span> 4508 Was ist ASMR in der Musik? â Eine umfassende Erklärung </div> 4509 </div> 4510 </div> 4511 </a> 4512</article></div><div class="asmb-sidebar-item col-12"> 4513<article class="asmb-teaser asmb-teaser-text-recommendation post-3067989 post type-post status-publish format-standard has-post-thumbnail hentry category-musik category-musik-news tag-udo-lindenberg tag-giorgio-moroder tag-soundtrack tag-klaus-doldinger tag-passport tag-tatort tag-jazz tag-das-boot tag-filmmusik tag-die-unendlic
4513he-geschichte"> 4514 <a href="https://www.rollingstone.de/klaus-doldinger-die-unendliche-geschichte-3067989/"> 4515 <div class="teaser-text-container"> 4516 <div class="teaser-title"> 4517 <div class="asmb-headline headline-s font-headline typo-color-black weight-700"> 4518 <span> 4519 </span> 4520 So komponierte Klaus Doldinger den Soundtrack zur âUnendlichen Geschichteâ </div> 4521 </div> 4522 </div> 4523 </a> 4524</article></div> 4525 </div> 4526</div> 4527 <div class="asmb-article-copy-text"> 4528 <!-- Script https://open.spotify.com/embed/show/0suM2jcYo3BQEV05Udiz3u?utm_source=generator blocked until consent is given -->
4529<script type="text/javascript"> 4530 if (typeof window.rs_blocked_scripts === "undefined") { 4531 window.rs_blocked_scripts = []; 4532 } 4533 window.rs_blocked_scripts.push({ 4534 blocked_src: "https://open.spotify.com/embed/show/0suM2jcYo3BQEV05Udiz3u?utm_source=generator", 4535 category: "advertising", 4536 id: "megaphone-player-js", 4537 async: false 4538 }); 4539 </script>
4539 4540<div class="rs-blocked-content-placeholder" data-script-id="megaphone-player" data-rs-blocked="true" data-rs-category="advertising"> 4541 <div style="padding: 15px; background: #f5f5f5; border: 1px solid #ddd; text-align: center;"> 4542 <strong>Podcast Player</strong><br> 4543 Bitte akzeptieren Sie die Datenschutzeinstellungen oder loggen Sie sich mit ContentPass ein, um den Podcast-Player zu laden. 4544 </div> 4545 </div> <p>Das 50. Album von Neil Young zählt zu seinen besten. Wirklich. Die hypnotische Akustikgitarre, der ergreifende Gesang, die elegischen Themen. Ein alter Mann blickt zurück auf sein Leben, mit Wärme und Wehmut, begleitet von einer kongenialen Band. Findet zumindest Jan. Birgit ist nicht ganz so überzeugt. Würde man diese Texte bei anderen nicht banal finden?</p> 4546 </div> 4547 </div> 4548 <div class="asmb-author-outro-container"><p style="font-weight:700;font-style:italic;"><a href="https://www.rollingstone.de/author/jan-jekal/">Jan Jekal</a> schreibt für ROLLING STONE. <a href="https://www.rollingstone.de/author/jan-jekal/">
4548Weitere Artikel und das Autorenprofil gibt es hier</a>.</p></div> <div class="asmb-article-outro-widget-area"> 4549 <div id="text-27" class="asmb-article-outro-widget widget_text"> <div class="textwidget"><p><b><i>âJa, sie sind es wirklich!â Die groÃe Tokio-Hotel-Story und das exklusive Interview in der Oktober-Ausgabe von ROLLING STONE</i></b><b><i>. AuÃerdem </i></b><b><i>im Heft: Gespräche mit Danger Dan und Gracie Abrams, der neu entdeckten Song der Beatles und ein Besuch bei Annalena Baerbock in New York</i></b><b><i>: </i></b><a title="Original URL: 4550https://www.musik-magazine.de/rolling-stone-03-26-09/ 4551 4552Click to follow link." href="https://www.musik-magazine.de/rolling-stone-03-26-10/" target="_blank" rel="noopener" data-outlook-id="41d27c62-b67f-4f62-a4de-7bca011c5455"><b><i><u>Hier ROLLING STONE 10/26 bestellen!</u></i></b></a></p> 4553</div> 4554 </div> </div> 4555 <div class="asmb-article-footer-container"> 4556 <div class="asmb-tags-links-container"> 4557 <span class="asmb-tags-headline headline-xs typo-uppercase letter-spacing-l">Themen aus dem Artikel:</span> <div class="asmb-tags-links-items headline-xs"> 4558 <a href="https://www.rollingstone.de/themen/neil-young/" class="teaser-category asmb-category-secondary">Neil Young</a> <a href="https://www.rollingstone.de/themen/neil-young-and-the-chrome-hearts/" class="teaser-category asmb-category-secondary">Neil Young and the Chrome Hearts</a> <a href="https://www.rollingstone.de/themen/chrome-hearts/" class="teaser-category asmb-category-secondary">Chrome Hearts</a> <a href="https://www.rollingstone.de/themen/second-song/" class="teaser-category asmb-category-secondary">Second Song</a> </div> 4559 </div> 4560 </div> 4561 </div> 4562 </div> 4563 </section><!-- .asmb-article-content --> 4564 4565 <!-- Ad Outbrain --> 4566 <div id="outbrain_widget_container"></div> 4567 <!-- End Ad Outbrain --> 4568 4569 <div id="asmb-article-popular" class="asmb-popular"> 4570 <section id="asmb-popular"> 4571 <div class="asmb-popular-container asmb-section"> 4572 <div class="asmb-headline headline-m font-ultra typo-color-black typo-uppercase line-height-120 letter-spacing-l asmb-double-border-top">Mehr News und Stories</div> 4573 <div class="row"> 4574 4575 <div class="asmb-teaser-medium-container col-12 col-lg-4"> 4576 <article class="asmb-teaser asmb-teaser-medium post-3099191 post type-post status-publish format-standard has-post-thumbnail hentry category-musik category-musik-news tag-neil-young"> 4577 <a href="https://www.rollingstone.de/die-10-besten-neil-young-deep-cuts-3099191/"> 4578 <div class="teaser-image-container"> 4579 <img width="2560" height="1533" src="https://www.rollingstone.de/wp-content/uploads/2021/10/14/10/neil-young-gettyimages-1155383231-scaled.jpg" class="attachment-m size-m landscape wp-post-image" alt="Neil Young" decoding="async" srcset="https://www.rollingstone.de/wp-content/uploads/2021/10/14/10/neil-young-gettyimages-1155383231-scaled.jpg 2560w, https://www.rollingstone.de/wp-content/uploads/2021/10/14/10/neil-young-gettyimages-1155383231-scaled-584x350.jpg 584w, https://www.rollingstone.de/wp-content/uploads/2021/10/14/10/neil-young-gettyimages-1155383231-scaled-1024x613.jpg 1024w, https://www.rollingstone.de/wp-content/uploads/2021/10/14/10/neil-young-gettyimages-1155383231-scaled-768x460.jpg 768w, https://www.rollingstone.de/wp-content/uploads/2021/10/14/10/neil-young-gettyimages-1155383231-scaled-1536x920.jpg 1536w, https://www.rollingstone.de/wp-content/uploads/2021/10/14/10/neil-young-gettyimages-1155383231-scaled-2048x1226.jpg 2048w, https://www.rollingstone.de/wp-content/uploads/2021/10/14/10/neil-young-gettyimages-1155383231-scaled-420x252.jpg 420w, https://www.rollingstone.de/wp-content/uploads/2021/10/14/10/neil-young-gettyimages-1155383231-scaled-200x120.jpg 200w, https://www.rollingstone.de/wp-content/uploads/2021/10/14/10/neil-young-gettyimages-1155383231-scaled-104x62.jpg 104w, https://www.rollingstone.de/wp-content/uploads/2021/10/14/10/neil-young-gettyimages-1155383231-scaled-534x320.jpg 534w" sizes="(min-width: 768px) and (min-resolution: 192dpi) 300px, (min-width: 768px) and (max-resolution: 191dpi) 500px, (min-width: 600px) 500px, (max-width: 599px) and (min-resolution: 192dpi) 250px, (max-width: 599px) and (max-resolution: 191dpi) 500px" /> </div> 4580 <div class="teaser-text-container"> 4581 <div class="teaser-category-container"> 4582 <p class="headline-xxxs typo-uppercase typo-color-black letter-spacing-m"> 4583 Musik </p> 4584 </div> 4585 <div class="teaser-title"> 4586 <p class="headline-sm font-headline typo-color-black line-clamp-4">
4587 <span> 4588 </span> 4589 Neil Young: Die 10 besten Deep Cuts </p> 4590 </div> 4591 <div class="teaser-excerpt"> 4592 <p class="headline-s font-primary weight-400 typo-color-black line-clamp-4"> 4593 Die 10 besten Neil-Young-Deep-Cuts: Leser wählen Favoriten von "Thrasher" bis "Expecting to Fly". </p> 4594 </div> 4595 <div class="teaser-author"> 4596 <p class="headline-xxxs font-primary text-uppercase weight-400 letter-spacing-m typo-color-black"> 4597 <span>Von </span> 4598 Andy Greene </p> 4599 </div> 4600 </div> 4601 </a> 4602</article> </div> 4603 <div class="asmb-teaser-medium-container col-12 col-lg-4"> 4604 <article class="asmb-teaser asmb-teaser-medium post-3097365 post type-post status-publish format-standard has-post-thumbnail hentry category-musik category-musik-news tag-neil-young tag-bob-dylan tag-woodstock tag-protestsong tag-vietnamkrieg"> 4605 <a href="https://www.rollingstone.de/10-beste-protestsongs-aller-zeiten-3097365/"> 4606 <div class="teaser-image-container"> 4607 <img width="3000" height="1967" src="https://www.rollingstone.de/wp-content/uploads/2013/03/11/15/136100656.jpg" class="attachment-m size-m landscape wp-post-image" alt="Rage Against The Machine" decoding="async" srcset="https://www.rollingstone.de/wp-content/uploads/2013/03/11/15/136100656.jpg 3000w, https://www.rollingstone.de/wp-content/uploads/2013/03/11/15/136100656-534x350.jpg 534w, https://www.rollingstone.de/wp-content/uploads/2013/03/11/15/136100656-1024x671.jpg 1024w, https://www.rollingstone.de/wp-content/uploads/2013/03/11/15/136100656-420x275.jpg 420w, https://www.rollingstone.de/wp-content/uploads/2013/03/11/15/136100656-200x131.jpg 200w, https://www.rollingstone.de/wp-content/uploads/2013/03/11/15/136100656-104x68.jpg 104w, https://www.rollingstone.de/wp-content/uploads/2013/03/11/15/136100656-488x320.jpg 488w" sizes="(min-width: 768px) and (min-resolution: 192dpi) 300px, (min-width: 768px) and (max-resolution: 191dpi) 500px, (min-width: 600px) 500px, (max-width: 599px) and (min-resolution: 192dpi) 250px, (max-width: 599px) and (max-resolution: 191dpi) 500px" /> </div> 4608 <div class="teaser-text-container"> 4609 <div class="teaser-category-container"> 4610 <p class="headline-xxxs typo-uppercase typo-color-black letter-spacing-m"> 4611 Musik </p> 4612 </div> 4613 <div class="teaser-title"> 4614 <p class="headline-sm font-headline typo-color-black line-clamp-4"> 4615 <span> 4616 </span> 4617 Ranking: Die 10 besten Protestsongs aller Zeiten </p> 4618 </div> 4619 <div class="teaser-excerpt"> 4620 <p class="headline-s font-primary weight-400 typo-color-black line-clamp-4"> 4621 Die 10 gröÃten Protestsongs aller Zeiten â von Bob Dylan bis Rage Against the Machine. </p> 4622 </div> 4623 <div class="teaser-author"> 4624 <p class="headline-xxxs font-primary text-uppercase weight-400 letter-spacing-m typo-color-black"> 4625 <span>Von </span> 4626 Andy Greene </p> 4627 </div> 4628 </div> 4629 </a> 4630</article> </div> 4631 <div class="asmb-teaser-medium-container col-12 col-lg-4"> 4632 <article class="asmb-teaser asmb-teaser-medium post-3081139 post type-post status-publish format-standard has-post-thumbnail hentry category-musik category-musik-news tag-crazy-horse tag-neil-young"> 4633 <a href="https://www.rollingstone.de/neil-young-20-versteckte-songs-fuer-hardcore-fans-3081139/"> 4634 <div class="teaser-image-container"> 4635 <img width="2560" height="1701" src="https://www.rollingstone.de/wp-content/uploads/2025/07/GettyImages-798498215.jpg" class="attachment-m size-m landscape wp-post-image" alt="Canadian singer-songwriter and musician Neil Young performs on stage with Crazy Horse at Hammersmith Odeon, London, 28th M..." decoding="async" loading="lazy" srcset="https://www.rollingstone.de/wp-content/uploads/2025/07/gettyimages-798498215-scaled.webp 2560w, https://www.rollingstone.de/wp-content/uploads/2025/07/gettyimages-798498215-527x350.webp 527w, https://www.rollingstone.de/wp-content/uploads/2025/07/gettyimages-798498215-1024x680.webp 1024w, https://www.rollingstone.de/wp-content/uploads/2025/07/gettyimages-798498215-768x510.webp 768w, https://www.rollingstone.de/wp-content/uploads/2025/07/gettyimages-798498215-1536x1020.webp 1536w, https://www.rollingstone.de/wp-content/uploads/2025/07/gettyimages-798498215-2048x1360.webp 2048w, https://www.rollingstone.de/wp-content/uploads/2025/07/gettyimages-798498215-500x332.webp 500w, https://www.rollingstone.de/wp-content/uploads/2025/07/gettyimages-798498215-992x659.webp 992w, https://www.rollingstone.de/wp-content/uploads/2025/07/gettyimages-798498215-1800x1196.webp 1800w" sizes="(min-width: 768px) and (min-resolution: 192dpi) 300px, (min-width: 768px) and (max-resolution: 191dpi) 500px, (min-width: 600px) 500px, (max-width: 599px) and (min-resolution: 192dpi) 250px, (max-width: 599px) and (max-resolution: 191dpi) 500px" /> </div> 4636 <div class="teaser-text-container"> 4637 <div class="teaser-category-container"> 4638 <p class="headline-xxxs typo-uppercase typo-color-black letter-spacing-m"> 4639 Musik </p> 4640 </div> 4641 <div class="teaser-title"> 4642 <p class="headline-sm font-headline typo-color-black line-clamp-4">
4643 <span> 4644 </span> 4645 Neil Young: 20 Songs, die nur Hardcore-Fans kennen </p> 4646 </div> 4647 <div class="teaser-excerpt"> 4648 <p class="headline-s font-primary weight-400 typo-color-black line-clamp-4"> 4649 20 unterschätzte, selten gespielte oder unveröffentlichte Neil-Young-Songs, die selbst Hardcore-Fans oft übersehen â voller versteckter Schätze. </p> 4650 </div> 4651 <div class="teaser-author"> 4652 <p class="headline-xxxs font-primary text-uppercase weight-400 letter-spacing-m typo-color-black"> 4653 <span>Von </span> 4654 Andy Greene </p> 4655 </div> 4656 </div> 4657 </a> 4658</article> </div> 4659 </div> 4660 </div> 4661 </section> 4662 </div> 4663 4664</article><!-- #post-## --> 4665 </div><!-- #main --> 4666 4667</section><!-- #primary --> 4668 4669 4670 4671 <!-- Ad pos_footer desktop --> 4672 <div class="asmb-iqd-full-width asmb-iqd-desktop margin-m"> 4673 <div class="iqdcontainer" data-placement="pos_footer" data-device="desktop"></div> 4674 </div> 4675 4676 <!-- Ad pos_footer mobile --> 4677 <div class="asmb-iqd-full-width asmb-iqd-mobile margin-bottom-m"> 4678 <div class="iqdcontainer" data-placement="pos_footer" data-device="mobile"></div> 4679 </div> 4680 4681<footer id="colophon" class="asmb-footer" role="contentinfo"> 4682 <nav class="asmb-footer-container" aria-label="Footer-Navigation"> 4683 <div class="row"> 4684 <div class="asmb-footer-menu col-12 col-lg-9"> 4685 <div class="row gx-5 align-items-center"> 4686 <div class="col-12 col-lg-6"> 4687 <a class="asmb-footer-logo-container" aria-label="Zurück zur Startseite" href="https://www.rollingstone.de/"> 4688 <img class="asmb-footer-logo" src="https://www.rollingstone.de/wp-content/themes/RS-Theme-2023/images/RS-Logo-2025-small.svg" alt="ROLLING STONE Germany Logo"> 4689 </a> 4690 </div> 4691 <div class="col-6"> 4692 <ul class="asmb-footer-social-menu"> 4693 <li class="asmb-footer-social-icon"> 4694 <a href="https://www.instagram.com/rollingstone_de/?hl=de" aria-label="Folge uns auf Instagram" target="_blank"><i class="icon-instagram"></i></a> 4695 </li> 4696 <li class="asmb-footer-social-icon"> 4697 <a href="https://whatsapp.com/channel/0029Va65I6jEquiPWXenxp3W" aria-label="Folge uns auf WhatsApp" target="_blank"><i class="fa-brands icon-whatsapp"></i></a> 4698 </li> 4699 <li class="asmb-footer-social-icon"> 4700 <a href="https://www.facebook.com/rollingstonemagazin/?locale=de_DE" aria-label="Folge uns auf Facebook" target="_blank"><i class="icon-facebook"></i></a> 4701 </li> 4702 <li class="asmb-footer-social-icon"> 4703 <a href="https://www.youtube.com/@rollingstoneonline" aria-label="Abonniere uns auf YouTube" target="_blank"><i class="icon-youtube"></i></a> 4704 </li> 4705 <li class="asmb-footer-social-icon"> 4706 <a href="https://www.tiktok.com/@rollingstone_de" aria-label="Folge uns auf TikTok" target="_blank"><i class="icon-tiktok"></i></a> 4707 </li> 4708 </ul> 4709 </div> 4710 </div> 4711 <div class="asmb-newsletter-container"> 4712 <div class="typo-color-black font-headline headline-m mb-4">Abonniere die Printausgabe und bekomme ROLLING STONE<br>direkt nach Hause geliefert</div> 4713 <a class="asmb-button-primary asmb-button-xtra-small button-color-primary" href="https://www.musik-magazine.de/rollingstone" target="_blank">Jetzt abonnieren</a> 4714 </div> 4715 </div> 4716 <div class="asmb-footer-subscription col-12 col-lg-3"> 4717 <div class="row"> 4718 <div class="col-12"> 4719 <div class="asmb-footer-subscription-issue-container"> 4720 <div id="media_image-16" class="widget widget_media_image asmb-widget-current-issue"><img width="800" height="1039" src="https://www.rollingstone.de/wp-content/uploads/2024/01/rs_0224_coveradssmall.jpg" class="image wp-image-2688887 attachment-full size-full portrait" alt="RS_0224_greenDAY_cover.indd" style="max-width: 100%; height: auto;" decoding="async" loading="lazy" srcset="https://www.rollingstone.de/wp-content/uploads/2024/01/rs_0224_coveradssmall.jpg 800w, https://www.rollingstone.de/wp-content/uploads/2024/01/rs_0224_coveradssmall-269x350.jpg 269w, https://www.rollingstone.de/wp-content/uploads/2024/01/rs_0224_coveradssmall-788x1024.jpg 788w, https://www.rollingstone.de/wp-content/uploads/2024/01/rs_0224_coveradssmall-768x997.jpg 768w, https://www.rollingstone.de/wp-content/uploads/2024/01/rs_0224_coveradssmall-500x649.jpg 500w" sizes="auto, (max-width: 800px) 100v
4720w, 800px" /></div> <a href="https://www.musik-magazine.de/spezial_abo-vz-webshop-1760-as-mex/" target="_blank"> 4721 <div class="asmb-subscription-issue-badge"> 4722 <p class="asmb-subscription-issue-badge-headline font-ultra headline-sm typo-uppercase typo-color-black">Spezial-<br>Abo</p> 4723 <p class="headline-xxs font-headline typo-uppercase typo-color-black">3 Ausgaben</p> 4724 <p class="headline-l typo-color-primary font-ultra">9,95 â¬</p> 4725 <s class="headline-xs typo-color-black font-headline">28,70 â¬</s> 4726 </div> 4727 </a> 4728 </div> 4729 <div class="asmb-subscription-text"> 4730 <div class="typo-color-black font-headline headline-m">Abonniere die Printausgabe und bekomme ROLLING STONE direkt nach Hause geliefert</div> 4731 <a class="asmb-button-primary asmb-button-xtra-small button-color-primary" href="https://www.musik-magazine.de/rollingstone" target="_blank">Jetzt abonnieren</a> 4732 </div> 4733 </div> 4734 </div> 4735 </div> 4736 </div> 4737 <div class="asmb-footer-menu-legals-container"> 4738 <div class="asmb-footer-menu-legals"> 4739 <div class="menu-footer-legals-container"><ul id="menu-footer-legals" class="menu"><li id="menu-item-2673151" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-2673151"><a href="https://www.rollingstone.de/kontakt/">Kontakt</a></li> 4740<li id="menu-item-2673153" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2673153"><a target="_blank" href="https://www.mediahouse-berlin.de/mediadaten/">Mediadaten</a></li> 4741<li id="menu-item-2673155" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2673155"><a target="_blank" href="https://www.mediahouse-berlin.de/agb/">AGB</a></li> 4742<li id="menu-item-2673157" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-2673157"><a href="https://www.rollingstone.de/datenschutz/">Datenschutz</a></li> 4743<li id="menu-item-3091117" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-3091117"><a href="https://www.rollingstone.de/barrierefreiheit/">Barrierefreiheit</a></li> 4744<li id="menu-item-2673159" class="privacymanager menu-item menu-item-type-post_type menu-item-object-page menu-item-2673159"><a href="https://www.rollingstone.de/privatsphaere/">Privatsphäre</a></li> 4745<li id="menu-item-2673161" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-2673161"><a href="https://www.rollingstone.de/impressum/">Impressum</a></li> 4746<li id="menu-item-2673165" class="widerruf menu-item menu-item-type-custom menu-item-object-custom menu-item-2673165"><a href="#">Widerruf Tracking</a></li> 4747<li id="menu-item-2673167" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2673167"><a href="https://join.com/companies/mediahouse-berlin">Jobs</a></li> 4748</ul></div> </div> 4749 </div> 4750 </nav> 4751 <div class="asmb-footer-external-links-container"> 4752 <div class="headline-xxs font-primary weight-700">Digital-Angebote der Axel Springer SE</div> <div class="asmb-footer-external-links"> 4753 <div class="menu-digital-angebote-der-axel-springer-se-container"><ul id="menu-digital-angebote-der-axel-springer-se" class="menu"><li id="menu-item-208144" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-208144"><a target="_blank" href="https://musikexpress.de">Musikexpress</a></li> 4754<li id="menu-item-208142" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-208142"><a target="_blank" href="https://metal-hammer.de">Metal Hammer</a></li> 4755<li id="menu-item-2672945" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2672945"><a target="_blank" href="https://www.welt.de/">WELT</a></li> 4756<li id="menu-item-2672947" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2672947"><a target="_blank" href="https://www.businessinsider.de/">Business Insider</a></li> 4757<li id="menu-item-2672949" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2672949"><a target="_blank" href="https://www.businessinsider.de/gruenderszene/">Gründerszene</a></li> 4758<li id="menu-item-208133" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-208133"><a target="_blank" href="https://bild.de">BILD</a></li> 4759<li id="menu-item-208132" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-208132"><a target="_blank" href="https://www.bz-berlin.de/">B.Z.</a></li> 4760<li id="menu-item-208130" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-208130"><a target="_blank" href="https://www.autobild.de/">AUTO BILD</a></li> 4761<li id="menu-item-208134" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-208134"><a target="_blank" href="https://computerbild.de">COMPUTER BILD</a></li> 4762<li id="menu-item-208148" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-208148"><a target="_blank" href="https://sportbild.de">SPORTBILD</a></li> 4763<li id="menu-item-2672953" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2672953"><a target="_blank" href="https://www.fitbook.de/">Fitbook</a></li> 4764<li id="menu-item-208150" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-208150"><a target="_blank" href="https://Stylebook.de">Stylebook</a></li> 4765<li id="menu-item-2672955" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2672955"><a target="_blank" href="https://www.myhomebook.de/">myHomebook</a></li> 4766<li id="menu-item-2672957" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2672957"><a target="_blank" href="https://www.petbook.de/">Petbook</a></li> 4767<li id="menu-item-208135" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-208135"><a target="_blank" href="https://finanzen.net">finanzen.net</a></li> 4768<li id="menu-item-208151" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-208151"><a target="_blank" href="https://Transfermarkt.de">Transfermarkt</a></li> 4769<li id="menu-item-2672959" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2672959"><a target="_blank" href="https://www.upday.com/de">Upday</a></li> 4770<li id="menu-item-208139" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-208139"><a target="_blank" href="https://idealo.de">Idealo</a></li> 4771<li id="menu-item-208149" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-208149"><a target="_blank" href="https://StepStone.de">StepStone</a></li> 4772</ul></div> </div> 4773 <p class="headline-xxs font-primary weight-700 text-center">© Rolling Stone Germany is published by Mediahouse Berlin GmbH under license from Rolling Stone, LLC, a subsidiary of Penske Media Cooperation</p> 4774 </div> 4775</footer> 4776 4777</div><!-- #content --> 4778</div><!-- #page --> 4779
4780<script type="speculationrules"> 4781{"prefetch":[{"source":"document","where":{"and":[{"href_matches":"/*"},{"not":{"href_matches":["/wp-*.php","/wp-admin/*","/wp-content/uploads/*","/wp-content/*","/wp-content/plugins/*","/wp-content/themes/RS-Theme-2023/*","/*\\?(.+)"]}},{"not":{"selector_matches":"a[rel~=\"nofollow\"]"}},{"not":{"selector_matches":".no-prefetch, .no-prefetch a"}}]},"eagerness":"conservative"}]} 4782</script>
vendor: 1 bytes, line 4782
4782
4783<script id="facebook-embed-loader-js" src="https://www.rollingstone.de/wp-content/plugins/asmb-facebook-embed-2023/facebook-embed-loader.js"></script>
vendor: 1 bytes, line 4783
4783
4784<script id="outbrain-widget-script-js-extra"> 4785var outbrain_object = {"isRevShare":"","link":"https://www.rollingstone.de/audio-post/second-song-von-neil-young-ein-spaetes-meisterwerk/"}; 4786//# sourceURL=outbrain-widget-script-js-extra 4787</script>
vendor: 1 bytes, line 4787
4787
4788<script id="outbrain-widget-script-js" src="https://www.rollingstone.de/wp-content/plugins/asmb-outbrain/outbrain-widget.js?ver=2.0.9"></script>
vendor: 1 bytes, line 4788
4788
4789<script id="ph-picture-credits-js" src="https://www.rollingstone.de/wp-content/plugins/asmb-picture-meta-data/asmb-picture-meta-data.js?ver=1.0"></script>
vendor: 1 bytes, line 4789
4789
4790<script id="tiktok-embed-loader-js" src="https://www.rollingstone.de/wp-content/plugins/asmb-tiktok-embed/tiktok-embed-loader.js?ver=1.0"></script>
vendor: 1 bytes, line 4790
4790
4791<script id="custom-ad-banner-js-js" src="https://www.rollingstone.de/wp-content/plugins/cms-banner-article/js/cms-article-banner.js?ver=1.0"></script>
vendor: 1 bytes, line 4791
4791
4792<script id="wp-hooks-js" src="https://www.rollingstone.de/wp-includes/js/dist/hooks.min.js?ver=f0f188028580e8dc1255"></script>
vendor: 1 bytes, line 4792
4792
4793<script id="wp-i18n-js" src="https://www.rollingstone.de/wp-includes/js/dist/i18n.min.js?ver=1dfe7db3940c23ea9216"></script>
vendor: 1 bytes, line 4793
4793
4794<script id="wp-i18n-js-after"> 4795wp.i18n.setLocaleData( { 'text direction\u0004ltr': [ 'ltr' ] } ); 4796//# sourceURL=wp-i18n-js-after 4797</script>
vendor: 1 bytes, line 4797
4797
4798<script id="swv-js" src="https://www.rollingstone.de/wp-content/plugins/contact-form-7/includes/swv/js/index.js?ver=6.1.7"></script>
vendor: 1 bytes, line 4798
4798
4799<script id="contact-form-7-js-before"> 4800var wpcf7 = { 4801 "api": { 4802 "root": "https:\/\/www.rollingstone.de\/wp-json\/", 4803 "namespace": "contact-form-7\/v1" 4804 } 4805}; 4806//# sourceURL=contact-form-7-js-before 4807</script>
vendor: 1 bytes, line 4807
4807
4808<script id="contact-form-7-js" src="https://www.rollingstone.de/wp-content/plugins/contact-form-7/includes/js/index.js?ver=6.1.7"></script>
vendor: 1 bytes, line 4808
4808
4809<script id="tealium-tracker-js-extra"> 4810var myData = {"is_home":"","is_post":"1","current":"second-song-von-neil-young-ein-spaetes-meisterwerk"}; 4811//# sourceURL=tealium-tracker-js-extra 4812</script>
vendor: 1 bytes, line 4812
4812
4813<script id="tealium-tracker-js" src="https://www.rollingstone.de/wp-content/plugins/tealium-tracker/js/tealium-tracker.js?ver=1.5"></script>
vendor: 1 bytes, line 4813
4813
4814<script id="wp-bootstrap-starter-popper-js" src="https://www.rollingstone.de/wp-content/themes/RS-Theme-2023/inc/assets/js/popper.min.js?ver=7.1"></script>
vendor: 1 bytes, line 4814
4814
4815<script id="wp-bootstrap-starter-bootstrapjs-js" src="https://www.rollingstone.de/wp-content/themes/RS-Theme-2023/inc/assets/js/bootstrap.min.js?ver=7.1"></script>
vendor: 1 bytes, line 4815
4815
4816<script id="wp-bootstrap-starter-themejs-js" src="https://www.rollingstone.de/wp-content/themes/RS-Theme-2023/inc/assets/js/theme-script.min.js?ver=7.1"></script>
vendor: 1 bytes, line 4816
4816
4817<script id="wp-bootstrap-starter-skip-link-focus-fix-js" src="https://www.rollingstone.de/wp-content/themes/RS-Theme-2023/inc/assets/js/skip-link-focus-fix.min.js?ver=20151215"></script>
vendor: 1 bytes, line 4817
4817
4818<script id="myscript-js" src="https://www.rollingstone.de/wp-content/themes/RS-Theme-2023/toggle-element-visibility.js?ver=1.0"></script>
vendor: 1 bytes, line 4818
4818
4819<script id="iqd-consent-handler-js" src="https://www.rollingstone.de/wp-content/plugins/asmb-iq-digital/js/consent-handler.js?ver=1.0.1"></script>
vendor: 1 bytes, line 4819
4819
4820<script id="iqd-political-ad-listener-js" src="https://www.rollingstone.de/wp-content/plugins/asmb-iq-digital/js/political-ad-listener.js?ver=1.0.1"></script>
vendor: 1 bytes, line 4820
4820
4821<script id="atkp-scripts-js" src="https://www.rollingstone.de/wp-content/plugins/affiliate-toolkit-starter/dist/script.js?ver=3.9.0"></script>
vendor: 1 bytes, line 4821
4821
4822<script id="atkp-custom-scripts-js" src="https://www.rollingstone.de/wp-content/uploads/affiliate-toolkit/scripts.js?ver=3.9.0"></script>
vendor: 1 bytes, line 4822
4822
4823<script id="wp-emoji-settings" type="application/json"> 4824{"baseUrl":"https://s.w.org/images/core/emoji/17.0.2/72x72/","ext":".png","svgUrl":"https://s.w.org/images/core/emoji/17.0.2/svg/","svgExt":".svg","source":{"concatemoji":"https://www.rollingstone.de/wp-includes/js/wp-emoji-release.min.js?ver=7.1"}} 4825</script>
vendor: 1 bytes, line 4825
4825
4826<script type="module"> 4827/*! This file is auto-generated */ 4828var e="script#wp-emoji-settings",t=document.querySelector(e);if(!(t instanceof HTMLScriptElement))throw new Error("Element missing: "+e);const r=JSON.parse(t.text),s=(window._wpemojiSettings=r,"wpEmojiSettingsSupports"),o=["flag","emoji"];function i(e){try{var t={supportTests:e,timestamp:(new Date).valueOf()};sessionStorage.setItem(s,JSON.stringify(t))}catch(e){}}function c(e,t,n){e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(t,0,0);t=new Uint32Array(e.getImageData(0,0,e.canvas.width,e.canvas.height).data);e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(n,0,0);const r=new Uint32Array(e.getImageData(0,0,e.canvas.width,e.canvas.height).data);return t.every((e,t)=>e===r[t])}function p(e,t){e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(t,0,0);var n=e.getImageData(16,16,1,1);for(let e=0;e<n.data.length;e++)if(0!==n.data[e])return!1;return!0}function u(e,t,n,r){switch(t){case"flag":return n(e,"\ud83c\udff3\ufe0f\u200d\u26a7\ufe0f","\ud83c\udff3\ufe0f\u200b\u26a7\ufe0f")?!1:!n(e,"\ud83c\udde8\ud83c\uddf6","\ud83c\udde8\u200b\ud83c\uddf6")&&!n(e,"\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc65\udb40\udc6e\udb40\udc67\udb40\udc7f","\ud83c\udff4\u200b\udb40\udc67\u200b\udb40\udc62\u200b\udb40\udc65\u200b\udb40\udc6e\u200b\udb40\udc67\u200b\udb40\udc7f");case"emoji":return!r(e,"\ud83e\u1fac8")}return!1}function f(e,t,n,r){let a;const s=(a="undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?new OffscreenCanvas(300,150):document.createElement("canvas")).getContext("2d",{willReadFrequently:!0}),o=(s.textBaseline="top",s.font="600 32px Arial",{});return e.forEach(e=>{o[e]=t(s,e,n,r)}),o}function a(e){var t=document.createElement("script");t.src=e,t.defer=!0,document.head.appendChild(t)}r.supports={everything:!0,everythingExceptFlag:!0},new Promise(t=>{let n=function(){try{var e=JSON.parse(sessionStorage.getItem(s));if("object"==typeof e&&"number"==typeof e.timestamp&&(new Date).valueOf()<e.timestamp+604800&&"object"==typeof e.supportTests)return e.supportTests}catch(e){}return null}();if(!n){if("undefined"!=typeof Worker&&"undefined"!=typeof OffscreenCanvas&&"undefined"!=typeof URL&&URL.createObjectURL&&"undefined"!=typeof Blob)try{var e="postMessage("+f.toString()+"("+[JSON.stringify(o),u.toString(),c.toString(),p.toString()].join(",")+"));",r=new Blob([e],{type:"text/javascript"});const a=new Worker(URL.createObjectURL(r),{name:"wpTestEmojiSupports"});return void(a.onmessage=e=>{i(n=e.data),a.terminate(),t(n)})}catch(e){}i(n=f(o,u,c,p))}t(n)}).then(e=>{for(const n in e)r.supports[n]=e[n],r.supports.everything=r.supports.everything&&r.supports[n],"flag"!==n&&(r.supports.everythingExceptFlag=r.supports.everythingExceptFlag&&r.supports[n]);var t;r.supports.everythingExceptFlag=r.supports.everythingExceptFlag&&!r.supports.flag,r.supports.everything||((t=r.source||{}).concatemoji?a(t.concatemoji):t.wpemoji&&t.twemoji&&(a(t.twemoji),a(t.wpemoji)))}); 4829//# sourceURL=https://www.rollingstone.de/wp-includes/js/wp-emoji-loader.min.js 4830</script>
4830 4831
4831<script type="text/javascript"> 4832 jQuery(document).ready(function($) { 4833 $('#outbrain_widget_container').html('<div class="rs-blocked-content-placeholder" data-category="content">' + 4834 '<div style="padding: 15px; background: #f5f5f5;">' + 4835 '</div></div>'); 4836 }); 4837 </script>
4837 4838
4838<script type="text/javascript" id="rs-contentpass-event-handlers"> 4839 (function() { 4840 // Extract root domain for cross-subdomain cookie sharing 4841 function getRootDomain() { 4842 const hostname = window.location.hostname; 4843 const parts = hostname.split('.'); 4844 4845 // If it's an IP address or localhost, use the hostname as-is 4846 if (hostname === 'localhost' || /^\d+\.\d+\.\d+\.\d+$/.test(hostname)) { 4847 return hostname; 4848 } 4849 4850 // For domains like www.rollingstone.de or cmk.rollingstone.de 4851 // return .rollingstone.de to enable cross-subdomain sharing 4852 if (parts.length >= 2) { 4853 return '.' + parts.slice(-2).join('.'); 4854 } 4855 4856 return hostname; 4857 } 4858 4859 const rootDomain = getRootDomain(); 4860 4861 // Listen for Sourcepoint CMP consent events 4862 var tcfApiAttempts = 0; 4863 var maxTcfApiAttempts = 10; 4864 var tcfApiCheckInterval = null; 4865 4866 function checkForTcfApi() { 4867 if (typeof window.__tcfapi === 'function') { 4868 clearInterval(tcfApiCheckInterval); 4869 setupTcfEventListeners(); 4870 } else { 4871 tcfApiAttempts++; 4872 if (tcfApiAttempts >= maxTcfApiAttempts) { 4873 clearInterval(tcfApiCheckInterval); 4874 } else { 4875 4876 } 4877 } 4878 } 4879 4880 function setupTcfEventListeners() { 4881 function processTCFData(tcData, success) { 4882 if (!success) return; 4883 var isRejectAll = false; 4884 4885 // Check if this is a reject-all action by examining the TCF data 4886 if (tcData.eventStatus === 'useractioncomplete') { 4887 // Check if all purpose consents are false (indicating a reject-all) 4888 if (tcData.purpose && tcData.purpose.consents) { 4889 var allConsentsRejected = true; 4890 for (var purposeId in tcData.purpose.consents) { 4891 if (tcData.purpose.consents[purposeId] === true) { 4892 allConsentsRejected = false; 4893 break; 4894 } 4895 } 4896 4897 // If previously had consent (cookie exists) and now all consents are rejected 4898 if (allConsentsRejected && (document.cookie.indexOf('rs_consent_given=true') !== -1 || 4899 sessionStorage.getItem('rs_consent_given') === 'true')) { 4900 isRejectAll = true; 4901 } 4902 } 4903 4904 // Check if consent was given 4905 var hasConsent = false; 4906 try { 4907 if (tcData.purpose && tcData.purpose.consents && tcData.purpose.consents[1] === true) { 4908 hasConsent = true; 4909 } 4910 } catch (e) { 4911 console.error('[RS Event Handler] Error checking consent status:', e); 4912 } 4913 4914 if (hasConsent) { 4915 if (window.rs_reload_scheduled) return; 4916 window.rs_reload_scheduled = true; 4917 4918 try { 4919 sessionStorage.setItem('rs_consent_given', 'true'); 4920 document.cookie = 'rs_consent_given=true; path=/; domain=' + rootDomain + '; max-age=86400'; 4921 4922 window.rs_consent_given = true; 4923 4924 const consentEvent = new CustomEvent('rs-consent-changed', { 4925 detail: { 4926 consented: true, 4927 timestamp: new Date().getTime() 4928 }, 4929 bubbles: true 4930 }); 4931 document.dispatchEvent(consentEvent); 4932 4933 /* setTimeout(function() { 4934 window.location.reload(); 4935 }, 100); */ 4936 } catch (e) { 4937 console.error('[RS Event Handler] Error handling consent:', e); 4938 window.rs_reload_scheduled = false;
4939 } 4940 } else if (isRejectAll) { 4941 // Handle explicit consent revocation (reject-all) 4942 if (window.rs_reload_scheduled) return; 4943 window.rs_reload_scheduled = true; 4944 4945 try { 4946 document.cookie = 'rs_consent_given=; path=/; domain=' + rootDomain + '; expires=Thu, 01 Jan 1970 00:00:01 GMT'; 4947 sessionStorage.removeItem('rs_consent_given'); 4948 // Reset window flag 4949 window.rs_consent_given = false; 4950 4951 // Also remove ContentPass authentication cookie 4952 document.cookie = 'rs_cp_authenticated=; path=/; domain=' + rootDomain + '; expires=Thu, 01 Jan 1970 00:00:01 GMT'; 4953 sessionStorage.removeItem('rs_cp_authenticated'); 4954 // Reset window flag if it exists 4955 if (typeof window.rs_cp_authenticated !== 'undefined') { 4956 window.rs_cp_authenticated = false; 4957 } 4958 4959 // Only reload if this is NOT from the Widerruf link click 4960 // Check for the flag we set in the consent.js file 4961 /* if (!window.widerrufActionInProgress) { 4962 setTimeout(function() { 4963 window.location.reload(); 4964 }, 100); */ 4965 /* } else { 4966 // Do nothing, we're already handling this 4967 } */ 4968 } catch (e) { 4969 console.error('[RS Event Handler] Error handling consent revocation:', e); 4970 window.rs_reload_scheduled = false; 4971 } 4972 } else { 4973 console.log('[RS Event Handler] User action completed without giving consent (not a revocation)'); 4974 } 4975 } 4976 } 4977 4978 // Listen for consent events (both initial load and user action) 4979 try { 4980 window.__tcfapi('addEventListener', 2, processTCFData); 4981 4982 if (!window.rs_tcf_initial_check_complete) { 4983 window.rs_tcf_initial_check_complete = true; 4984 window.__tcfapi('getTCData', 2, processTCFData); 4985 } 4986 } catch (e) { 4987 console.error('[RS Event Handler] Error setting up CMP event listeners:', e); 4988 } 4989 } 4990 4991 // Start checking for TCF API 4992 checkForTcfApi(); 4993 tcfApiCheckInterval = setInterval(checkForTcfApi, 500); 4994 document.addEventListener('rs-contentpass-logged-in', function(e) { 4995 window.rs_cp_authenticated = true; 4996 sessionStorage.setItem('rs_cp_authenticated', 'true'); 4997 4998 /* setTimeout(function() { 4999 window.location.reload(); 5000 }, 100); */ 5001 }); 5002 5003 // Listen for ContentPass token changes in localStorage 5004 window.addEventListener('storage', function(e) { 5005 if (e.key === 'cp_token' || e.key === 'cp.token') { 5006 var token = e.newValue; 5007 if (token) { 5008 try { 5009 var isValid = true; 5010 5011 if (token.split('.').length !== 3) { 5012 isValid = false; 5013 } 5014 5015 if (isValid) { 5016 console.log('[RS Event Handler] ContentPass token detected in localStorage, setting authentication flag and reloading page'); 5017 window.rs_cp_authenticated = true; 5018 sessionStorage.setItem('rs_cp_authenticated', 'true'); 5019 5020 /* setTimeout(function() { 5021 window.location.reload(); 5022 }, 100); */ 5023 } 5024 } catch (err) { 5025 console.error('[RS Event Handler] Error processing ContentPass token:', err); 5026 } 5027 } 5028 } 5029 }); 5030 5031 // Check if ContentPass token already exists on page load 5032 function checkExistingToken() { 5033 var token = localStorage.getItem('cp_token') || localStorage.getItem('cp.token'); 5034 if (token) { 5035 try { 5036 // Check if token is valid and not expired 5037 var isValid = true; 5038 5039 // Simple JWT validation - check if it has three parts 5040 if (token.split('.').length !== 3) { 5041 isValid = false;
5042 } 5043 5044 if (isValid) { 5045 window.rs_cp_authenticated = true; 5046 sessionStorage.setItem('rs_cp_authenticated', 'true'); 5047 5048 /* setTimeout(function() { 5049 window.location.reload(); 5050 }, 100); */ 5051 } 5052 } catch (err) { 5053 console.error('[RS Event Handler] Error processing existing ContentPass token:', err); 5054 } 5055 } 5056 } 5057 5058 // Check for existing token on page load 5059 checkExistingToken(); 5060 5061 document.addEventListener('rsContentPassAuthStatusChanged', function(event) { 5062 if (event.detail && typeof event.detail.isAuthenticated === 'boolean') { 5063 if (event.detail.isAuthenticated) { 5064 window.rs_cp_authenticated = true; 5065 sessionStorage.setItem('rs_cp_authenticated', 'true'); 5066 5067 // Set a cookie that the server can read (expires in 30 days) 5068 const expiryDate = new Date(); 5069 expiryDate.setDate(expiryDate.getDate() + 30); 5070 document.cookie = 'rs_cp_authenticated=true; expires=' + expiryDate.toUTCString() + '; path=/; domain=' + rootDomain + '; SameSite=Lax'; 5071 } else { 5072 // Clear ContentPass authentication on logout 5073 window.rs_cp_authenticated = false; 5074 sessionStorage.removeItem('rs_cp_authenticated'); 5075 document.cookie = 'rs_cp_authenticated=; path=/; domain=' + rootDomain + '; expires=Thu, 01 Jan 1970 00:00:01 GMT'; 5076 5077 } 5078 } 5079 }); 5080 5081 /** 5082 * Kajomi Newsletter Consent Handler 5083 * Creates iframe directly (avoids document.write issues after page load) 5084 */ 5085 (function() { 5086 5087 var kajomiProcessed = false; 5088 5089 function hasConsent() { 5090 return window.rs_consent_given === true || 5091 document.cookie.indexOf('rs_consent_given=true') !== -1 || 5092 (typeof sessionStorage !== 'undefined' && sessionStorage.getItem('rs_consent_given') === 'true'); 5093 } 5094 5095 function showKajomiForms() { 5096 if (kajomiProcessed) { 5097 return; 5098 } 5099 5100 var placeholders = document.querySelectorAll('.kajomi-newsletter-placeholder'); 5101 5102 if (placeholders.length === 0) return; 5103 5104 kajomiProcessed = true; 5105 5106 placeholders.forEach(function(placeholder) { 5107 var contentEl = placeholder.nextElementSibling; 5108 5109 if (!contentEl || !contentEl.classList.contains('kajomi-newsletter-content')) { 5110 contentEl = placeholder.parentNode.querySelector('.kajomi-newsletter-content'); 5111 } 5112 5113 if (!contentEl) { 5114 console.error('[Kajomi Consent] Content element not found'); 5115 return; 5116 } 5117 5118 // Hide the placeholder 5119 placeholder.style.display = 'none'; 5120 5121 // Get Kajomi config from data attributes 5122 var domain = contentEl.getAttribute('data-kajomi-domain'); 5123 var formId = contentEl.getAttribute('data-kajomi-id'); 5124 var width = contentEl.getAttribute('data-kajomi-width') || '100%'; 5125 var height = contentEl.getAttribute('data-kajomi-height') || '234px'; 5126 5127 5128 if (!domain || !formId) { 5129 console.error('[Kajomi Consent] Missing domain or formId'); 5130 return; 5131 } 5132 var iframeId = 'f' + formId + '_' + Math.random().toString(36).substr(2, 6); 5133 5134 // Build iframe URL (same pattern as KajomiLandingPage.write()) 5135 var resizeParam = encodeURIComponent(window.location.href); 5136 var iframeSrc = '//' + domain + '/l/' + formId + '.html?_resize_frame=' + resizeParam; 5137 5138 // Create the iframe directly 5139 var iframe = document.createElement('iframe'); 5140 iframe.id = iframeId; 5141 iframe.src = iframeSrc; 5142 iframe.title = 'Formular'; 5143 iframe.width = width; 5144 iframe.height = height; 5145 iframe.scrolling = 'no'; 5146 iframe.style.cssText = 'background-color:transparent;border:none;position:relative;overflow:hidden;'; 5147 5148 placeholder.parentNode.insertBefore(iframe, contentEl); 5149 5150 if (!document.querySelector('script[src*="app_kajomi_helper"]')) { 5151 var script = document.createElement('script'); 5152 script.src = '//nextgen.kajomigenerator.de/static/js/app_kajomi_helper.js?4'; 5153 document.head.appendChild(script); 5154 } 5155 5156 if (contentEl.parentNode) { 5157 contentEl.parentNode.removeChild(contentEl); 5158 } 5159 5160 }); 5161 } 5162 5163 document.addEventListener('rs-consent-changed', function(event) { 5164 if (event.detail && event.detail.consented === true) { 5165 showKajomiForms(); 5166 } 5167 }); 5168 5169 if (hasConsent()) { 5170 if (document.readyState === 'complete' || document.readyState === 'interactive') { 5171 setTimeout(showKajomiForms, 100); 5172 } else { 5173 document.addEventListener('DOMContentLoaded', function() { 5174 setTimeout(showKajomiForms, 100); 5175 }); 5176 } 5177 } 5178 })(); 5179 5180 })(); 5181 </script>
5181 5182 <style> 5183 .rs-blocked-link-wrapper, 5184 .rs-blocked-image-wrapper { 5185 margin: 1rem 0; 5186 padding: 1rem; 5187 background: #f8f8f8; 5188 border: 1px solid #ddd; 5189 border-radius: 4px; 5190 text-align: center; 5191 } 5192 5193 .rs-tracking-pixel { 5194 display: none !important; 5195 } 5196 5197 .rs-blocked-link-placeholder, 5198 .rs-blocked-image-placeholder { 5199 display: flex; 5200 align-items: center; 5201 justify-content: center; 5202 gap: 0.5rem; 5203 color: #666; 5204 font-size: 0.9rem; 5205 } 5206 5207 .rs-blocked-icon { 5208 font-size: 1.5rem; 5209 } 5210 5211 .rs-blocked-message { 5212 font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; 5213 } 5214 5215 .rs-blocked-original-content { 5216 display: none; 5217 } 5218 </style> 5219 5220
5220<script type="text/javascript" id="rs-content-filter-unwrap"> 5221 (function() { 5222 'use strict'; 5223 var initialBlocked = document.querySelectorAll('[data-rs-blocked="true"]'); 5224 5225 /** 5226 * Unwrap blocked content based on consent status 5227 */ 5228 function unwrapBlockedContent() { 5229 if (typeof window.rs_check_consent_status !== 'function') { 5230 return; 5231 } 5232 5233 var hasConsent = window.rs_check_consent_status(); 5234 var isAuthenticated = window.rs_cp_authenticated === true; 5235 5236 if (!hasConsent && !isAuthenticated) { 5237 return; 5238 } 5239 5240 var wrappers = document.querySelectorAll('[data-rs-blocked="true"]'); 5241 5242 wrappers.forEach(function(wrapper) { 5243 var category = wrapper.getAttribute('data-rs-category'); 5244 var type = wrapper.getAttribute('data-rs-type'); 5245 5246 var shouldUnwrap = false; 5247 5248 if (hasConsent) { 5249 shouldUnwrap = true; 5250 } else if (isAuthenticated && category === 'content') { 5251 shouldUnwrap = true; 5252 } 5253 5254 if (!shouldUnwrap) { 5255 return; 5256 } 5257 5258 var originalContainer = wrapper.querySelector('.rs-blocked-original-content'); 5259 5260 if (!originalContainer) { 5261 return; 5262 } 5263 var originalElement = originalContainer.firstElementChild; 5264 5265 if (!originalElement) { 5266 return; 5267 } 5268 5269 var restoredElement = originalElement.cloneNode(true); 5270 5271 if (type === 'link') { 5272 var originalHref = wrapper.getAttribute('data-rs-original-href'); 5273 if (originalHref && restoredElement.tagName.toLowerCase() === 'a') { 5274 restoredElement.setAttribute('href', originalHref); 5275 } 5276 var blockedHref = restoredElement.getAttribute('data-blocked-href'); 5277 if (blockedHref) { 5278 restoredElement.setAttribute('href', blockedHref); 5279 restoredElement.removeAttribute('data-blocked-href'); 5280 } 5281 } 5282 5283 if (type === 'image') { 5284 var originalSrc = wrapper.getAttribute('data-rs-original-src'); 5285 if (originalSrc && restoredElement.tagName.toLowerCase() === 'img') { 5286 restoredElement.setAttribute('src', originalSrc); 5287 } 5288 var blockedSrc = restoredElement.getAttribute('data-blocked-src'); 5289 if (blockedSrc) { 5290 restoredElement.setAttribute('src', blockedSrc); 5291 restoredElement.removeAttribute('data-blocked-src'); 5292 } 5293 } 5294 5295 wrapper.parentNode.replaceChild(restoredElement, wrapper); 5296 }); 5297 } 5298 5299 /** 5300 * Initialize unwrapper 5301 */ 5302 function initUnwrapper() { 5303 unwrapBlockedContent(); 5304 5305 document.addEventListener('rs-consent-changed', function(e) { 5306 setTimeout(unwrapBlockedContent, 100); 5307 }); 5308 document.addEventListener('rsContentPassAuthStatusChanged', function(e) { 5309 setTimeout(unwrapBlockedContent, 100); 5310 }); 5311 setTimeout(unwrapBlockedContent, 1000); 5312 } 5313 5314 // Initialize when DOM is ready 5315 if (document.readyState === 'loading') { 5316 document.addEventListener('DOMContentLoaded', initUnwrapper); 5317 } else { 5318 initUnwrapper(); 5319 } 5320 5321 })(); 5322 </script>
5322 5323
5323<script> 5324 document.addEventListener('DOMContentLoaded', function() { 5325 if (typeof AdController !== 'undefined') { 5326 AdController.finalize(); 5327 } 5328 }); 5329 window.IQDComplete = { 5330 init: function() { 5331 IQDTracker.log('COMPLETE', 'IQDComplete signal initialized'); 5332 return true; 5333 } 5334 }; 5335 5336 window.addEventListener('load', () => { 5337 setTimeout(() => { 5338 if (typeof window.IQDComplete.init === 'function') { 5339 window.IQDComplete.init(); 5340 IQDTracker.log('COMPLETE', 'Page load signal sent successfully'); 5341 } 5342 }, 100); 5343 }); 5344 </script>
5344 5345
5345<script type="text/javascript" data-description="sourcepoint stub code"> 5346 function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}!function(){for(var t,e,o=[],n=window,r=n;r;){try{if(r.frames.__tcfapiLocator){t=r;break}}catch(t){}if(r===n.top)break;r=n.parent}t||(function t(){var e=n.document,o=!!n.frames.__tcfapiLocator;if(!o)if(e.body){var r=e.createElement("iframe");r.style.cssText="display:none",r.name="__tcfapiLocator",e.body.appendChild(r)}else setTimeout(t,5);return!o}(),n.__tcfapi=function(){for(var t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];if(!n.length)return o;"setGdprApplies"===n[0]?n.length>3&&2===parseInt(n[1],10)&&"boolean"==typeof n[3]&&(e=n[3],"function"==typeof n[2]&&n[2]("set",!0)):"ping"===n[0]?"function"==typeof n[2]&&n[2]({gdprApplies:e,cmpLoaded:!1,cmpStatus:"stub"}):o.push(n)},n.addEventListener("message",(function(t){var e="string"==typeof t.data,o={};if(e)try{o=JSON.parse(t.data)}catch(t){}else o=t.data;var n="object"===_typeof(o)?o.__tcfapiCall:null;n&&window.__tcfapi(n.command,n.version,(function(o,r){var a={__tcfapiReturn:{returnValue:o,success:r,callId:n.callId}};t&&t.source&&t.source.postMessage&&t.source.postMessage(e?JSON.stringify(a):a,"*")}),n.parameter)}),!1))}(); 5347</script>
5347 5348
5349<script type="text/javascript" data-description="sourcepoint configuration"> 5350 window._sp_ = { 5351 config: { 5352 // Please include your existing accountId as provided by Sourcepoint 5353 accountId: 1924, 5354 // Sourcepoint base endpoint, no change needed â Sourcepoint recommends to only use a single endpoint 5355 // https://documentation.sourcepoint.com/implementation/web-implementation/multi-campaign-web-implementation/best-practices-improve-gdpr-tcf-v2-message-loading#leverage-single-server-endpoint 5356 baseEndpoint: 'https://cdn.privacy-mgmt.com', 5357 // other possible Sourcepoint configurations 5358 // ... 5359 // New: The isSPA setting is needed to make sure the Sourcepoint scenario starts after executeMessaging() is called below 5360 isSPA: true, 5361 // New: This "acps" targeting parameter is being used to not display the layer for contentpass users 5362 // If you already use targetingParams, please make sure to extend the object accordingly 5363 gdpr: { 5364 targetingParams: { 5365 acps: 'false' 5366 }, 5367 }, 5368 } 5369 }; 5370</script>
5370 5371
5372<script type="text/javascript" src="https://cdn.privacy-mgmt.com/unified/wrapperMessagingWithoutDetection.js"></script>
5372 5373
5374<script type="text/javascript" data-description="contentpass integration"> 5375 (function() { 5376 var cpBaseUrl = 'https://cp.rollingstone.de'; 5377 var cpController = cpBaseUrl + '/now.js'; 5378 var cpPropertyId = 'a63d3ff8'; 5379 5380 !function(C,o,n,t,P,a,s){C.CPObject=n,C[n]||(C[n]=function(){ 5381 for(var e=arguments.length,i=new Array(e),c=0;c<e;c++)i[c]=arguments[c];const[r,u,l]=i;if(C[n].q||(C[n].q=[]), 5382 t=Array.prototype.slice.call(arguments,0),!C[n].patched&&("fatal"===r&&u&&(C[n].le=u, 5383 Array.prototype.forEach.call(C[n].q,(function(e){"error"===e[0]&&"function"==typeof e[1]&&e[1](u)}))), 5384 "error"===r&&"function"==typeof u&&C[n].le&&u(C[n].le),"extension"===r&&u&&l&&"function"==typeof l.init&&(l.init(), 5385 l.initialized=!0),"authenticate"===r&&u)){try{ 5386 P=-1===(o.cookie||"").indexOf("_cpauthhint=")&&!(C.localStorage||{})._cpuser&&-1===C.location.href.toLowerCase().indexOf("cpauthenticated") 5387 }catch(e){P=!1}P&&(a={isLoggedIn:function(){return!1},hasValidSubscription:function(){return!1}}, 5388 "function"==typeof u&&u(null,a),t=["authenticate",null])}C[n].q.push(t)});try{ 5389 ((s=(o.cookie.split("_cpauthhint=")[1]||"").split(";")[0])?Number(s[1]):NaN)>0&&(o.body?o.body.classList.add("cpauthenticated"):o.addEventListener("DOMContentLoaded",(function(){ 5390 o.body.classList.add("cpauthenticated")})))}catch(e){}C[n].l=+new Date,C[n].sv=5}(window,document,"cp"); 5391 5392 // Will activate contentpass and initialize basic interfaces for 5393 // communicating with contentpass. 5394 cp('create', cpPropertyId, { 5395 baseUrl: cpBaseUrl 5396 }); 5397 5398 // This function will trigger rendering of the Sourcepoint consent layer. First, it will check 5399 // whether the current user is an authenticated contentpass user. If so, the targeting parameter 5400 // acps is set to the string value 'true' (important: the value is not a bool, but a string!). 5401 // If the user is not an authenticated contentpass user, the targeting parameter is set to 5402 // 'false'. Make sure to not show the consent layer when the targeting parameter is set to 'true' 5403 // in your Sourcepoint scenario. When login status is determined, Sourcepoint is automatically 5404 // triggered by calling window._sp_.executeMessaging(). 5405 cp('render', { 5406 onFullConsent: function() { 5407 console.log('[CP] onFullConsent'); 5408 // Init advertising here 5409 // 5410 // Attention: 5411 // When you update your vendor list without asking for re-consent 5412 // then Sourcepoint does not signal full consent for previously 5413 // fully consented visitors. Thus this callback is not executed,
5414 // and partially consented impressions are not monetized at all! 5415 // 5416 // We therefore strongly recommend to configure your Sourcepoint 5417 // scenario setup to always ask for re-consent on vendor updates. 5418 // 5419 // Alternatively you can always load vendors specifically based 5420 // on their respective consent status according to the TCF API. 5421 // You can find a sample integration for this on 5422 // https://docs.contentpass.net/docs/3rdparty 5423 } 5424 }) 5425 })() 5426</script>
5426 5427
5428<script src="https://cp.rollingstone.de/now.js" async fetchPriority="high" onerror="cp('fatal', arguments)"></script>
5428 5429
5430<script type="text/javascript" data-description="contentpass tealium integration"> 5431(function () { 5432 // ContentPass Third Party Resource Loading for Tealium 5433 // This follows the pattern from ContentPass documentation 5434 cp('authenticate', function (err, user) { 5435 if (err || (!user.isLoggedIn() || !user.hasValidSubscription())) { 5436 // Load Tealium for users who are not ContentPass subscribers 5437 // This executes immediately and independently of consent status 5438 console.log('[CP-Tealium] User is not a ContentPass subscriber'); 5439 5440 if (window.tealiumContentPassController) { 5441 window.tealiumContentPassController.handleAuthentication(false); 5442 } else { 5443 console.warn('[CP-Tealium] Tealium controller not available'); 5444 } 5445 } else { 5446 console.log('[CP-Tealium] User is a ContentPass subscriber, Tealium will not be loaded'); 5447 5448 if (window.tealiumContentPassController) { 5449 window.tealiumContentPassController.handleAuthentication(true); 5450 } 5451 } 5452 }); 5453})(); 5454</script>
5454 5455
5456<script type="text/javascript" data-description="contentpass sourcepoint authenticate usage"> 5457(function () { 5458 cp('authenticate', function(err, user) { 5459 if (err || (!user.isLoggedIn() && !user.hasValidSubscription())) { 5460 (function spExecMsg() { 5461 if (window._sp_ && window._sp_.executeMessaging) { 5462 if (!window._sp_.config.isSPA) { 5463 console.warn('[SPCP] Sourcepoint not in SPA mode!'); 5464 } else if (window._sp_.version) { 5465 console.log('[SPCP] Sourcepoint already running'); 5466 } else { 5467 console.log('[SPCP] Starting Sourcepoint'); 5468 window._sp_.executeMessaging(); 5469 } 5470 } else { 5471 console.log('[SPCP] Sourcepoint not loaded yet. Retrying.'); 5472 setTimeout(spExecMsg, 10); 5473 } 5474 })(); 5475 } 5476 }); 5477})(); 5478</script>
5478 5479<div class="social-sharing-popup__container"> 5480 <div class="social-sharing-popup__headline">Deine Datensicherheit bei der Nutzung der Teilen-Funktion</div> 5481 <div class="social-sharing-popup__description">Um diesen Artikel oder andere Inhalte über Soziale-Netzwerke zu teilen, brauchen wir deine Zustimmung für <a href="#" aria-label="Open modal with third party info" class="social-sharing-popup__description--pm-link">diesen Zweck der Datenverarbeitung</a></div> 5482 <div class="social-sharing-popup__button-container"> 5483 <button class="social-sharing-popup__button social-sharing-popup__button--close">SchlieÃen</button> 5484 <button class="social-sharing-popup__button social-sharing-popup__button--accept">Akzeptieren</button> 5485 </div> 5486</div> 5487
5487<script type="text/javascript" id="contentpass-auth-listener"> 5488 (function() { 5489 // Extract root domain for cross-subdomain cookie sharing 5490 function getRootDomain() { 5491 const hostname = window.location.hostname; 5492 const parts = hostname.split('.'); 5493 5494 // If it's an IP address or localhost, use the hostname as-is 5495 if (hostname === 'localhost' || /^\d+\.\d+\.\d+\.\d+$/.test(hostname)) { 5496 return hostname; 5497 } 5498 5499 // For domains like www.rollingstone.de or cmk.rollingstone.de 5500 // return .rollingstone.de to enable cross-subdomain sharing 5501 if (parts.length >= 2) { 5502 return '.' + parts.slice(-2).join('.'); 5503 } 5504 5505 return hostname; 5506 } 5507 5508 const rootDomain = getRootDomain(); 5509 5510 // Initialize global object to store ContentPass status 5511 window.rsContentPass = window.rsContentPass || { 5512 isAuthenticated: false, 5513 authChecked: false 5514 }; 5515 5516 const hasEarlyAuth = sessionStorage.getItem('rs_cp_authenticated') === 'true' || 5517 localStorage.getItem('cp_token') || 5518 localStorage.getItem('cp.token'); 5519 5520 if (hasEarlyAuth) { 5521 window.rsContentPass.isAuthenticated = true; 5522 window.rsContentPass.authChecked = true; 5523 if (window.tealiumContentPassController) { 5524 window.tealiumContentPassController.handleAuthentication(true); 5525 } 5526 5527 // Dispatch event for other scripts to listen for 5528 const event = new CustomEvent('rsContentPassAuthStatusChanged', { 5529 detail: { isAuthenticated: true } 5530 }); 5531 document.dispatchEvent(event); 5532 5533 // Set both sessionStorage and cookie for authentication 5534 sessionStorage.setItem('rs_cp_authenticated', 'true'); 5535 window.rs_cp_authenticated = true; 5536 5537 const expiryDate = new Date(); 5538 expiryDate.setDate(expiryDate.getDate() + 30); 5539 document.cookie = 'rs_cp_authenticated=true; expires=' + expiryDate.toUTCString() + '; path=/; domain=' + rootDomain + '; SameSite=Lax'; 5540 5541 return; 5542 } 5543 5544 function handleUserStatus(err, user) { 5545 if (err) { 5546 window.rsContentPass.authChecked = true; 5547 if (window.tealiumContentPassController) { 5548 window.tealiumContentPassController.handleAuthentication(false); 5549 } 5550 return; 5551 } 5552 if (user && typeof user.isLoggedIn === 'function' && typeof user.hasValidSubscription === 'function') { 5553 const isAuthenticated = user.isLoggedIn() && user.hasValidSubscription(); 5554 window.rsContentPass.isAuthenticated = isAuthenticated; 5555 window.rsContentPass.authChecked = true; 5556 // Notify Tealium controller 5557 if (window.tealiumContentPassController) { 5558 window.tealiumContentPassController.handleAuthentication(isAuthenticated); 5559 } 5560 5561 // Dispatch event for other scripts to listen for 5562 const event = new CustomEvent('rsContentPassAuthStatusChanged', { 5563 detail: { isAuthenticated: isAuthenticated } 5564 }); 5565 document.dispatchEvent(event); 5566 5567 if (isAuthenticated) { 5568 sessionStorage.setItem('rs_cp_authenticated', 'true'); 5569 window.rs_cp_authenticated = true; 5570 5571 // Set a cookie that the server can read (expires in 30 days) 5572 const expiryDate = new Date(); 5573 expiryDate.setDate(expiryDate.getDate() + 30); 5574 document.cookie = 'rs_cp_authenticated=true; expires=' + expiryDate.toUTCString() + '; path=/; domain=' + rootDomain + '; SameSite=Lax'; 5575 if (hasEarlyAuth) { 5576 } /* else { 5577 window.location.reload(); 5578 } */ 5579 } else if (user.isLoggedIn()) { 5580 console.log('[CP Authenticate] User is logged in but does NOT have a valid subscription.'); 5581 } else { 5582 console.log('[CP Authenticate] User is NOT logged in.'); 5583 } 5584 } else { 5585 console.warn('[CP Authenticate] User object or expected methods not available for status check.', user); 5586 window.rsContentPass.authChecked = true; 5587 if (window.tealiumContentPassController) { 5588 window.tealiumContentPassController.handleAuthentication(false); 5589 } 5590 } 5591 } 5592 5593 function tryAuthenticate() { 5594 if (typeof cp === 'function') { 5595 cp('authenticate', handleUserStatus); 5596 cp('on', 'auth', function(event) { 5597 if ( 5598 event && event.user && 5599 typeof event.user.isLoggedIn === 'function' && 5600 typeof event.user.hasValidSubscription === 'function' 5601 ) { 5602 // Update the global status object when auth status changes 5603 const isAuthenticated = event.user.isLoggedIn() && event.user.hasValidSubscription(); 5604 5605 // Only update and dispatch event if status changed 5606 if (window.rsContentPass.isAuthenticated !== isAuthenticated) { 5607 window.rsContentPass.isAuthenticated = isAuthenticated; 5608 // Notify Tealium controller of status change 5609 if (window.tealiumContentPassController) { 5610 window.tealiumContentPassController.handleAuthentication(isAuthenticated); 5611 } 5612 // Dispatch event for other scripts to listen for 5613 const statusEvent = new CustomEvent('rsContentPassAuthStatusChanged', { 5614 detail: { isAuthenticated: isAuthenticated } 5615 }); 5616 document.dispatchEvent(statusEvent); 5617 5618 // Update session storage 5619 if (isAuthenticated) { 5620 try { 5621 sessionStorage.setItem('rs_cp_authenticated', 'true'); 5622 } catch (e) { 5623 console.error('[CP Authenticate] Error setting sessionStorage:', e); 5624 } 5625 } 5626 } 5627 5628 if (isAuthenticated) { 5629 console.log('[CP Authenticate] "auth" event: User is authenticated (logged in and valid subscription).'); 5630 } else if (event.user.isLoggedIn()) { 5631 console.log('[CP Authenticate] "auth" event: User is logged in but does NOT have a valid subscription.'); 5632 } else { 5633 console.log('[CP Authenticate] "auth" event: User is NOT logged in.'); 5634 } 5635 } else { 5636 console.warn('[CP Authenticate] "auth" event: User object or expected methods not available.', event); 5637 } 5638 }); 5639 } else { 5640 console.warn('[CP Authenticate] cp SDK not available.'); 5641 window.rsContentPass.authChecked = true; 5642 } 5643 } 5644 5645 if (document.readyState === 'complete' || document.readyState === 'interactive') { 5646 tryAuthenticate(); 5647 } else { 5648 window.addEventListener('DOMContentLoaded', tryAuthenticate); 5649 } 5650 })(); 5651 </script>
5651 5652 5653</body> 5654 5655</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.