Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add matomo event tracking #246

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -14,6 +14,7 @@
- Handle previous format of link to discussions, e.g. from e-mails [#241](https://github.com/etalab/udata-front/pull/241)
- Add `last_update` sort in datasets page [#242](https://github.com/etalab/udata-front/pull/242)
- Fix `.fr-btn` in `.markdown` [#243](https://github.com/etalab/udata-front/pull/243)
- Add Matomo event tracking [#246](https://github.com/etalab/udata-front/pull/246)
- New scope for Captchetat piste OAuth [#250](https://github.com/etalab/udata-front/pull/250)

## 3.2.2 (2023-04-18)
Expand Down
Expand Up @@ -79,7 +79,7 @@
:href="resource.latest"
:title="$t('Download resource')"
download
class="fr-btn fr-btn--secondary fr-btn--secondary-grey-500 fr-icon-download-line fr-icon--sm"
class="fr-btn fr-btn--secondary fr-btn--secondary-grey-500 fr-icon-download-line fr-icon--sm matomo_download"
>
</a>
</p>
Expand All @@ -103,14 +103,44 @@
<ul class="fr-tabs__list" role="tablist" :aria-label="$t('Resource menu')">
<template v-if="hasExplore">
<li role="presentation">
<button :id="resourcePreviewButtonId" class="fr-tabs__tab" tabindex="0" role="tab" aria-selected="true" :aria-controls="resourcePreviewTabId">{{$t('Preview')}}</button>
<button
:id="resourcePreviewButtonId"
class="fr-tabs__tab"
tabindex="0"
role="tab"
aria-selected="true"
:aria-controls="resourcePreviewTabId"
@click="registerEvent(resourcePreviewButtonId)"
>
{{$t('Preview')}}
</button>
</li>
<li role="presentation">
<button :id="resourceStructureButtonId" class="fr-tabs__tab" tabindex="0" role="tab" aria-selected="false" :aria-controls="resourceStructureTabId">{{$t('Data structure')}}</button>
<button
:id="resourceStructureButtonId"
class="fr-tabs__tab"
tabindex="0"
role="tab"
aria-selected="false"
:aria-controls="resourceStructureTabId"
@click="registerEvent(resourceStructureButtonId)"
>
{{$t('Data structure')}}
</button>
</li>
</template>
<li role="presentation">
<button :id="resourceInformationButtonId" class="fr-tabs__tab" :tabindex="resourceInformationTabIndex" role="tab" :aria-selected="resourceInformationSelectedTab" :aria-controls="resourceInformationTabId">{{$t('Metadata')}}</button>
<button
:id="resourceInformationButtonId"
class="fr-tabs__tab"
:tabindex="resourceInformationTabIndex"
role="tab"
:aria-selected="resourceInformationSelectedTab"
:aria-controls="resourceInformationTabId"
@click="registerEvent(resourceInformationButtonId)"
>
{{$t('Metadata')}}
</button>
</li>
</ul>
<div
Expand Down Expand Up @@ -260,7 +290,7 @@
</template>

<script>
import { inject, defineComponent, ref, computed } from "vue";
import { defineComponent, ref, computed, unref } from "vue";
import SchemaLoader from "./schema-loader.vue";
import useOwnerName from "../../../composables/useOwnerName";
import useResourceImage from "../../../composables/useResourceImage";
Expand Down Expand Up @@ -306,15 +336,44 @@ export default defineComponent({
const owner = useOwnerName(props.resource);
const resourceImage = useResourceImage(props.resource);
const { getComponentsForHook } = useComponentsForHook();

/** @type {import("vue").Ref<HTMLElement | undefined>} */
const content = ref();

const expanded = ref(false);
const expand = () => {
if(expanded.value) {
globalThis._paq?.push(['trackEvent', 'Close resource', props.resource.id]);
} else {
globalThis._paq?.push(['trackEvent', 'Open resource', props.resource.id]);
if(hasExplore.value) {
registerEvent(resourcePreviewButtonId);
} else if (hasSchema.value) {
registerEvent(resourceStructureButtonId);
} else {
registerEvent(resourceInformationButtonId);
}
}
expanded.value = !expanded.value;
if(content.value) {
toggleAccordion(content.value, expanded.value);
}
}

/**
*
* @param {import("vue").ComputedRef<string> | string} tab Tab name
*/
const registerEvent = (tab) => {
const tabName = unref(tab);
globalThis._paq?.push(['trackEvent', 'View resource tab', props.resource.id, tab]);
if(tabName === resourcePreviewButtonId.value) {
globalThis._paq?.push(['trackEvent', 'Show preview', props.resource.id]);
} else if (tabName === resourceStructureButtonId.value) {
globalThis._paq?.push(['trackEvent', 'Show data structure', props.resource.id]);
}
}

const availabilityChecked = computed(() => props.resource.extras && props.resource.extras['check:status']);
const lastUpdate = computed(() => props.resource.last_modified);
const unavailable = computed(() => availabilityChecked.value && availabilityChecked.value >= 400);
Expand All @@ -337,6 +396,7 @@ export default defineComponent({
const resourceInformationTabIndex = computed(() => hasExplore.value ? -1 : 0);

return {
registerEvent,
owner,
resourceImage,
filesize,
Expand Down
Expand Up @@ -97,7 +97,7 @@
{{$t('Reset filters')}}
</button>
<a
class="fr-btn fr-btn--secondary fr-btn--secondary-grey-500 fr-icon-download-line fr-btn--icon-left justify-center w-100"
class="fr-btn fr-btn--secondary fr-btn--secondary-grey-500 fr-icon-download-line fr-btn--icon-left justify-center w-100 matomo_download"
:href="downloadLink"
v-else-if="downloadLink"
>
Expand Down
Expand Up @@ -19,6 +19,7 @@ selects.forEach((select) => {
select.disabled = true;
}
select.form?.submit();
globalThis._paq?.push(['trackEvent', 'Search', 'Sort', select.value]);
});
}
});
14 changes: 9 additions & 5 deletions udata_front/theme/gouvfr/assets/js/components/vanilla/tabs.js
Expand Up @@ -30,21 +30,25 @@ tabs.forEach((tab) => {
tabsButtons.forEach((tabButton) => {
tabButton.addEventListener("click", (el) => {
el.preventDefault();
const target = /** @type {HTMLElement} */ (el.target);

const previouslyActive = Array.from(tabsButtons).find((tab) =>
tab.getAttribute("aria-selected") === "true"
);
if (previouslyActive) {
previouslyActive.setAttribute("aria-selected", "false");
const previousAriaControls = previouslyActive.getAttribute("aria-controls") || "";
document
.getElementById(previouslyActive.getAttribute("aria-controls"))
.classList.remove("fr-unhidden");
.getElementById(previousAriaControls)
?.classList.remove("fr-unhidden");
}

el.target.setAttribute("aria-selected", "true");
const ariaControls = target.getAttribute("aria-controls") || "";
target.setAttribute("aria-selected", "true");
document
.getElementById(el.target.getAttribute("aria-controls"))
.classList.add("fr-unhidden");
.getElementById(ariaControls)
?.classList.add("fr-unhidden");
globalThis._paq?.push(['trackEvent', 'Move page to tab', window.location.pathname, tabButton.textContent]);
});
});
});
Expand Up @@ -35,13 +35,16 @@ function tryPreviousHashes(target) {
}

/**
* Update UI to match hash
* Update UI to match hash.
* This is done on page launch with hash and when the hash is updated with a link or manual edition.
* It isn't triggered on hash update from `handleUpdateUrlButtons` below.
*/
function moveToHash() {
const hash = window.location.hash;
if(!hash) {
return;
}
globalThis._paq?.push(['trackEvent', 'Move page to hash', window.location.pathname, hash]);
if(hash.startsWith("#/")) {
moveToCurrentHash(hash.slice(2));
} else {
Expand All @@ -68,6 +71,7 @@ export default function handleUpdateUrlButtons() {
if(!url.hash.includes(targetHash)) {
url.hash = targetHash;
window.history.pushState(null, "", url);
globalThis._paq?.push(['trackEvent', 'Move page to hash', window.location.pathname, targetHash]);
}
});
});
Expand Down
Expand Up @@ -62,7 +62,7 @@
href="{{ resource.latest }}"
title="{{ _('Download resource') }}"
download
class="fr-btn fr-btn--sm fr-icon-download-line"
class="fr-btn fr-btn--sm fr-icon-download-line matomo_download"
></a>
</li>
{% endif %}
Expand Down