Skip to content

Commit 7fd7c9a

Browse files
committed
chore(analytics): add Cloudflare insights and optimize gtag.js
1 parent f895a25 commit 7fd7c9a

File tree

3 files changed

+260
-0
lines changed

3 files changed

+260
-0
lines changed

_layouts/default.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111

1212
<title>{{ page.title }}</title>
1313

14+
<script defer src='https://static.cloudflareinsights.com/beacon.min.js'
15+
data-cf-beacon='{"token": "70fc8c466cc1445098b3fc6f209c22c2"}'>
16+
</script>
17+
1418
{% if site.google_analytics %}
1519
<script async src="https://www.googletagmanager.com/gtag/js?id={{ site.google_analytics }}"></script>
1620
<script>
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
---
2+
title: "Optimizing gtag.js Performance on Jekyll GitHub Pages"
3+
lang: en
4+
layout: post
5+
audio: false
6+
translated: false
7+
generated: true
8+
---
9+
10+
Using `gtag.js` on a GitHub Pages site built with Jekyll presents some unique constraints, as GitHub Pages has limited server-side control and no direct access to caching headers or server-side scripting. However, you can still optimize the fetch speed of `https://www.googletagmanager.com/gtag/js?id=UA-66656236-1` using client-side techniques and Jekyll-specific configurations. Below are targeted strategies to improve its performance in this context:
11+
12+
---
13+
14+
### 1. **Load `gtag.js` Asynchronously**
15+
Ensure the `gtag.js` script is loaded asynchronously to avoid blocking page rendering. In your Jekyll site:
16+
- Add the script to your Jekyll layout or include file (e.g., `_includes/analytics.html` or directly in your `default.html` layout).
17+
- Use the `async` attribute:
18+
```html
19+
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-66656236-1"></script>
20+
```
21+
- Place this in the `<head>` or just before `</body>` in your Jekyll template (e.g., `_layouts/default.html`):
22+
```html
23+
<head>
24+
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-66656236-1"></script>
25+
<script>
26+
window.dataLayer = window.dataLayer || [];
27+
function gtag(){dataLayer.push(arguments);}
28+
gtag('js', new Date());
29+
gtag('config', 'UA-66656236-1');
30+
</script>
31+
</head>
32+
```
33+
- **Why it helps**: `async` ensures the script doesn’t block HTML parsing, reducing perceived load time.
34+
35+
---
36+
37+
### 2. **Add Preconnect for Google’s Domain**
38+
Reduce DNS lookup and connection latency by adding a `preconnect` hint for `googletagmanager.com`. In your Jekyll layout (`_layouts/default.html` or `_includes/head.html`):
39+
```html
40+
<link rel="preconnect" href="https://www.googletagmanager.com" crossorigin>
41+
```
42+
- Place this in the `<head>` before the `gtag.js` script.
43+
- **Why it helps**: Initiates DNS resolution and TCP connection early, speeding up the fetch of `gtag.js`.
44+
45+
---
46+
47+
### 3. **Lazy-Load `gtag.js`**
48+
Since GitHub Pages is static, you can lazy-load `gtag.js` to prioritize critical content. Add the following JavaScript to your Jekyll template or a separate JS file (e.g., `assets/js/analytics.js`):
49+
```javascript
50+
window.addEventListener('load', () => {
51+
const script = document.createElement('script');
52+
script.src = 'https://www.googletagmanager.com/gtag/js?id=UA-66656236-1';
53+
script.async = true;
54+
document.head.appendChild(script);
55+
script.onload = () => {
56+
window.dataLayer = window.dataLayer || [];
57+
function gtag(){dataLayer.push(arguments);}
58+
gtag('js', new Date());
59+
gtag('config', 'UA-66656236-1');
60+
};
61+
});
62+
```
63+
- Include this script in your Jekyll layout:
64+
```html
65+
<script src="{{ '/assets/js/analytics.js' | relative_url }}"></script>
66+
```
67+
- **Why it helps**: Delays `gtag.js` loading until after the page’s critical resources (e.g., HTML, CSS) are loaded, improving initial page speed.
68+
69+
---
70+
71+
### 4. **Use a CDN Proxy via Cloudflare**
72+
GitHub Pages doesn’t allow custom caching headers, but you can proxy `gtag.js` through a CDN like Cloudflare to cache it closer to your users:
73+
1. **Set up Cloudflare**:
74+
- Add your GitHub Pages site to Cloudflare (e.g., `username.github.io`).
75+
- Enable Cloudflare’s DNS and proxying for your domain.
76+
2. **Proxy `gtag.js`**:
77+
- Create a Page Rule in Cloudflare to cache the `gtag.js` script or host a local copy in your Jekyll site’s `_site` folder (e.g., `assets/js/gtag.js`).
78+
- Update your script tag:
79+
```html
80+
<script async src="{{ '/assets/js/gtag.js' | relative_url }}"></script>
81+
```
82+
- Sync the local copy with Google’s `gtag.js` periodically to ensure it’s up-to-date (manual process or via a CI/CD script).
83+
3. **Cache Settings**:
84+
- In Cloudflare, set a cache rule for the script (e.g., `Cache Everything` with a TTL of 1 hour).
85+
- **Why it helps**: Cloudflare’s edge servers reduce latency by serving the script from a location closer to your users.
86+
- **Note**: Be cautious with proxying Google’s scripts, as they may update frequently. Test thoroughly to ensure tracking works.
87+
88+
---
89+
90+
### 5. **Optimize Jekyll Build and Delivery**
91+
Ensure your Jekyll site is optimized to minimize overall page load time, which indirectly helps `gtag.js` performance:
92+
- **Minify Assets**:
93+
- Use a Jekyll plugin like `jekyll-compress` or `jekyll-minifier` to minify HTML, CSS, and JS.
94+
- Add to your `_config.yml`:
95+
```yaml
96+
plugins:
97+
- jekyll-compress
98+
```
99+
- **Enable Gzip Compression**:
100+
- GitHub Pages automatically enables Gzip for supported files, but confirm your CSS/JS files are compressed by checking the `Content-Encoding` header in browser dev tools.
101+
- **Reduce Blocking Resources**:
102+
- Minimize the number of render-blocking CSS/JS files loaded before `gtag.js`.
103+
- Use `jekyll-assets` or similar to optimize asset delivery:
104+
```yaml
105+
plugins:
106+
- jekyll-assets
107+
```
108+
- **Inline Critical CSS**:
109+
- Inline critical CSS in the `<head>` and defer non-critical CSS to reduce render-blocking time, which can make `gtag.js` appear to load faster.
110+
- **Image Optimization**:
111+
- Compress images using `jekyll-picture-tag` or a similar plugin to reduce overall page weight, freeing up bandwidth for `gtag.js`.
112+
113+
---
114+
115+
### 6. **Switch to Minimal Analytics**
116+
If `gtag.js` remains slow or analytics isn’t critical:
117+
- Consider lightweight alternatives like Plausible or Fathom, which use smaller scripts (~1 KB vs. ~50 KB for `gtag.js`).
118+
- Example for Plausible:
119+
```html
120+
<script defer data-domain="yourdomain.com" src="https://plausible.io/js/plausible.js"></script>
121+
```
122+
- Add this to your Jekyll `_includes/analytics.html` and include it in your layout.
123+
- **Why it helps**: Smaller scripts load faster, especially on GitHub Pages’ static infrastructure.
124+
125+
---
126+
127+
### 7. **Test and Monitor Performance**
128+
- **Measure Fetch Time**:
129+
- Use Chrome DevTools (Network tab) to check `gtag.js` load time.
130+
- Test with tools like Lighthouse or WebPageTest to assess overall page performance.
131+
- **Simulate User Locations**:
132+
- Use a tool like Pingdom to test load times from regions where your audience is located, as GitHub Pages and Google’s CDN performance vary geographically.
133+
- **Monitor Real User Metrics**:
134+
- If using Google Analytics, check the Site Speed report to track `gtag.js` impact.
135+
- **Jekyll-Specific Debugging**:
136+
- Run `jekyll build --profile` to identify slow-building components in your site that might indirectly affect performance.
137+
138+
---
139+
140+
### 8. **Limitations with GitHub Pages**
141+
- **No Server-Side Control**: GitHub Pages is a static host, so you can’t implement server-side tagging or custom cache headers for `gtag.js`.
142+
- **No HTTP/3**: GitHub Pages uses HTTP/2, which is fast but not as optimized as HTTP/3. A CDN like Cloudflare can upgrade to HTTP/3.
143+
- **Geographic Latency**: GitHub Pages servers are primarily US-based, so users far from the US may experience slower loads. A CDN mitigates this.
144+
145+
---
146+
147+
### Example Jekyll Setup
148+
Here’s a sample `_includes/analytics.html` for your Jekyll site combining `preconnect` and `async`:
149+
```html
150+
<link rel="preconnect" href="https://www.googletagmanager.com" crossorigin>
151+
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-66656236-1"></script>
152+
<script>
153+
window.dataLayer = window.dataLayer || [];
154+
function gtag(){dataLayer.push(arguments);}
155+
gtag('js', new Date());
156+
gtag('config', 'UA-66656236-1');
157+
</script>
158+
```
159+
Include it in your layout (`_layouts/default.html`):
160+
```html
161+
<head>
162+
</head>
163+
```
164+
165+
---
166+
167+
### Next Steps
168+
- **Test Current Performance**: Share the current fetch time for `gtag.js` (from browser dev tools) or your site’s URL, and I can analyze it further.
169+
- **Geographic Context**: Let me know your audience’s primary location (e.g., US, Europe, Asia) to tailor CDN or proxy recommendations.
170+
- **Cloudflare Setup**: If you’re open to using Cloudflare, I can provide detailed steps to proxy `gtag.js`.
171+
- **Alternative Analytics**: If you’re open to switching from Google Analytics, I can recommend specific lightweight tools and their Jekyll integration.
172+
173+
Would you like me to focus on any of these aspects or perform a specific analysis (e.g., test your site’s performance or provide a Cloudflare setup guide)?

