Skip to content

Commit ad5d9c8

Browse files
authored
Merge pull request #79 from jtpio/plausible
Add Plausible analytics
2 parents 6f8e170 + ac07799 commit ad5d9c8

File tree

3 files changed

+80
-0
lines changed

3 files changed

+80
-0
lines changed

.github/workflows/deploy.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ jobs:
3535
run: |
3636
pixi run filter-kernels
3737
38+
- name: Add Plausible analytics
39+
shell: bash -l {0}
40+
run: |
41+
pixi run add-plausible
42+
3843
- name: Upload dist artifact for testing
3944
uses: actions/upload-artifact@v4
4045
with:

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@ platforms = ["linux-64", "osx-64", "win-64", "osx-arm64"]
1111
clean = "rm -rf .jupyterlite.doit.df dist"
1212
build = "jupyter lite build"
1313
filter-kernels = "python scripts/filter_xeus_kernels.py dist"
14+
add-plausible = "python scripts/add_plausible.py dist"
1415
test = "pytest ui-tests/ -v"
1516
readthedocs = "rm -rf $READTHEDOCS_OUTPUT/html && cp -r dist $READTHEDOCS_OUTPUT/html"
1617

1718
[tool.pixi.dependencies]
19+
beautifulsoup4 = ">=4.12"
1820
python = ">=3.12"
1921
mamba = ">=2.4.0,<3"
2022
pydata-sphinx-theme = ">=0.16.1,<0.17"

scripts/add_plausible.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Post-build script to inject Plausible analytics into the JupyterLite site.
4+
5+
This script modifies the built JupyterLite HTML files to include
6+
Plausible analytics tracking with hash-based routing support.
7+
"""
8+
9+
import argparse
10+
from pathlib import Path
11+
12+
from bs4 import BeautifulSoup
13+
14+
PLAUSIBLE_SRC = "https://plausible.io/js/pa-B75UO5--FNXYQSG7GBWkf.js"
15+
PLAUSIBLE_INIT = (
16+
"window.plausible=window.plausible||function(){(plausible.q=plausible.q||[]).push(arguments)},"
17+
"plausible.init=plausible.init||function(i){plausible.o=i||{}};"
18+
"plausible.init()"
19+
)
20+
21+
22+
def inject_plausible(dist_dir: Path) -> None:
23+
"""Inject Plausible analytics scripts into all HTML files."""
24+
html_files = list(dist_dir.rglob("*.html"))
25+
print(f"Found {len(html_files)} HTML files")
26+
27+
for html_file in html_files:
28+
soup = BeautifulSoup(html_file.read_text(), "html.parser")
29+
30+
head = soup.find("head")
31+
if not head:
32+
print(f"Warning: No <head> found in {html_file}, skipping")
33+
continue
34+
35+
# Add the external Plausible script
36+
external_script = soup.new_tag("script")
37+
external_script["async"] = ""
38+
external_script["src"] = PLAUSIBLE_SRC
39+
head.append(external_script)
40+
41+
# Add the inline initialization script
42+
init_script = soup.new_tag("script")
43+
init_script.string = PLAUSIBLE_INIT
44+
head.append(init_script)
45+
46+
html_file.write_text(str(soup))
47+
print(f"Injected Plausible into: {html_file}")
48+
49+
50+
def main() -> None:
51+
parser = argparse.ArgumentParser(
52+
description="Inject Plausible analytics into the built JupyterLite site."
53+
)
54+
parser.add_argument(
55+
"dist_dir",
56+
type=Path,
57+
help="Path to the dist directory containing the built JupyterLite site",
58+
)
59+
args = parser.parse_args()
60+
61+
dist_dir = args.dist_dir
62+
63+
if not dist_dir.exists():
64+
print(f"Error: dist directory not found at {dist_dir}")
65+
print("Please run 'pixi run build' first.")
66+
return
67+
68+
inject_plausible(dist_dir)
69+
print("Done!")
70+
71+
72+
if __name__ == "__main__":
73+
main()

0 commit comments

Comments
 (0)