[{"data":1,"prerenderedAt":734},["ShallowReactive",2],{"navigation_docs":3,"-analytics":68,"-analytics-surround":729},[4,30,36,62],{"title":5,"path":6,"stem":7,"children":8},"Get started","\u002Fget-started","1.get-started\u002F0.index",[9,10,14,18,22,26],{"title":5,"path":6,"stem":7},{"title":11,"path":12,"stem":13},"Create a podcast","\u002Fget-started\u002Fcreate-podcast","1.get-started\u002F1.create-podcast",{"title":15,"path":16,"stem":17},"Add an episode","\u002Fget-started\u002Fadd-episode","1.get-started\u002F2.add-episode",{"title":19,"path":20,"stem":21},"Make an episode page","\u002Fget-started\u002Fepisode-page","1.get-started\u002F3.episode-page",{"title":23,"path":24,"stem":25},"Check and share the feed","\u002Fget-started\u002Ffeed","1.get-started\u002F4.feed",{"title":27,"path":28,"stem":29},"Submit to podcast directories","\u002Fget-started\u002Fdirectories","1.get-started\u002F5.directories",{"title":31,"path":32,"stem":33,"children":34},"Analytics","\u002Fanalytics","2.analytics\u002F0.index",[35],{"title":31,"path":32,"stem":33},{"title":37,"path":38,"stem":39,"children":40},"Site building","\u002Fsite-building","3.site-building\u002F0.index",[41,42,46,50,54,58],{"title":37,"path":38,"stem":39},{"title":43,"path":44,"stem":45},"Permissions","\u002Fsite-building\u002Fpermissions","3.site-building\u002F1.permissions",{"title":47,"path":48,"stem":49},"Troubleshooting","\u002Fsite-building\u002Ftroubleshooting","3.site-building\u002F2.troubleshooting",{"title":51,"path":52,"stem":53},"Customize the feed","\u002Fsite-building\u002Ffeed","3.site-building\u002F3.feed",{"title":55,"path":56,"stem":57},"Fields and display","\u002Fsite-building\u002Ffields-and-display","3.site-building\u002F4.fields-and-display",{"title":59,"path":60,"stem":61},"Update and uninstall","\u002Fsite-building\u002Fupdates","3.site-building\u002F5.updates",{"title":63,"path":64,"stem":65,"children":66},"Contribute","\u002Fcontribute","4.contribute\u002F0.index",[67],{"title":63,"path":64,"stem":65},{"id":69,"title":31,"body":70,"description":722,"extension":723,"links":724,"meta":725,"navigation":726,"path":32,"seo":727,"stem":33,"__hash__":728},"docs\u002F2.analytics\u002F0.index.md",{"type":71,"value":72,"toc":711},"minimark",[73,90,93,98,101,112,127,138,143,166,385,392,410,414,431,470,481,485,488,491,495,502,518,529,533,595,602,607,625,629,648,654,659,666,670,696,707],[74,75,76,80,81,84,85,89],"p",{},[77,78,79],"strong",{},"Podcast Publisher Analytics"," is an optional module labeled ",[77,82,83],{},"Alpha"," in Drupal's podcast menu. It records ",[86,87,88],"em",{},"download intents"," for episode audio and adds a per-podcast report. It is not a listener count or a measure of how much audio someone played.",[74,91,92],{},"Download intent records are stored in your Drupal database, and location lookup uses a local GeoLite2 database. You manage this data as part of your own site, including its access, backups, and retention.",[94,95,97],"h2",{"id":96},"_1-install-the-geolite2-city-database","1. Install the GeoLite2 City database",[74,99,100],{},"The analytics module checks for this exact file when it is enabled:",[102,103,109],"pre",{"className":104,"code":106,"language":107,"meta":108},[105],"language-text","web\u002Flibraries\u002Fgeolite2\u002FGeoLite2-City.mmdb\n","text","",[110,111,106],"code",{"__ignoreMap":108},[74,113,114,115,118,119,122,123,126],{},"If your web root is not ",[110,116,117],{},"web",", use ",[110,120,121],{},"libraries\u002Fgeolite2\u002FGeoLite2-City.mmdb"," inside your web root. Without the file, Drupal refuses to enable the module with the message ",[86,124,125],{},"GeoLite2 City Database must be downloaded to the libraries folder",".",[74,128,129,130,137],{},"The GeoLite2 data is published by MaxMind under the ",[131,132,136],"a",{"href":133,"rel":134},"https:\u002F\u002Fwww.maxmind.com\u002Fen\u002Fgeolite2\u002Feula",[135],"nofollow","GeoLite2 End User License Agreement",". Check that your use complies with it.",[139,140,142],"h3",{"id":141},"option-a-composer","Option A: Composer",[74,144,145,146,149,150,153,154,157,158,161,162,165],{},"Add a package repository for the database to your project's ",[110,147,148],{},"composer.json",". Composer installs it as a Drupal library and extracts it to the path above, provided your ",[110,151,152],{},"installer-paths"," map ",[110,155,156],{},"type:drupal-library"," to ",[110,159,160],{},"web\u002Flibraries\u002F{$name}",", as the ",[110,163,164],{},"drupal\u002Frecommended-project"," template does.",[102,167,171],{"className":168,"code":169,"language":170,"meta":108,"style":108},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\"repositories\": [\n    {\n        \"type\": \"package\",\n        \"package\": {\n            \"name\": \"podcast-publisher-analytics\u002Fgeolite2\",\n            \"version\": \"1.0.0\",\n            \"type\": \"drupal-library\",\n            \"dist\": {\n                \"url\": \"https:\u002F\u002Fcdn.jsdelivr.net\u002Fnpm\u002Fgeolite2-city@latest\u002FGeoLite2-City.mmdb.gz\",\n                \"type\": \"gzip\"\n            }\n        }\n    }\n]\n","json",[110,172,173,195,201,227,241,264,285,305,319,342,361,367,373,379],{"__ignoreMap":108},[174,175,178,182,186,188,192],"span",{"class":176,"line":177},"line",1,[174,179,181],{"class":180},"sMK4o","\"",[174,183,185],{"class":184},"sfazB","repositories",[174,187,181],{"class":180},[174,189,191],{"class":190},"sTEyZ",": ",[174,193,194],{"class":180},"[\n",[174,196,198],{"class":176,"line":197},2,[174,199,200],{"class":180},"    {\n",[174,202,204,207,211,213,216,219,222,224],{"class":176,"line":203},3,[174,205,206],{"class":180},"        \"",[174,208,210],{"class":209},"spNyl","type",[174,212,181],{"class":180},[174,214,215],{"class":180},":",[174,217,218],{"class":180}," \"",[174,220,221],{"class":184},"package",[174,223,181],{"class":180},[174,225,226],{"class":180},",\n",[174,228,230,232,234,236,238],{"class":176,"line":229},4,[174,231,206],{"class":180},[174,233,221],{"class":209},[174,235,181],{"class":180},[174,237,215],{"class":180},[174,239,240],{"class":180}," {\n",[174,242,244,247,251,253,255,257,260,262],{"class":176,"line":243},5,[174,245,246],{"class":180},"            \"",[174,248,250],{"class":249},"sBMFI","name",[174,252,181],{"class":180},[174,254,215],{"class":180},[174,256,218],{"class":180},[174,258,259],{"class":184},"podcast-publisher-analytics\u002Fgeolite2",[174,261,181],{"class":180},[174,263,226],{"class":180},[174,265,267,269,272,274,276,278,281,283],{"class":176,"line":266},6,[174,268,246],{"class":180},[174,270,271],{"class":249},"version",[174,273,181],{"class":180},[174,275,215],{"class":180},[174,277,218],{"class":180},[174,279,280],{"class":184},"1.0.0",[174,282,181],{"class":180},[174,284,226],{"class":180},[174,286,288,290,292,294,296,298,301,303],{"class":176,"line":287},7,[174,289,246],{"class":180},[174,291,210],{"class":249},[174,293,181],{"class":180},[174,295,215],{"class":180},[174,297,218],{"class":180},[174,299,300],{"class":184},"drupal-library",[174,302,181],{"class":180},[174,304,226],{"class":180},[174,306,308,310,313,315,317],{"class":176,"line":307},8,[174,309,246],{"class":180},[174,311,312],{"class":249},"dist",[174,314,181],{"class":180},[174,316,215],{"class":180},[174,318,240],{"class":180},[174,320,322,325,329,331,333,335,338,340],{"class":176,"line":321},9,[174,323,324],{"class":180},"                \"",[174,326,328],{"class":327},"sbssI","url",[174,330,181],{"class":180},[174,332,215],{"class":180},[174,334,218],{"class":180},[174,336,337],{"class":184},"https:\u002F\u002Fcdn.jsdelivr.net\u002Fnpm\u002Fgeolite2-city@latest\u002FGeoLite2-City.mmdb.gz",[174,339,181],{"class":180},[174,341,226],{"class":180},[174,343,345,347,349,351,353,355,358],{"class":176,"line":344},10,[174,346,324],{"class":180},[174,348,210],{"class":327},[174,350,181],{"class":180},[174,352,215],{"class":180},[174,354,218],{"class":180},[174,356,357],{"class":184},"gzip",[174,359,360],{"class":180},"\"\n",[174,362,364],{"class":176,"line":363},11,[174,365,366],{"class":180},"            }\n",[174,368,370],{"class":176,"line":369},12,[174,371,372],{"class":180},"        }\n",[174,374,376],{"class":176,"line":375},13,[174,377,378],{"class":180},"    }\n",[174,380,382],{"class":176,"line":381},14,[174,383,384],{"class":180},"]\n",[74,386,387,388,391],{},"Keep your existing repositories, such as ",[110,389,390],{},"https:\u002F\u002Fpackages.drupal.org\u002F8",", in the same list. Then run:",[102,393,397],{"className":394,"code":395,"language":396,"meta":108,"style":108},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","composer require podcast-publisher-analytics\u002Fgeolite2\n","bash",[110,398,399],{"__ignoreMap":108},[174,400,401,404,407],{"class":176,"line":177},[174,402,403],{"class":249},"composer",[174,405,406],{"class":184}," require",[174,408,409],{"class":184}," podcast-publisher-analytics\u002Fgeolite2\n",[139,411,413],{"id":412},"option-b-manual-download","Option B: Manual download",[74,415,416,417,420,421,424,425,430],{},"Download the ",[77,418,419],{},"GeoLite2 City"," database in binary ",[110,422,423],{},".mmdb"," format, either from your ",[131,426,429],{"href":427,"rel":428},"https:\u002F\u002Fdev.maxmind.com\u002Fgeoip\u002Fgeolite2-free-geolocation-data\u002F",[135],"MaxMind account"," or from the mirror used above. Then place it in the libraries directory:",[102,432,434],{"className":394,"code":433,"language":396,"meta":108,"style":108},"mkdir -p web\u002Flibraries\u002Fgeolite2\ncurl -L https:\u002F\u002Fcdn.jsdelivr.net\u002Fnpm\u002Fgeolite2-city@latest\u002FGeoLite2-City.mmdb.gz | gunzip > web\u002Flibraries\u002Fgeolite2\u002FGeoLite2-City.mmdb\n",[110,435,436,447],{"__ignoreMap":108},[174,437,438,441,444],{"class":176,"line":177},[174,439,440],{"class":249},"mkdir",[174,442,443],{"class":184}," -p",[174,445,446],{"class":184}," web\u002Flibraries\u002Fgeolite2\n",[174,448,449,452,455,458,461,464,467],{"class":176,"line":197},[174,450,451],{"class":249},"curl",[174,453,454],{"class":184}," -L",[174,456,457],{"class":184}," https:\u002F\u002Fcdn.jsdelivr.net\u002Fnpm\u002Fgeolite2-city@latest\u002FGeoLite2-City.mmdb.gz",[174,459,460],{"class":180}," |",[174,462,463],{"class":249}," gunzip",[174,465,466],{"class":180}," >",[174,468,469],{"class":184}," web\u002Flibraries\u002Fgeolite2\u002FGeoLite2-City.mmdb\n",[74,471,472,473,476,477,480],{},"A download from MaxMind arrives as a ",[110,474,475],{},".tar.gz"," archive. Extract it and copy only ",[110,478,479],{},"GeoLite2-City.mmdb"," into the directory.",[139,482,484],{"id":483},"keep-it-current","Keep it current",[74,486,487],{},"MaxMind updates GeoLite2 regularly. To refresh the database, replace the file using the same method you installed it with. The module opens the file each time cron processes the tracking queue, so no cache clear is needed.",[74,489,490],{},"The database is used for location lookup. A private development IP may have no result; the module logs that lookup error while still storing the download intent.",[94,492,494],{"id":493},"_2-enable-the-optional-module","2. Enable the optional module",[74,496,497,498,501],{},"Use ",[77,499,500],{},"Extend"," in Drupal or run:",[102,503,505],{"className":394,"code":504,"language":396,"meta":108,"style":108},"drush en podcast_publisher_analytics\n",[110,506,507],{"__ignoreMap":108},[174,508,509,512,515],{"class":176,"line":177},[174,510,511],{"class":249},"drush",[174,513,514],{"class":184}," en",[174,516,517],{"class":184}," podcast_publisher_analytics\n",[74,519,520,521,524,525,528],{},"The main ",[110,522,523],{},"podcast_publisher"," module must already be enabled. Enabling analytics alone does ",[77,526,527],{},"not"," switch the feed's audio URLs to tracked URLs.",[94,530,532],{"id":531},"_3-track-feed-audio-urls","3. Track feed audio URLs",[534,535,536,548,555,566,584],"ol",{},[537,538,539,540,543,544,547],"li",{},"Open ",[77,541,542],{},"Structure → Views → Podcast Feed"," (",[110,545,546],{},"\u002Fadmin\u002Fstructure\u002Fviews\u002Fview\u002Fpodcast_feed",").",[537,549,550,551,554],{},"Select the ",[77,552,553],{},"Feed"," display.",[537,556,557,558,561,562,565],{},"Under ",[77,559,560],{},"Fields",", open ",[77,563,564],{},"Podcast Episode: Audio File",". Choose the field that provides the enclosure URL, not the separate Mimetype or Filelength fields.",[537,567,568,569,157,572,575,576,579,580,583],{},"Set ",[77,570,571],{},"Formatter",[77,573,574],{},"Download Tracker URL",". Leave ",[77,577,578],{},"Source"," as ",[110,581,582],{},"feed"," unless you use another source label.",[537,585,586,587,590,591,594],{},"Click ",[77,588,589],{},"Apply",", then ",[77,592,593],{},"Save"," the View.",[74,596,597],{},[598,599],"img",{"alt":600,"src":601},"The Podcast Feed audio field using the Download Tracker URL formatter","\u002Fimages\u002Fanalytics-formatter.png",[74,603,604],{},[86,605,606],{},"The formatter replaces the enclosure's direct file URL with a tracking URL.",[74,608,609,610,613,614,617,618,621,622,624],{},"Open a podcast feed and inspect an episode's ",[110,611,612],{},"\u003Cenclosure>"," URL. A tracked URL begins with your site's domain followed by ",[110,615,616],{},"\u002Fpodcast-publisher\u002Ffeed\u002F",". The URL redirects to the audio file when requested. If it still points directly to ",[110,619,620],{},"\u002Fsites\u002Fdefault\u002Ffiles\u002F",", check that you edited and saved the ",[77,623,553],{}," display's audio URL field.",[94,626,628],{"id":627},"_4-process-requests-and-read-the-report","4. Process requests and read the report",[74,630,631,632,635,636,639,640,643,644,647],{},"The tracking endpoint queues requests. Run Drupal cron regularly so its ",[110,633,634],{},"podcast_download_intent_tracker"," queue worker processes them. The report is at ",[77,637,638],{},"Podcasts → your podcast → Analytics",", with a path like ",[110,641,642],{},"\u002Fadmin\u002Fcontent\u002Fpodcast\u002F{podcast_id}\u002Fanalytics",". Viewing it requires ",[77,645,646],{},"Administer podcast episode settings"," permission.",[74,649,650],{},[598,651],{"alt":652,"src":653},"The Podcast Analytics report showing one processed sample download","\u002Fimages\u002Fanalytics-report.png",[74,655,656],{},[86,657,658],{},"The report groups counts by episode and offers Since publication, Today, Last 7 days, Last 30 days, and Last 90 days filters.",[74,660,661,662,665],{},"For a local check, request the tracked enclosure URL with ",[110,663,664],{},"GET",", run cron, and reload the report. A normal browser or podcast client request is useful for this check; recognized bots are excluded.",[94,667,669],{"id":668},"what-the-number-means","What the number means",[671,672,673,680,683,686,693],"ul",{},[537,674,675,676,679],{},"A ",[110,677,678],{},"HEAD"," request does not enter the tracking queue.",[537,681,682],{},"Known bots are excluded from the report.",[537,684,685],{},"Repeated requests from the same IP address and user agent for the same episode file are counted at most once within 24 hours.",[537,687,688,689,692],{},"A full file request counts. Partial byte-range requests count after roughly one minute of audio has been requested, with the module's special handling for a ",[110,690,691],{},"0-1"," byte request from Apple's CoreMedia framework.",[537,694,695],{},"Cron rehashes older requester identifiers as part of the module's privacy handling.",[74,697,698,699,702,703,126],{},"The report counts qualifying requests to ",[77,700,701],{},"tracked"," URLs. Direct file links, cached downloads served without reaching Drupal, and listening behavior after a redirect are outside what this module measures. If a count remains at zero, use the ",[131,704,706],{"href":705},"\u002Fsite-building\u002Ftroubleshooting#analytics-still-shows-zero","analytics checks",[708,709,710],"style",{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":108,"searchDepth":197,"depth":197,"links":712},[713,718,719,720,721],{"id":96,"depth":197,"text":97,"children":714},[715,716,717],{"id":141,"depth":203,"text":142},{"id":412,"depth":203,"text":413},{"id":483,"depth":203,"text":484},{"id":493,"depth":197,"text":494},{"id":531,"depth":197,"text":532},{"id":627,"depth":197,"text":628},{"id":668,"depth":197,"text":669},"Set up tracked audio URLs and understand download intent counts.","md",null,{},true,{"title":31,"description":722},"LJeH-4Kt6N2Hhl0g4n4y8iQ2JVETRSusY643X4qBqOk",[730,732],{"title":27,"path":28,"stem":29,"description":731,"children":-1},"List your feed in Apple Podcasts, Spotify, YouTube, and the Podcast Index.",{"title":37,"path":38,"stem":39,"description":733,"children":-1},"Configure editor access, episode pages, and feed behavior.",1791210501777]