Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions assets/live-stats.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Latest view counts for the catalog and the resource pages.
*
* The daily traffic workflow keeps a fresh resource-stats.json on the automation/traffic-stats-staging
* branch. Publishing it to master needs a pull request that GitHub Actions cannot open here, so the
* copy on the site is only as fresh as the last merged weekly PR. This script reads the staging copy
* straight from raw.githubusercontent.com, which serves it to any site and caches it for five minutes.
*
* Only the view counts are taken from it. The local file stays the source for everything else
* (upvotes, discussion links), and it is the fallback when the staging copy cannot be read, is
* older than the local file, or was rendered by a different counting method (sources.views).
* Exposes window.FastTrackLiveStats = { url, fetch, pick }. It never throws and never blocks a page.
*/
(function () {
'use strict';

var LIVE_STATS_URL = 'https://raw.githubusercontent.com/microsoft/FastTrack/automation/traffic-stats-staging/resource-stats.json';
var TIMEOUT_MS = 5000;

// Resolves with the parsed staging file, or null on any failure or timeout.
function fetchLive() {
return new Promise(function (resolve) {
try {
if (!window.fetch) { resolve(null); return; }
var controller = window.AbortController ? new AbortController() : null;
var timer = setTimeout(function () {
if (controller) controller.abort();
resolve(null);
}, TIMEOUT_MS);
var options = { credentials: 'omit', referrerPolicy: 'no-referrer' };
if (controller) options.signal = controller.signal;
window.fetch(LIVE_STATS_URL, options)
.then(function (response) {
if (!response.ok) throw new Error('HTTP ' + response.status);
return response.json();
})
.then(function (doc) { clearTimeout(timer); resolve(doc); })
.catch(function () { clearTimeout(timer); resolve(null); });
} catch (error) {
resolve(null);
}
});
}

// Returns { slug: views } when the staging copy can replace the local view counts, else null.
function pick(local, live) {
try {
if (!local || !live || !live.resources || typeof live.resources !== 'object') return null;
if (!local.sources || !live.sources || !local.sources.views || local.sources.views !== live.sources.views) return null;
var localTime = Date.parse(local.generatedAt);
var liveTime = Date.parse(live.generatedAt);
if (!(liveTime >= localTime)) return null;

var views = {};
var found = false;
Object.keys(live.resources).forEach(function (slug) {
var entry = live.resources[slug];
var count = entry ? Number(entry.views) : NaN;
if (isFinite(count) && count >= 0) {
views[slug] = Math.round(count);
found = true;
}
});
return found ? views : null;
} catch (error) {
return null;
}
}

window.FastTrackLiveStats = { url: LIVE_STATS_URL, fetch: fetchLive, pick: pick };
})();
1 change: 1 addition & 0 deletions assets/privacy-notice.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@
'<ul>',
'<li><strong>Google Fonts.</strong> The catalog and resource pages load fonts from fonts.googleapis.com and fonts.gstatic.com.</li>',
'<li><strong>giscus and GitHub.</strong> A resource&rsquo;s detail view in the catalog loads comments and reactions from giscus.app, which uses GitHub Discussions in the microsoft/FastTrack repository. You sign in with GitHub to react or comment.</li>',
'<li><strong>Latest view counts.</strong> The catalog and resource pages read a public statistics file from the microsoft/FastTrack repository on raw.githubusercontent.com. The request carries no cookies and sends no referrer.</li>',
'<li><strong>Links to other sites</strong>, such as Microsoft Learn and GitHub, follow those sites&rsquo; own privacy statements.</li>',
'</ul>',
'</section>',
Expand Down
16 changes: 12 additions & 4 deletions assets/resource-page.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,25 @@
}

