-
Notifications
You must be signed in to change notification settings - Fork 43
[Feature] Analytics & Reporting
Analytics & tracking are opt-in features due to privacy concerns. We as a vendor do not enable this feature out of the box.
To enable tracking, visit Violet Rails Admin - Web Settings and mark the tracking checkbox:
Before opting into analytics its advisable to choose a data retention policy (for GDPR compliance for example) by navigating to Violet Rails Admin - Web Settings and selecting how often you want the system to purge analytics related data:
Violet Rails bundles the definitive & battle-tested ™️ first-party tracking gem for Rails: https://github.com/ankane/ahoy and integrates its tracking capabilities with your business application seamlessly. In addition to tracking, Violet also provides various dynamically generated dashboards for gleaning insights into your website analytics and business logic.
- Section Views - when visitors read parts of the page
- Video watch time - find out how long someone watched a video before they bounced
- Clicks - find out which parts of your website and app attract attention
- Form submissions - find out how often people submit information and payments
- Any other event - see developer docs for custom events
To track clicks/touches on any DOM element. Append the following data attributes
-
data-violet-track-click="true"
-> this tells Violet to track clicks -
data-violet-event-name="your-dasherized-unique-identifier-here"
-> this tells Violet which event to track clicks under -
data-violet-event-label="your human friendly label here"
-> this sets the label of the event
- see visit tracking segmented by time period and page
- see trends compared to the previous period
- see complete event list per visit and visitor
- track video watch time reliably, even when the visitor quits the browser
- see analytics on a per video basis
- see demographics on a per video basis
- track which sections are being viewed and how often
- track form submissions over periods of time
It is able to visualize and query analytics data:
and show analytics events grouped by name:
To track custom events in the CMS, simply call ahoy
in a script tag or in your javascript
layout:
full docs: https://github.com/ankane/ahoy.js
ahoy.track("My second event", {language: "JavaScript"});
and it will show up as a custom event
see demo video here: https://user-images.githubusercontent.com/25191509/169423339-76a21a86-eed8-4999-bce8-28fa48da326f.mp4
All analytics can be queried via GraphQL. See here for usage: https://github.com/restarone/violet_rails/blob/master/test/controllers/graphql_controller_test.rb
#Reporting A periodic report delivered to you containing stats from your app.
Select the users you want to have access to this feature and make sure Deliver Analytics Report is checked.
Next select how often you want to see a report by navigating to Admin -> Web Settings. This will send the report periodically to the users you have selected
You can define and track custom events such as when someone visits a page or clicks a button with ahoy.js.
Call ahoy.track
to track an event. To register a single occurrence of an event, you can save an object containing information related to analytics and visitor events to session storage.
To detect when someone visits a section on a page, you can use the Intersection Observer API.
<main>
<section>
<h1>Tell Your Psychedelic Story</h1>
<button data-analytics-id="hero-section-story-button">CTA</button>
</section>
<section data-analytics-id="share-story">
<h2>Share Your Psychedelic Story</h2>
<button data-analytics-id="share-story-section-story-button">CTA</button>
</section>
<section data-analytics-id="join-story-project">
<h2>Join The Psychedelic Storytelling Project</h2>
<button data-analytics-id="join-story-project-section-story-button">CTA</button>
</section>
<section data-analytics-id="quotes">
<!-- content here -->
</section>
</main>
<script>
function initAnalytics() {
const analyticsBrowserStorageKey = "nikeanLandingAnalytics";
const sectionsViewedMap = {
"share-story": false,
"join-story-project": false,
quotes: false,
partners: false,
}
const landingAnalytics = JSON.parse(
sessionStorage.getItem(analyticsBrowserStorageKey)
);
if (!landingAnalytics) {
const value = {
analyticsHaveBeenAdded: false,
sectionsViewedMap
};
sessionStorage.setItem(analyticsBrowserStorageKey, JSON.stringify(value));
}
const analyticsHaveBeenAdded = landingAnalytics?.["analyticsHaveBeenAdded"];
if (!analyticsHaveBeenAdded) addAnalytics();
setUpObserversForTrackingSectionViews();
function setUpObserversForTrackingSectionViews() {
trackSectionViews(
document.querySelector("[data-analytics-id='share-story']")
);
trackSectionViews(
document.querySelector("[data-analytics-id='join-story-project']")
);
trackSectionViews(document.querySelector("[data-analytics-id='quotes']"));
trackSectionViews(
document.querySelector("[data-analytics-id='partners']")
);
function trackSectionViews(target) {
const sectionName = target.dataset.analyticsId;
const observerOptions = {
root: null,
threshold: 0.75,
};
const observer = new IntersectionObserver((entries) => {
const landingAnalytics = JSON.parse(
sessionStorage.getItem(analyticsBrowserStorageKey)
);
const entry = entries[0];
const targetHasBeenViewed =
landingAnalytics.sectionsViewedMap[sectionName];
if (entry.isIntersecting && !targetHasBeenViewed) {
ahoy.track(`web/root/view-section-${sectionName}`, {
language: "JavaScript",
});
landingAnalytics.sectionsViewedMap[sectionName] = true;
sessionStorage.setItem(
analyticsBrowserStorageKey,
JSON.stringify(landingAnalytics)
);
}
}, observerOptions);
observer.observe(target);
}
}
function addAnalytics() {
ahoy.track("web/root/landing-page-visited", {
language: "JavaScript",
});
trackStoryBtnClicks();
function trackStoryBtnClicks() {
document.addEventListener("click", function (e) {
if (e.target.classList.contains("cta")) {
ahoy.track(`web/root/${e.target.dataset.analyticsId}-clicked`, {
language: "JavaScript",
});
}
});
}
const value = {
analyticsHaveBeenAdded: true,
sectionsViewedMap
};
sessionStorage.setItem(analyticsBrowserStorageKey, JSON.stringify(value));
}
}
</script>
- names for events on the website level should have this structure ->
web/<page-name>/<event-name>
- e.g. an event for tracking landing page visits can have a name like
web/root/landing-page-visited
- e.g. an event for tracking landing page visits can have a name like
- names for events on the API level should have this structure ->
API/<API-namespace-name>/<event-name>
- e.g. an event for tracking when someone views a form associated with
blog
API namespace can have a name likeAPI/blog/form-viewed
- e.g. an event for tracking when someone views a form associated with
- during testing, all event names should be postfixed with
-test
- e.g.
web/root/landing-page-visited-test
- e.g.