Skip to content

Commit da24fc6

Browse files
committed
feat: Implement analytics tracking for user interactions and add new documentation on Python docstrings
1 parent 861cd00 commit da24fc6

7 files changed

Lines changed: 550 additions & 64 deletions

File tree

.vitepress/config.mts

Lines changed: 65 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -66,65 +66,72 @@ export default defineConfig({
6666
},
6767
sidebar: [
6868
{
69-
text: "Amazon to Scrap Local Alexa Processing: All Voice Commands Moving to the Cloud",
70-
link: "/docs/Amazon-to-Scrap-Local-Alexa-Processing.md",
69+
text: "Penify Blogs",
70+
items: [{
71+
text: "🧠 How Much Docstring Is Enough? A Practical Guide for Python Developers",
72+
link: "/docs/how-much-docstring-is-enough.md",
73+
},
74+
{
75+
text: "Amazon to Scrap Local Alexa Processing: All Voice Commands Moving to the Cloud",
76+
link: "/docs/Amazon-to-Scrap-Local-Alexa-Processing.md",
77+
},
78+
{
79+
text: "Gemma 3: The Most Powerful AI Model for Single-GPU Deployment in 2025/March",
80+
link: "/docs/current-strongest-model-that-fits-on-a-single-GPU.md",
81+
},
82+
{
83+
text: "📚 DeepSeek’s Smallpond: Extending DuckDB for Distributed Big Data Processing",
84+
link: "/docs/extending-duck-db-for-distrubuted-data-processing.md",
85+
},
86+
{
87+
text: "📚 Chain of Draft: Thinking Faster with Less",
88+
link: "/docs/chain-of-draft.md",
89+
},
90+
{
91+
text: "📜 How to Streamline LLM Applications with LiteLLM Proxy: A Simple Guide",
92+
link: "/docs/Streamline-LLM-Applications-with-LiteLLM.md",
93+
},
94+
{
95+
text: "📜 20 Essential Git Command-Line Tricks for Developers",
96+
link: "/docs/command-line-tricks-developer-should-know.md",
97+
},
98+
{
99+
text: "☁️ Run HyperDrive Using Azure",
100+
link: "/docs/run-hyperdrive-using-azure.md",
101+
},
102+
{
103+
text: "⚖️ AzureML vs HyperDrive",
104+
link: "/docs/azureml-hyperdrive.md",
105+
},
106+
{
107+
text: "🔍 A Comparative Overview of LangChain, Semantic Kernel, AutoGen",
108+
link: "/docs/comparative-anlaysis-of-langchain-semantic-kernel-autogen.md",
109+
},
110+
{
111+
text: "📚 Automated Code Documentation: A Decade in Review",
112+
link: "/docs/automated-source-code-documentation.md",
113+
},
114+
{
115+
text: "✍️ Simplify Git Commits with Penify-CLI's Summary Generator",
116+
link: "/docs/commit-summary-with-cli.md",
117+
},
118+
{
119+
text: "🤖 Automate Code Documentation with Penify-CLI",
120+
link: "/docs/code-documentation-with-cli.md",
121+
},
122+
{
123+
text: "📩 Semantic Commit Messages: Elevating Your Code Quality and Collaboration",
124+
link: "/docs/semantic-commit-messages.md",
125+
},
126+
{
127+
text: "🐍 Four Common Docstring Formats in Python",
128+
link: "/docs/common-docstring-format-in-python.md",
129+
},
130+
{
131+
text: "🌱 Penify Genesis",
132+
link: "/docs/penify-genesis",
133+
}]
71134
},
72-
{
73-
text: "Gemma 3: The Most Powerful AI Model for Single-GPU Deployment in 2025/March",
74-
link: "/docs/current-strongest-model-that-fits-on-a-single-GPU.md",
75-
},
76-
{
77-
text: "📚 DeepSeek’s Smallpond: Extending DuckDB for Distributed Big Data Processing",
78-
link: "/docs/extending-duck-db-for-distrubuted-data-processing.md",
79-
},
80-
{
81-
text: "📚 Chain of Draft: Thinking Faster with Less",
82-
link: "/docs/chain-of-draft.md",
83-
},
84-
{
85-
text: "📜 How to Streamline LLM Applications with LiteLLM Proxy: A Simple Guide",
86-
link: "/docs/Streamline-LLM-Applications-with-LiteLLM.md",
87-
},
88-
{
89-
text: "📜 20 Essential Git Command-Line Tricks for Developers",
90-
link: "/docs/command-line-tricks-developer-should-know.md",
91-
},
92-
{
93-
text: "☁️ Run HyperDrive Using Azure",
94-
link: "/docs/run-hyperdrive-using-azure.md",
95-
},
96-
{
97-
text: "⚖️ AzureML vs HyperDrive",
98-
link: "/docs/azureml-hyperdrive.md",
99-
},
100-
{
101-
text: "🔍 A Comparative Overview of LangChain, Semantic Kernel, AutoGen",
102-
link: "/docs/comparative-anlaysis-of-langchain-semantic-kernel-autogen.md",
103-
},
104-
{
105-
text: "📚 Automated Code Documentation: A Decade in Review",
106-
link: "/docs/automated-source-code-documentation.md",
107-
},
108-
{
109-
text: "✍️ Simplify Git Commits with Penify-CLI's Summary Generator",
110-
link: "/docs/commit-summary-with-cli.md",
111-
},
112-
{
113-
text: "🤖 Automate Code Documentation with Penify-CLI",
114-
link: "/docs/code-documentation-with-cli.md",
115-
},
116-
{
117-
text: "📩 Semantic Commit Messages: Elevating Your Code Quality and Collaboration",
118-
link: "/docs/semantic-commit-messages.md",
119-
},
120-
{
121-
text: "🐍 Four Common Docstring Formats in Python",
122-
link: "/docs/common-docstring-format-in-python.md",
123-
},
124-
{
125-
text: "🌱 Penify Genesis",
126-
link: "/docs/penify-genesis",
127-
}
128135
],
129136
socialLinks: [
130137
{icon: {svg: `<?xml version="1.0" encoding="iso-8859-1"?>

.vitepress/theme/Analytics.vue

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
<script setup>
2+
import { onMounted, onUnmounted, watch } from 'vue'
3+
import { useRoute, useData } from 'vitepress'
4+
import { pageView, trackLinkClick, inHouseAnalytics } from './analytics'
5+
6+
const route = useRoute()
7+
const { page } = useData()
8+
9+
// Track page view on initial load
10+
onMounted(() => {
11+
// Force immediate page view tracking
12+
trackPageView()
13+
14+
// Set up event listeners for interaction tracking
15+
addLinkClickListeners()
16+
addButtonClickListeners()
17+
addScrollTracking()
18+
19+
// Log successful initialization
20+
console.log('Analytics tracking initialized')
21+
})
22+
23+
function trackPageView() {
24+
// Track the page view with current URL and referrer
25+
inHouseAnalytics('pageView', {
26+
url: window.location.href,
27+
path: route.path,
28+
referrer: document.referrer
29+
})
30+
}
31+
32+
// Track page views on route changes
33+
// This is the VitePress-compatible way to track route changes
34+
watch(() => route.path, (newPath, oldPath) => {
35+
if (newPath !== oldPath) {
36+
console.log(`Route changed: ${oldPath} -> ${newPath}`)
37+
setTimeout(() => {
38+
// Track page view after route change
39+
trackPageView()
40+
}, 100)
41+
}
42+
})
43+
44+
// Clean up event listeners
45+
onUnmounted(() => {
46+
removeLinkClickListeners()
47+
removeButtonClickListeners()
48+
removeScrollTracking()
49+
})
50+
51+
// Track clicks on links
52+
function addLinkClickListeners() {
53+
document.addEventListener('click', handleLinkClick)
54+
}
55+
56+
function removeLinkClickListeners() {
57+
document.removeEventListener('click', handleLinkClick)
58+
}
59+
60+
function handleLinkClick(event) {
61+
const link = event.target.closest('a')
62+
if (link && link.href) {
63+
// Track all link clicks with href, target, and referrer
64+
inHouseAnalytics('linkClick', {
65+
url: link.href,
66+
text: link.innerText || link.textContent,
67+
referrer: document.referrer || window.location.href
68+
})
69+
}
70+
}
71+
72+
// Track button clicks
73+
function addButtonClickListeners() {
74+
document.addEventListener('click', handleButtonClick)
75+
}
76+
77+
function removeButtonClickListeners() {
78+
document.removeEventListener('click', handleButtonClick)
79+
}
80+
81+
function handleButtonClick(event) {
82+
const button = event.target.closest('button')
83+
if (button) {
84+
// Track all button clicks
85+
inHouseAnalytics('buttonClick', {
86+
text: button.innerText || button.textContent,
87+
id: button.id,
88+
class: button.className,
89+
referrer: document.referrer || window.location.href
90+
})
91+
}
92+
}
93+
94+
// Track scroll depth
95+
let scrollTracker
96+
function addScrollTracking() {
97+
scrollTracker = new ScrollDepthTracker()
98+
}
99+
100+
function removeScrollTracking() {
101+
if (scrollTracker) {
102+
scrollTracker.destroy()
103+
}
104+
}
105+
106+
// ScrollDepthTracker class to track user scroll depth
107+
class ScrollDepthTracker {
108+
constructor() {
109+
this.tracked = {
110+
'25': false,
111+
'50': false,
112+
'75': false,
113+
'100': false
114+
}
115+
this.handleScroll = this.handleScroll.bind(this)
116+
window.addEventListener('scroll', this.handleScroll, { passive: true })
117+
}
118+
119+
handleScroll() {
120+
const scrollTop = window.scrollY
121+
const docHeight = document.documentElement.scrollHeight - window.innerHeight
122+
if (docHeight <= 0) return
123+
124+
const scrollPercent = (scrollTop / docHeight) * 100
125+
126+
if (scrollPercent >= 25 && !this.tracked['25']) {
127+
this.tracked['25'] = true
128+
inHouseAnalytics('scroll', {
129+
depth: '25%',
130+
url: window.location.href,
131+
referrer: document.referrer
132+
})
133+
}
134+
if (scrollPercent >= 50 && !this.tracked['50']) {
135+
this.tracked['50'] = true
136+
inHouseAnalytics('scroll', {
137+
depth: '50%',
138+
url: window.location.href,
139+
referrer: document.referrer
140+
})
141+
}
142+
if (scrollPercent >= 75 && !this.tracked['75']) {
143+
this.tracked['75'] = true
144+
inHouseAnalytics('scroll', {
145+
depth: '75%',
146+
url: window.location.href,
147+
referrer: document.referrer
148+
})
149+
}
150+
if (scrollPercent >= 99 && !this.tracked['100']) {
151+
this.tracked['100'] = true
152+
inHouseAnalytics('scroll', {
153+
depth: '100%',
154+
url: window.location.href,
155+
referrer: document.referrer
156+
})
157+
}
158+
}
159+
160+
destroy() {
161+
window.removeEventListener('scroll', this.handleScroll)
162+
}
163+
}
164+
</script>
165+
166+
<template>
167+
<!-- This component doesn't render anything -->
168+
</template>

.vitepress/theme/Layout.vue

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
<template #aside-bottom>
44
<ShareButtons />
55
<EmailSignup />
6+
<Analytics />
67
</template>
78
<template #doc-footer-before>
89
<AuthorInfo />
9-
<Comments />
10+
<Comments />
1011
</template>
12+
1113
</Layout>
1214
</template>
1315

@@ -17,6 +19,7 @@ import ShareButtons from './ShareButtons.vue'
1719
import AuthorInfo from './AuthorInfo.vue'
1820
import EmailSignup from './EmailSignup.vue'
1921
import Comments from './Comments.vue'
22+
import Analytics from './Analytics.vue'
2023
2124
const { Layout } = DefaultTheme
22-
</script>
25+
</script>

0 commit comments

Comments
 (0)