Skip to content

Commit 6a628f2

Browse files
chore: improved world map rendering & graph for bounce rate metric
Signed-off-by: Henry <mail@henrygressmann.de>
1 parent 5231411 commit 6a628f2

File tree

3 files changed

+49
-7
lines changed

3 files changed

+49
-7
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Since this is not a library, this changelog focuses on the changes that are rele
2222
- Fixed error when both `listen` and `port` configuration options are set
2323
- Added retry logic when loading the DuckDB database to handle potential locking issues on startup (e.g. when the database is being updated by another process or when using a shared network drive)
2424
- Improved filtering out invalid referrers
25-
- Improved world map rendering for bounce rate metric
25+
- Improved world map rendering & graph for bounce rate metric
2626

2727
## [v1.4.0] - 2026-03-14
2828

src/utils/referrer.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,13 @@ pub fn process_referer(referer: Option<&str>) -> Referrer {
5656
return Referrer::Local;
5757
}
5858

59-
match referer.map(url::Url::parse) {
59+
let original = referer;
60+
let referer = original.map(|referer| {
61+
// if the referer doesn't start with a scheme, add "http://" to make it parseable as a URL
62+
if referer.contains("://") { referer.to_string() } else { format!("http://{}", referer) }
63+
});
64+
65+
match referer.as_deref().map(url::Url::parse) {
6066
// valid referer are stripped to the FQDN
6167
Some(Ok(referer_uri)) => {
6268
// ignore localhost / IP addresses
@@ -73,7 +79,7 @@ pub fn process_referer(referer: Option<&str>) -> Referrer {
7379
Referrer::Fqdn(referer_fqn.to_string())
7480
}
7581
// invalid referer are kept as is (e.g. when using custom referer values outside of the browser)
76-
Some(Err(_)) => Referrer::Unknown(referer.map(ToString::to_string)),
82+
Some(Err(_)) => Referrer::Unknown(original.map(ToString::to_string)),
7783
None => Referrer::Unknown(None),
7884
}
7985
}
@@ -99,10 +105,10 @@ mod test {
99105
);
100106

101107
assert_eq!(process_referer(Some("google.com")), Referrer::Fqdn("google.com".to_string()));
102-
assert_eq!(process_referer(Some("127.0.0.1")), Referrer::Unknown(None));
103-
assert_eq!(process_referer(Some("1.1.1.1")), Referrer::Unknown(None));
104-
assert_eq!(process_referer(Some("localhost")), Referrer::Unknown(None));
105-
assert_eq!(process_referer(Some("asdf.localhost")), Referrer::Unknown(None));
108+
assert_eq!(process_referer(Some("127.0.0.1")), Referrer::Local);
109+
assert_eq!(process_referer(Some("1.1.1.1")), Referrer::Local);
110+
assert_eq!(process_referer(Some("localhost")), Referrer::Local);
111+
assert_eq!(process_referer(Some("asdf.localhost")), Referrer::Local);
106112

107113
assert_eq!(
108114
process_referer(Some("invalid referrer")),

web/src/components/graph/graph.tsx

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,30 @@ export const LineGraph = ({
9494
? scaleLinear([0, 1], [dimensions.height - paddingBottom - paddingTop, 0])
9595
: scaleLinear([0, Math.max(maxY * 1.25 || 0, 20)], [dimensions.height - paddingBottom - paddingTop, 0]);
9696

97+
const bounceTolerance = 0.01;
98+
const isExtremeBouncePoint = (d: DataPoint) =>
99+
metric === "bounce_rate" && (d.y <= bounceTolerance || d.y >= 1 - bounceTolerance);
100+
const isNormalPoint = (d: DataPoint) => !isExtremeBouncePoint(d);
101+
97102
const svgArea = area<DataPoint>()
103+
.defined(isNormalPoint)
104+
.x((d) => xAxis(d.x))
105+
.y0(yAxis(0))
106+
.y1((d) => yAxis(d.y));
107+
108+
const svgAreaFaded = area<DataPoint>()
109+
.defined(() => metric === "bounce_rate")
98110
.x((d) => xAxis(d.x))
99111
.y0(yAxis(0))
100112
.y1((d) => yAxis(d.y));
101113

102114
const svgLine = area<DataPoint>()
115+
.defined(isNormalPoint)
116+
.x((d) => xAxis(d.x))
117+
.y((d) => yAxis(d.y));
118+
119+
const svgLineFaded = area<DataPoint>()
120+
.defined(() => metric === "bounce_rate")
103121
.x((d) => xAxis(d.x))
104122
.y((d) => yAxis(d.y));
105123

@@ -111,6 +129,14 @@ export const LineGraph = ({
111129
.duration(transition)
112130
.attr("d", svgArea(data) || "");
113131

132+
svg
133+
.selectChild("#background-faded")
134+
.attr("transform", `translate(0, ${paddingTop})`)
135+
.transition()
136+
.ease(easeCubic)
137+
.duration(transition)
138+
.attr("d", svgAreaFaded(data) || "");
139+
114140
svg
115141
.selectChild("#line")
116142
.attr("transform", `translate(0, ${paddingTop})`)
@@ -119,6 +145,14 @@ export const LineGraph = ({
119145
.duration(transition)
120146
.attr("d", svgLine(data) || "");
121147

148+
svg
149+
.selectChild("#line-faded")
150+
.attr("transform", `translate(0, ${paddingTop})`)
151+
.transition()
152+
.ease(easeCubic)
153+
.duration(transition)
154+
.attr("d", svgLineFaded(data) || "");
155+
122156
const yAxisElement = svg.selectChild<SVGGElement>("#y-axis");
123157
const xAxisElement = svg.selectChild<SVGGElement>("#x-axis");
124158

@@ -287,7 +321,9 @@ export const LineGraph = ({
287321
</linearGradient>
288322
</defs>
289323
<path id="background" fill="url(#graphGradient)" stroke="none" />
324+
<path id="background-faded" fill="url(#graphGradient)" stroke="none" opacity="0.14" />
290325
<path id="line" fill="none" stroke="#a6cee3" />
326+
<path id="line-faded" fill="none" stroke="#a6cee3" opacity="0.15" />
291327
{/* doted line */}
292328
<path
293329
id="needle"

0 commit comments

Comments
 (0)