// Builds the FactHub dataset of social platform size (monthly users and US adult reach). const fs = require('fs'); const path = require('path'); const crypto = require('crypto'); const KEY = 'social-platform-size-2026'; const OUT = path.join(__dirname, '..', 'out', KEY); fs.mkdirSync(OUT, { recursive: true }); fs.copyFileSync(__filename, path.join(OUT, 'build-size-dataset.js')); // value_type: reported (company figure), estimated (third-party), proxy (ad reach or weekly users, not MAU) // [platform, owner, users_monthly, users_low, value_type, metric, as_of, source_id, registered_accounts, pew_pct, notes] const R = [ ['YouTube', 'Google', null, 2530000000, 'proxy', 'Advertising reach (Google ad-planning data); Google publishes no user count', '2025-01', 'datareportal-youtube', null, 84, 'Widely quoted figures of about 2.7 billion monthly users have no primary source. Google describes YouTube only as having "billions" of monthly logged-in users.'], ['Facebook', 'Meta', 3070000000, null, 'reported', 'Monthly active users', '2023-12-31', 'meta-q4-2023', null, 71, 'Last Facebook-only figure Meta published; Meta stopped reporting per-app users after 2023 and now reports 3.6 billion daily active people across all its apps.'], ['Instagram', 'Meta', 3000000000, null, 'reported', 'Monthly active users (CEO announcement)', '2025-09-24', 'instagram-3b', null, 50, 'Announced by Mark Zuckerberg; not an audited filing.'], ['TikTok', 'TikTok USDS Joint Venture / ByteDance', null, 1590000000, 'proxy', 'Advertising reach, users 18+ (ad-planning data); TikTok publishes no global user count', '2025-01', 'datareportal-tiktok', null, 37, 'Third-party sites quote about 1.9 billion monthly users without a cited primary source.'], ['X', 'SpaceX (X and xAI)', 550000000, 302000000, 'reported', 'Monthly active users across X and Grok combined (SEC filing); low value is Similarweb\'s estimate of X mobile-app users, June 2026', '2026-03-31', 'spacex-fwp', null, 21, 'X has claimed about 600 million users; the SEC filing figure is lower and includes Grok. Similarweb estimated about 302 million monthly users of the X mobile app in June 2026.'], ['Reddit', 'Reddit, Inc.', null, 514600000, 'proxy', 'Weekly active uniques (Reddit does not report monthly users; monthly users must be at least this)', '2026-06-30', 'reddit-q2-2026', null, 26, 'Daily active uniques: 130.3 million worldwide, 53.2 million in the US.'], ['Threads', 'Meta', 500000000, null, 'reported', 'Monthly active users (company announcement)', '2026-06-16', 'threads-500m', null, 8, 'Announced by Meta; reported by Reuters and others. Similarweb estimated 147 million daily mobile users in July 2026.'], ['Rumble', 'RUM Group Inc.', 56000000, null, 'reported', 'Average global monthly active users, Q1 2026 (SEC filing)', '2026-03-31', 'rumble-q1-2026', null, null, 'Earnings-call summaries report 57 million for Q2 2026, but the Q2 press release does not state it; Rumble said it will stop reporting MAU. Not covered by Pew.'], ['Bluesky', 'Bluesky Social PBC', 10400000, null, 'estimated', 'Monthly active users of the mobile app (Similarweb); web users not included', '2026-06', 'techcrunch-bluesky', 46000000, 4, 'Bluesky publishes registered accounts (nearly 46 million) but not active users. Similarweb puts the quarterly average near 22 million at the late-2024 peak.'], ['Truth Social', 'Trump Media & Technology Group', null, null, 'estimated', 'No published or credible monthly-user figure; Similarweb estimated an average of 25 million monthly visits in January-July 2026', '2026-07', 'gvwire-truth-social', null, 3, 'Visits are not users; one person can make many visits. Similarweb estimated visits fell about 36% year over year in July 2026.'], ['Mastodon', 'Independent servers (Mastodon gGmbH develops the software)', 728201, null, 'reported', 'Active users across servers tracked by the Mastodon project\'s statistics API', '2026-10-10', 'mastodon-stats', 10501112, null, 'Covers servers that report to the Mastodon project; peak was about 2.6 million in late 2022. Not covered by Pew.'], ]; const header = ['platform', 'owner', 'users_monthly', 'users_low', 'value_type', 'metric', 'as_of', 'source_id', 'registered_accounts', 'pew_2025_us_adults_pct', 'notes']; const cell = v => { const s = v == null ? '' : String(v); return /[",\n]/.test(s) ? '"' + s.replace(/"/g, '""') + '"' : s; }; fs.writeFileSync(path.join(OUT, 'platform-size.csv'), [header, ...R].map(r => r.map(cell).join(',')).join('\n') + '\n'); const sha = f => 'sha256:' + crypto.createHash('sha256').update(fs.readFileSync(f)).digest('hex'); const art = (id, role, file, mediaType, description) => ({ id, role, fileName: path.basename(file), mediaType, byteLength: fs.statSync(file).size, contentDigest: sha(file), description, access: 'public' }); const src = (id, name, url, role, a, digest) => { const s = { id, name, url, retrievedAt: '2026-10-10', role, licenseName: 'Publisher copyright; figures reproduced as facts', redistribution: 'Figures extracted; source not redistributed' }; if (a) { s.archiveUrl = a[0]; s.archivedAt = a[1]; } if (digest) s.contentDigest = digest; return s; }; const sources = [ src('pew-factsheet', 'Pew Research Center: Social Media Fact Sheet (2025 survey, fielded Feb. 5 to June 18, 2025, 5,022 U.S. adults)', 'https://www.pewresearch.org/internet/fact-sheet/social-media/', 'Primary: share of U.S. adults who ever use each platform', ['https://web.archive.org/web/20261010225132/https://www.pewresearch.org/internet/fact-sheet/social-media/', '2026-10-10T22:51:32Z'], 'sha256:c30e038bbbe4fc30edf6088fbd374b5895d17d0b9b3f6329b3a752723c57b90e'), src('pew-report-2025', 'Pew Research Center: Americans\' Social Media Use 2025 (November 20, 2025)', 'https://www.pewresearch.org/internet/2025/11/20/americans-social-media-use-2025/', 'Primary: report accompanying the fact sheet', ['https://web.archive.org/web/20261010225223/https://www.pewresearch.org/internet/2025/11/20/americans-social-media-use-2025/', '2026-10-10T22:52:23Z'], null), src('meta-q4-2023', 'Meta Reports Fourth Quarter and Full Year 2023 Results', 'https://investor.atmeta.com/investor-news/press-release-details/2024/Meta-Reports-Fourth-Quarter-and-Full-Year-2023-Results-Initiates-Quarterly-Dividend/default.aspx', 'Primary: Facebook monthly active users', ['https://web.archive.org/web/20261003115447/https://investor.atmeta.com/investor-news/press-release-details/2024/Meta-Reports-Fourth-Quarter-and-Full-Year-2023-Results-Initiates-Quarterly-Dividend/default.aspx', '2026-10-03T11:54:47Z'], null), src('instagram-3b', 'Neowin: Instagram joins the 3 billion monthly active club (September 2025)', 'https://www.neowin.net/news/instagram-joins-the-3-billion-monthly-active-club-alongside-facebook-and-whatsapp/', 'Secondary: report of Mark Zuckerberg\'s announcement', null, null), src('datareportal-youtube', 'DataReportal: Essential YouTube statistics', 'https://datareportal.com/essential-youtube-stats', 'Secondary: YouTube advertising reach from Google ad-planning data', null, 'sha256:345f5292ccf6da39f1a0bb774cb4f069cc3a2a60154c6cde51af3015ca32de68'), src('datareportal-tiktok', 'DataReportal: Essential TikTok statistics', 'https://datareportal.com/essential-tiktok-stats', 'Secondary: TikTok advertising reach from ad-planning data', null, 'sha256:e36c4a9189a732b4df2596e33499fb3433123c697ecaa58fccee69fa10436310'), src('spacex-fwp', 'SpaceX free writing prospectus filed with the SEC (May 2026)', 'https://www.sec.gov/Archives/edgar/data/1181412/000162828026040610/spacexfwp.htm', 'Primary: X and Grok monthly active users as of March 31, 2026', ['https://web.archive.org/web/20261010225349/https://www.sec.gov/Archives/edgar/data/1181412/000162828026040610/spacexfwp.htm', '2026-10-10T22:53:49Z'], 'sha256:68336edda541e8892480a09e4fd96ecaa27dc68380775459d5c9de77d9fb3f5e'), src('reddit-q2-2026', 'Reddit Reports Second Quarter 2026 Results (SEC Form 8-K exhibit)', 'https://www.sec.gov/Archives/edgar/data/0001713445/000171344526000098/earningspressreleaseq226.htm', 'Primary: daily and weekly active uniques', ['https://web.archive.org/web/20261010225416/https://www.sec.gov/Archives/edgar/data/1713445/000171344526000098/earningspressreleaseq226.htm', '2026-10-10T22:54:16Z'], 'sha256:f30ea0eb1eb5cbb9a03e237c994b42f2f1c04b65f1a922619ec520f0a02c5c8a'), src('threads-500m', 'Social Media Today: Threads reaches 500 million user milestone (June 2026)', 'https://www.socialmediatoday.com/news/threads-reaches-500-million-user-milestone/823099/', 'Secondary: report of Meta\'s announcement', ['https://web.archive.org/web/20261010225430/https://www.socialmediatoday.com/news/threads-reaches-500m-user-milestone/823099/', '2026-10-10T22:54:30Z'], null), src('rumble-q1-2026', 'Rumble first quarter 2026 results (SEC Form 8-K exhibit, May 14, 2026)', 'https://www.sec.gov/Archives/edgar/data/0001830081/000121390026056619/ea029055101ex99-1.htm', 'Primary: average global monthly active users', ['https://web.archive.org/web/20261010225437/https://www.sec.gov/Archives/edgar/data/1830081/000121390026056619/ea029055101ex99-1.htm', '2026-10-10T22:54:37Z'], 'sha256:674a49d887d420ec89f4b8692292a880069217c363c7573ee266f0b0e42a15cc'), src('techcrunch-bluesky', 'TechCrunch: Bluesky\'s active user base is shrinking (August 11, 2026), citing Similarweb', 'https://techcrunch.com/2026/08/11/blueskys-active-user-base-is-shrinking-as-its-focus-expands-beyond-the-app/', 'Secondary: Similarweb estimates for Bluesky, X and Threads', ['https://web.archive.org/web/20261001230654/https://techcrunch.com/2026/08/11/blueskys-active-user-base-is-shrinking-as-its-focus-expands-beyond-the-app/', '2026-10-01T23:06:54Z'], null), src('gvwire-truth-social', 'GV Wire (New York Times): Traffic to Trump\'s Truth Social falls sharply this summer (August 10, 2026), citing Similarweb', 'https://gvwire.com/2026/08/10/traffic-to-trumps-truth-social-falls-sharply-this-summer/', 'Secondary: Similarweb visit estimates for Truth Social', null, null), src('mastodon-stats', 'Mastodon project statistics API', 'https://api.joinmastodon.org/statistics', 'Primary: daily server, account and active-user counts', null, 'sha256:d74f9cf2c9b71b7635beff1b113220c772e932cc43f25c1ae51405df70800de4'), ]; const SRC_BY = Object.fromEntries(R.map(r => [r[0], r[7]])); const rows = R.map(r => Object.fromEntries(header.map((h, i) => [h, r[i]]))); const sizeRows = rows.map(r => ({ platform: r.platform, users_for_comparison: r.users_monthly ?? r.users_low, basis: r.users_monthly != null ? r.metric : (r.users_low != null ? r.metric : 'none'), value_type: r.value_type, as_of: r.as_of })).filter(r => r.users_for_comparison != null).sort((a, b) => b.users_for_comparison - a.users_for_comparison); const pewRows = rows.filter(r => r.pew_2025_us_adults_pct != null).map(r => ({ platform: r.platform, pew_2025_us_adults_pct: r.pew_2025_us_adults_pct })).sort((a, b) => b.pew_2025_us_adults_pct - a.pew_2025_us_adults_pct); const f = (name, type, description, extra = {}) => ({ name, type, description, nullable: true, valueType: 'observed', ...extra }); const content = { key: KEY, status: 'Final', rulesVersion: '2.14', title: 'How big are the major social platforms? Users and US reach, 2026', description: 'Monthly users worldwide and the share of US adults using eleven social platforms, with each figure labeled as company-reported, third-party estimate, or proxy.', selectionRationale: 'Gives scale to a comparison of moderation rules across platforms: a policy at Facebook or YouTube reaches far more people than one at Bluesky or Mastodon. Covers the largest US platforms plus the alternatives promoted by politicians on the left and right.', topics: ['social media', 'platform size', 'monthly active users'], geography: ['Worldwide', 'United States'], temporalCoverage: 'Latest available figure per platform, January 2025 to October 2026; Pew survey February to June 2025', unitOfObservation: 'One platform', updateCadence: 'Irregular', curator: 'FactHub', reproducibilityStatus: 'Reproducible from cited sources', reproducibilityExplanation: 'Each figure is copied from the cited source; Pew percentages are the 2025 row of the Social Media Fact Sheet table, read on 2026-10-10. No calculations beyond sorting.', limitations: [ 'Figures are not comparable measures. They mix company-reported monthly users, a combined X-and-Grok figure, weekly users (Reddit), advertising reach (YouTube, TikTok), mobile-only third-party estimates (Bluesky) and web visits (Truth Social). value_type and metric say which is which.', 'Most company figures are self-reported and unaudited; announcements (Instagram, Threads) are not filings.', 'Monthly users are worldwide; Pew percentages are US adults only.', 'Dates differ by up to two years across platforms; Facebook\'s last per-app figure is from December 2023.', 'Truth Social publishes no user count, and no credible independent monthly-user estimate was found.', 'Mastodon\'s figure covers servers that report to the Mastodon project, not every server in the network.', 'Pew did not report figures for Rumble or Mastodon.', ], sources, artifacts: [ art('platform-size', 'curatedTable', path.join(OUT, 'platform-size.csv'), 'text/csv', 'One row per platform: monthly users, lower-bound or proxy figure, measure, date, source, and Pew share of US adults.'), art('build-js', 'transformationManifest', path.join(OUT, 'build-size-dataset.js'), 'text/javascript', 'Script holding the curated figures and building this dataset.'), ], tables: [{ id: 'platform-size', title: 'Social platform size', artifactId: 'platform-size', unitOfObservation: 'One platform', description: 'Latest available user figures for eleven social platforms, with the measure behind each.', fields: [ f('platform', 'string', 'Platform name.', { nullable: false }), f('owner', 'string', 'Owning company or operator.', { nullable: false }), f('users_monthly', 'integer', 'Monthly users as reported or estimated (see value_type and metric). Empty when no monthly figure exists.', { units: 'users', sourceIds: Object.values(SRC_BY) }), f('users_low', 'integer', 'A lower-bound or proxy figure: advertising reach, weekly users, or a mobile-only estimate. Empty when not needed.', { units: 'users', sourceIds: Object.values(SRC_BY) }), f('value_type', 'string', 'reported (company figure), estimated (third-party), or proxy (a related measure, not monthly users).', { nullable: false, valueType: 'derived', derivation: 'FactHub classification of the source.' }), f('metric', 'string', 'Exact measure behind the figures.', { nullable: false }), f('as_of', 'string', 'Date or month the figure refers to.', { nullable: false }), f('source_id', 'string', 'Id of the source entry for the user figure.', { nullable: false }), f('registered_accounts', 'integer', 'Registered accounts, where the platform publishes them.', { units: 'accounts', sourceIds: ['techcrunch-bluesky', 'mastodon-stats'] }), f('pew_2025_us_adults_pct', 'number', 'Share of US adults who say they ever use the platform (Pew, 2025). Empty when Pew did not report it.', { units: 'percent', sourceIds: ['pew-factsheet'] }), f('notes', 'string', 'Caveats and related figures.'), ], }], analyses: [ { id: 'users-for-comparison', title: 'Platforms ranked by best available user figure', question: 'Roughly how many people use each platform worldwide?', operation: 'For each platform, take users_monthly if present, otherwise users_low; sort descending. Truth Social is omitted (no figure).', scope: 'Ten platforms with a figure; dates and measures differ.', resultShape: 'table', structuredResult: { rows: sizeRows }, displayResult: sizeRows.map(r => `${r.platform}: ${(r.users_for_comparison / 1e6).toLocaleString('en-US', { maximumFractionDigits: 1 })} million`).join('; '), methodologicalNotes: ['Mixes measures; see basis and value_type for each row.', 'Spans about 4,000-fold from Facebook (3.07 billion) to Mastodon (0.73 million).'], limitations: ['Not like-for-like: monthly users, weekly users, ad reach and mobile-only estimates are combined for a sense of scale only.', 'A log scale is needed to chart all platforms.'], executedAt: '2026-10-10T23:40:00Z', }, { id: 'pew-us-reach', title: 'Share of US adults who use each platform (Pew, 2025)', question: 'What share of US adults use each platform?', operation: 'Copy the 2025 row of Pew\'s Social Media Fact Sheet; sort descending.', scope: 'Nine platforms Pew reports; survey fielded Feb. 5 to June 18, 2025, 5,022 US adults.', resultShape: 'table', structuredResult: { rows: pewRows }, displayResult: pewRows.map(r => `${r.platform}: ${r.pew_2025_us_adults_pct}%`).join('; '), methodologicalNotes: ['"Ever use" the platform, as reported by respondents.'], limitations: ['Self-reported use; does not measure frequency.', 'Pew did not report Rumble or Mastodon.'], executedAt: '2026-10-10T23:40:00Z', }, ], changelog: [{ date: '2026-10-10', summary: 'First release: eleven platforms, latest user figures as of 2026-10-10 and Pew 2025 US reach.' }], }; const parts = { sources: content.sources, tables: content.tables, analyses: content.analyses }; fs.writeFileSync(path.join(OUT, 'dataset-parts.json'), JSON.stringify(parts, null, 1) + '\n'); content.artifacts.push(art('dataset-parts', 'documentation', path.join(OUT, 'dataset-parts.json'), 'application/json', 'Sources, table definition and saved analyses for this dataset, as JSON.')); for (const k of Object.keys(parts)) content[k] = { $artifact: 'dataset-parts', pointer: '/' + k }; fs.writeFileSync(path.join(OUT, 'content.min.json'), JSON.stringify(content)); console.log(sizeRows.map(r => r.platform + ' ' + r.users_for_comparison).join('\n')); const p = content.artifacts.find(a => a.id === 'dataset-parts'); console.log(p.contentDigest, p.byteLength);