Skip to content

Commit a28a758

Browse files
author
John Rogers
committed
Enhanced analytics tracking by adding Google Analytics 4 and Hotjar integration, updated Sidebar to conditionally display Admin link for admin users, and refactored search tracking logic in DiscoverPageContent for improved performance and reliability. Removed console logs for logo resolution in DataCatalogCard and OrganizationCard components.
1 parent 855430d commit a28a758

16 files changed

Lines changed: 1952 additions & 98 deletions

.cursor-updates

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,6 @@
7272
- Fixed 'No results' message flashing during search - now only shows after search actually completes (loading goes from true to false), preventing false "0 results" display while search is in progress
7373
- Fixed variables table hiding logic - now correctly hides when get_variables returns no results on first page, regardless of whether there's a search query
7474
- Replaced /items/[slug] with catch-all route /items/[[...slug]] that pre-generates and pre-renders all item routes (by slug and UUID, 21k+ routes) with data at build time, just like studies pages - fetches from cache/API during build and passes to component, fetchResultByUuid handles both slugs and UUIDs
75-
- Removed all optional parameters (query, alpha, maxVectorDistance, maxDistanceMode) from fetchResultByUuid and fetchResultsByUuids lookup endpoints - now only passes uuid or slug to improve API performance, batch lookup still supported
75+
- Removed all optional parameters (query, alpha, maxVectorDistance, maxDistanceMode) from fetchResultByUuid and fetchResultsByUuids lookup endpoints - now only passes uuid or slug to improve API performance, batch lookup still supported
76+
- Added Google Analytics 4 with anonymized IP tracking (no cookie consent required) - configured with anonymize_ip, allow_google_signals: false, and allow_ad_personalization_signals: false for GDPR compliance
77+
- Added Hotjar tracking gated behind harmonyCookieConsent cookie (shared with harmonydata.github.io) - created HotjarTracker client component that checks for consent cookie and polls for changes to enable cross-site consent sharing

firestore.rules

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
rules_version = '2';
2+
service cloud.firestore {
3+
match /databases/{database}/documents {
4+
5+
// Helper function to check if user is admin
6+
// Admin users have a document in 'users' collection with their UID as document ID
7+
// and isAdmin: true field
8+
function isAdmin() {
9+
return request.auth != null &&
10+
exists(/databases/$(database)/documents/users/$(request.auth.uid)) &&
11+
get(/databases/$(database)/documents/users/$(request.auth.uid)).data.isAdmin == true;
12+
}
13+
14+
// Users collection: Only admins can read their own admin status document
15+
// Document ID must match the authenticated user's UID
16+
match /users/{userId} {
17+
allow read: if request.auth != null &&
18+
request.auth.uid == userId &&
19+
isAdmin();
20+
// Only admins can write (for creating admin users)
21+
allow write: if isAdmin();
22+
}
23+
24+
// Analytics events: Public can create, admins can read
25+
match /analytics_events/{eventId} {
26+
allow create: if true; // Anyone can create analytics events
27+
allow read: if isAdmin(); // Only admins can read
28+
allow update, delete: if isAdmin(); // Only admins can modify
29+
}
30+
31+
// Ratings/Feedback: Public can create, admins can read
32+
match /ratings/{ratingId} {
33+
allow create: if true; // Anyone can create feedback/ratings
34+
allow read: if isAdmin(); // Only admins can read
35+
allow update, delete: if isAdmin(); // Only admins can modify
36+
}
37+
38+
// Mismatches (Harmony quality feedback): Public can create, admins can read
39+
match /mismatches/{mismatchId} {
40+
allow create: if true; // Anyone can create mismatch reports
41+
allow read: if isAdmin(); // Only admins can read
42+
allow update, delete: if isAdmin(); // Only admins can modify
43+
}
44+
45+
// Other collections (saved_searches, saved_resources, harmonisations, etc.)
46+
// These are user-specific, so users can read/write their own data
47+
match /saved_searches/{searchId} {
48+
allow read, write: if request.auth != null &&
49+
resource.data.userId == request.auth.uid;
50+
allow create: if request.auth != null &&
51+
request.resource.data.userId == request.auth.uid;
52+
}
53+
54+
match /saved_resources/{resourceId} {
55+
allow read, write: if request.auth != null &&
56+
resource.data.userId == request.auth.uid;
57+
allow create: if request.auth != null &&
58+
request.resource.data.userId == request.auth.uid;
59+
}
60+
61+
match /harmonisations/{harmonisationId} {
62+
allow read, write: if request.auth != null &&
63+
resource.data.userId == request.auth.uid;
64+
allow create: if request.auth != null &&
65+
request.resource.data.userId == request.auth.uid;
66+
}
67+
}
68+
}

0 commit comments

Comments
 (0)