scripts/selenium/selenium_404.py

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import argparse
2+
from selenium import webdriver
3+
from selenium.webdriver.firefox.service import Service
4+
from selenium.webdriver.common.by import By
5+
from urllib.parse import urlparse
6+
import requests
7+
import sys
8+
9+
parser = argparse.ArgumentParser(description="Crawl a website and find 404 links.")
10+
parser.add_argument("--max-check-links", type=int, default=None, help="Maximum number of links to check before exiting early.")
11+
args = parser.parse_args()
12+
13+
service = Service(executable_path="/home/lzw/bin/geckodriver")
14+
driver = webdriver.Firefox(service=service)
15+
16+
blog_url = "http://localhost:4000"
17+
domain = urlparse(blog_url).netloc
18+
19+
visited_urls = set()
20+
broken_links = []
21+
checked_links = 0
22+
23+
def is_same_domain(url, base_domain):
24+
try:
25+
parsed_url = urlparse(url)
26+
return parsed_url.netloc == base_domain
27+
except:
28+
return False
29+
30+
def check_link_status(url):
31+
if url == "http://localhost:4000/error-en":
32+
return True
33+
try:
34+
response = requests.head(url, timeout=5, allow_redirects=True)
35+
if response.status_code == 404:
36+
return True
37+
return False
38+
except requests.RequestException:
39+
return False
40+
41+
def crawl(url):
42+
global checked_links
43+
if args.max_check_links is not None and checked_links >= args.max_check_links:
44+
print(f"Reached max checked links: {args.max_check_links}")
45+
sys.exit(0)
46+
if url in visited_urls:
47+
return
48+
visited_urls.add(url)
49+
checked_links += 1
50+
if check_link_status(url):
51+
broken_links.append(url)
52+
print(f"Broken link found: {url}")
53+
return
54+
try:
55+
driver.get(url)
56+
links = driver.find_elements(By.TAG_NAME, "a")
57+
hrefs = [link.get_attribute("href") for link in links if link.get_attribute("href")]
58+
unique_hrefs = set(hrefs)
59+
for href in unique_hrefs:
60+
if href and is_same_domain(href, domain) and href not in visited_urls:
61+
crawl(href)
62+
except Exception as e:
63+
print(f"Error crawling {url}: {e}")
64+
65+
try:
66+
crawl(blog_url)
67+
if broken_links:
68+
print("\nSummary of 404 links:")
69+
for link in broken_links:
70+
print(link)
71+
else:
72+
print("No 404 links found.")
73+
except SystemExit:
74+
if broken_links:
75+
print("\nSummary of 404 links:")
76+
for link in broken_links:
77+
print(link)
78+
else:
79+
print("No 404 links found.")
80+
except Exception as e:
81+
print(f"An error occurred: {e}")
82+
finally:
83+
driver.quit()

0 commit comments

Comments
 (0)