// Views come from the published stats, so the page needs no rebuild when the counts change. The row
// stays hidden if the file cannot be read. Keep VIEWS_TIP in step with the catalog (index.html).
// stays hidden if the file cannot be read. The latest counts are taken from the staged stats when
// they can be read in time (assets/live-stats.js). Keep VIEWS_TIP in step with the catalog (index.html).
var VIEWS_TIP = "Catalog page views recorded by Microsoft Clarity since Jul 2026, plus views of the resource's GitHub folder from saved snapshots (Apr\u2013Jun and 14\u201327 Oct 2026). Some days were never captured, so this is a minimum.";
var LIVE_STATS_WAIT_MS = 1500;
var viewsRow = document.getElementById('viewsRow');
var viewsValue = document.getElementById('viewsValue');
if (viewsRow && viewsValue && slug && script && script.src && window.fetch) {
fetch(new URL('../resource-stats.json', script.src).href, { cache: 'no-cache' })
.then(function (response) { if (!response.ok) throw new Error('HTTP ' + response.status); return response.json(); })
.then(function (data) {
var liveStats = window.FastTrackLiveStats ? window.FastTrackLiveStats.fetch() : Promise.resolve(null);
var liveOrTimeout = Promise.race([liveStats, new Promise(function (resolve) { setTimeout(function () { resolve(null); }, LIVE_STATS_WAIT_MS); })]);
var localStats = fetch(new URL('../resource-stats.json', script.src).href, { cache: 'no-cache' })
.then(function (response) { if (!response.ok) throw new Error('HTTP ' + response.status); return response.json(); });
Promise.all([localStats, liveOrTimeout])
.then(function (results) {
var data = results[0];
if (!data || !data.resources || typeof data.resources !== 'object') return;
var entry = data.resources[slug];
var views = entry ? Number(entry.views) : 0;
var fresh = window.FastTrackLiveStats ? window.FastTrackLiveStats.pick(data, results[1]) : null;
if (fresh && Object.prototype.hasOwnProperty.call(fresh, slug)) views = fresh[slug];
if (!isFinite(views) || views < 0) views = 0;
var short = views >= 10000 ? (views / 1000).toFixed(0) + 'k' : views >= 1000 ? (views / 1000).toFixed(1) + 'k' : String(views);
viewsValue.textContent = short;
Expand Down
14 changes: 14 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -1641,6 +1641,7 @@ <h3>Related resources</h3>
</div>

<script src="assets/privacy-notice.js" defer></script>
<script src="assets/live-stats.js"></script>

<script>
// --- DATASET ---
Expand Down Expand Up @@ -1799,10 +1800,17 @@ <h3>Related resources</h3>
return d.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric', timeZone: 'UTC' });
};

// How long the first render waits for the latest counts (assets/live-stats.js) before it
// falls back to the committed file. Counts that arrive later are not applied.
const LIVE_STATS_WAIT_MS = 1500;

async function loadCatalog() {
grid.classList.add('d-none');
showEmptyState('Loading catalog…', 'Reading the latest FastTrack resource metadata.', false);

// Started now so it runs alongside the catalog and stats requests.
const liveStats = window.FastTrackLiveStats ? window.FastTrackLiveStats.fetch() : Promise.resolve(null);

try {
const response = await fetch(CATALOG_URL, { cache: 'no-cache' });
if (!response.ok) throw new Error(`Catalog request failed with HTTP ${response.status}`);
Expand All @@ -1815,6 +1823,12 @@ <h3>Related resources</h3>
const statsData = await statsRes.json();
STATS = statsData.resources || {};
STATS_LOADED = true;
// Take only the view counts from the latest staged stats (see assets/live-stats.js).
const live = await Promise.race([liveStats, new Promise(resolve => setTimeout(() => resolve(null), LIVE_STATS_WAIT_MS))]);
const liveViews = window.FastTrackLiveStats ? window.FastTrackLiveStats.pick(statsData, live) : null;
if (liveViews) {
Object.keys(liveViews).forEach(slug => { STATS[slug] = { ...(STATS[slug] || {}), views: liveViews[slug] }; });
}
}
} catch (e) {
console.warn('Failed to load stats:', e);
Expand Down
1 change: 1 addition & 0 deletions r/add-engagegroupadmins/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ <h2>Related resources</h2>
</div>
</footer>
<script src="../../assets/privacy-notice.js" defer></script>
<script src="../../assets/live-stats.js" defer></script>
<script src="../../assets/resource-page.js" data-clarity="w810tntgw1" defer></script>
</body>
</html>
1 change: 1 addition & 0 deletions r/agent-365-enablement-checklist/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ <h2>Related resources</h2>
</div>
</footer>
<script src="../../assets/privacy-notice.js" defer></script>
<script src="../../assets/live-stats.js" defer></script>
<script src="../../assets/resource-page.js" data-clarity="w810tntgw1" defer></script>
</body>
</html>
1 change: 1 addition & 0 deletions r/agent-365-lifecycle-atlas/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ <h2>Related resources</h2>
</div>
</footer>
<script src="../../assets/privacy-notice.js" defer></script>
<script src="../../assets/live-stats.js" defer></script>
<script src="../../assets/resource-page.js" data-clarity="w810tntgw1" defer></script>
</body>
</html>
1 change: 1 addition & 0 deletions r/agent-brainstorming-template/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ <h2>Related resources</h2>
</div>
</footer>
<script src="../../assets/privacy-notice.js" defer></script>
<script src="../../assets/live-stats.js" defer></script>
<script src="../../assets/resource-page.js" data-clarity="w810tntgw1" defer></script>
</body>
</html>
1 change: 1 addition & 0 deletions r/agents-cost-calculator/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ <h2>Related resources</h2>
</div>
</footer>
<script src="../../assets/privacy-notice.js" defer></script>
<script src="../../assets/live-stats.js" defer></script>
<script src="../../assets/resource-page.js" data-clarity="w810tntgw1" defer></script>
</body>
</html>
1 change: 1 addition & 0 deletions r/ai-council/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ <h2>Related resources</h2>
</div>
</footer>
<script src="../../assets/privacy-notice.js" defer></script>
<script src="../../assets/live-stats.js" defer></script>
<script src="../../assets/resource-page.js" data-clarity="w810tntgw1" defer></script>
</body>
</html>
1 change: 1 addition & 0 deletions r/analyze-sharepointrisk/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ <h2>Related resources</h2>
</div>
</footer>
<script src="../../assets/privacy-notice.js" defer></script>
<script src="../../assets/live-stats.js" defer></script>
<script src="../../assets/resource-page.js" data-clarity="w810tntgw1" defer></script>
</body>
</html>
1 change: 1 addition & 0 deletions r/autoreply-agent/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ <h2>Related resources</h2>
</div>
</footer>
<script src="../../assets/privacy-notice.js" defer></script>
<script src="../../assets/live-stats.js" defer></script>
<script src="../../assets/resource-page.js" data-clarity="w810tntgw1" defer></script>
</body>
</html>
1 change: 1 addition & 0 deletions r/comparedocs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ <h2>Related resources</h2>
</div>
</footer>
<script src="../../assets/privacy-notice.js" defer></script>
<script src="../../assets/live-stats.js" defer></script>
<script src="../../assets/resource-page.js" data-clarity="w810tntgw1" defer></script>
</body>
</html>
1 change: 1 addition & 0 deletions r/copilot-agents-guide/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ <h2>Related resources</h2>
</div>
</footer>
<script src="../../assets/privacy-notice.js" defer></script>
<script src="../../assets/live-stats.js" defer></script>
<script src="../../assets/resource-page.js" data-clarity="w810tntgw1" defer></script>
</body>
</html>
1 change: 1 addition & 0 deletions r/copilot-analytics-reports-navigator/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ <h2>Related resources</h2>
</div>
</footer>
<script src="../../assets/privacy-notice.js" defer></script>
<script src="../../assets/live-stats.js" defer></script>
<script src="../../assets/resource-page.js" data-clarity="w810tntgw1" defer></script>
</body>
</html>
1 change: 1 addition & 0 deletions r/copilot-interaction-report/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ <h2>Related resources</h2>
</div>
</footer>
<script src="../../assets/privacy-notice.js" defer></script>
<script src="../../assets/live-stats.js" defer></script>
<script src="../../assets/resource-page.js" data-clarity="w810tntgw1" defer></script>
</body>
</html>
1 change: 1 addition & 0 deletions r/copilot-studio-workflow/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ <h2>Related resources</h2>
</div>
</footer>
<script src="../../assets/privacy-notice.js" defer></script>
<script src="../../assets/live-stats.js" defer></script>
<script src="../../assets/resource-page.js" data-clarity="w810tntgw1" defer></script>
</body>
</html>
1 change: 1 addition & 0 deletions r/create-engagecommunities/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ <h2>Related resources</h2>
</div>
</footer>
<script src="../../assets/privacy-notice.js" defer></script>
<script src="../../assets/live-stats.js" defer></script>
<script src="../../assets/resource-page.js" data-clarity="w810tntgw1" defer></script>
</body>
</html>
1 change: 1 addition & 0 deletions r/deepresearch/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ <h2>Related resources</h2>
</div>
</footer>
<script src="../../assets/privacy-notice.js" defer></script>
<script src="../../assets/live-stats.js" defer></script>
<script src="../../assets/resource-page.js" data-clarity="w810tntgw1" defer></script>
</body>
</html>
1 change: 1 addition & 0 deletions r/delete-allcommunityposts/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ <h2>Related resources</h2>
</div>
</footer>
<script src="../../assets/privacy-notice.js" defer></script>
<script src="../../assets/live-stats.js" defer></script>
<script src="../../assets/resource-page.js" data-clarity="w810tntgw1" defer></script>
</body>
</html>
1 change: 1 addition & 0 deletions r/delete-engagegroups/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ <h2>Related resources</h2>
</div>
</footer>
<script src="../../assets/privacy-notice.js" defer></script>
<script src="../../assets/live-stats.js" defer></script>
<script src="../../assets/resource-page.js" data-clarity="w810tntgw1" defer></script>
</body>
</html>
1 change: 1 addition & 0 deletions r/delete-engageusers/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ <h2>Related resources</h2>
</div>
</footer>
<script src="../../assets/privacy-notice.js" defer></script>
<script src="../../assets/live-stats.js" defer></script>
<script src="../../assets/resource-page.js" data-clarity="w810tntgw1" defer></script>
</body>
</html>
1 change: 1 addition & 0 deletions r/disable-insightsheadspace/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ <h2>Related resources</h2>
</div>
</footer>
<script src="../../assets/privacy-notice.js" defer></script>
<script src="../../assets/live-stats.js" defer></script>
<script src="../../assets/resource-page.js" data-clarity="w810tntgw1" defer></script>
</body>
</html>
1 change: 1 addition & 0 deletions r/ess-servicenow-itsm-get-request-details/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ <h2>Related resources</h2>
</div>
</footer>
<script src="../../assets/privacy-notice.js" defer></script>
<script src="../../assets/live-stats.js" defer></script>
<script src="../../assets/resource-page.js" data-clarity="w810tntgw1" defer></script>
</body>
</html>
1 change: 1 addition & 0 deletions r/ess-servicenow-itsm-get-user-requests/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ <h2>Related resources</h2>
</div>
</footer>
<script src="../../assets/privacy-notice.js" defer></script>
<script src="../../assets/live-stats.js" defer></script>
<script src="../../assets/resource-page.js" data-clarity="w810tntgw1" defer></script>
</body>
</html>
1 change: 1 addition & 0 deletions r/export-copilotinteractions/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ <h2>Related resources</h2>
</div>
</footer>
<script src="../../assets/privacy-notice.js" defer></script>
<script src="../../assets/live-stats.js" defer></script>
<script src="../../assets/resource-page.js" data-clarity="w810tntgw1" defer></script>
</body>
</html>
1 change: 1 addition & 0 deletions r/export-engagefiles/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ <h2>Related resources</h2>
</div>
</footer>
<script src="../../assets/privacy-notice.js" defer></script>
<script src="../../assets/live-stats.js" defer></script>
<script src="../../assets/resource-page.js" data-clarity="w810tntgw1" defer></script>
</body>
</html>
1 change: 1 addition & 0 deletions r/export-engagenetworkdata/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ <h2>Related resources</h2>
</div>
</footer>
<script src="../../assets/privacy-notice.js" defer></script>
<script src="../../assets/live-stats.js" defer></script>
<script src="../../assets/resource-page.js" data-clarity="w810tntgw1" defer></script>
</body>
</html>
1 change: 1 addition & 0 deletions r/export-m365copilotreports/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ <h2>Related resources</h2>
</div>
</footer>
<script src="../../assets/privacy-notice.js" defer></script>
<script src="../../assets/live-stats.js" defer></script>
<script src="../../assets/resource-page.js" data-clarity="w810tntgw1" defer></script>
</body>
</html>
1 change: 1 addition & 0 deletions r/export-simpleplacesvisual/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ <h2>Related resources</h2>
</div>
</footer>
<script src="../../assets/privacy-notice.js" defer></script>
<script src="../../assets/live-stats.js" defer></script>
<script src="../../assets/resource-page.js" data-clarity="w810tntgw1" defer></script>
</body>
</html>
1 change: 1 addition & 0 deletions r/find-mailboxdelegates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ <h2>Related resources</h2>
</div>
</footer>
<script src="../../assets/privacy-notice.js" defer></script>
<script src="../../assets/live-stats.js" defer></script>
<script src="../../assets/resource-page.js" data-clarity="w810tntgw1" defer></script>
</body>
</html>
1 change: 1 addition & 0 deletions r/get-aadadminrolemembers/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ <h2>Related resources</h2>
</div>
</footer>
<script src="../../assets/privacy-notice.js" defer></script>
<script src="../../assets/live-stats.js" defer></script>
<script src="../../assets/resource-page.js" data-clarity="w810tntgw1" defer></script>
</body>
</html>
1 change: 1 addition & 0 deletions r/get-allinsightslicensedusers/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ <h2>Related resources</h2>
</div>
</footer>
<script src="../../assets/privacy-notice.js" defer></script>
<script src="../../assets/live-stats.js" defer></script>
<script src="../../assets/resource-page.js" data-clarity="w810tntgw1" defer></script>
</body>
</html>
1 change: 1 addition & 0 deletions r/get-engagegroupinfo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ <h2>Related resources</h2>
</div>
</footer>
<script src="../../assets/privacy-notice.js" defer></script>
<script src="../../assets/live-stats.js" defer></script>
<script src="../../assets/resource-page.js" data-clarity="w810tntgw1" defer></script>
</body>
</html>
1 change: 1 addition & 0 deletions r/get-groupsmembersmanagers/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ <h2>Related resources</h2>
</div>
</footer>
<script src="../../assets/privacy-notice.js" defer></script>
<script src="../../assets/live-stats.js" defer></script>
<script src="../../assets/resource-page.js" data-clarity="w810tntgw1" defer></script>
</body>
</html>
Loading
Loading