Shopify

Shopify : créez votre store locator sans app

Le store locator ou liste des magasins est une fonctionnalité régulièrement demandée pour nos clients.
Sur Shopify, un store locator peut facilement être créé avec les métaobjects et un modèle de page dans votre thème Shopify.
Bien entendu, des apps payantes existes mais encore une fois, nous souhaitons éviter au maximum l’utilisation d’apps externe pour des raisons de performance et parce que c’est simple à faire dans le thème.
Voici les différentes étapes.

Création des meta-objets associés à vos magasins

Rendez-vous dans les paramètres de votre back-office Shopify, puis accèdez à l’onglet ‘Custom data’. Ajouter une définition parmi vos metaobjets.

Nommez votre nouvelle définition ‘Stores’, c’est le nom qui nous permettra de retrouver le meta-objet en pour pouvoir accéder en front à tous ses champs déclarés.
Les champs sont les déclarations utiles qui permettent de déclarer les données concernant chaque magasin.

Shopify : créez votre store locator sans app - 2

Voici la liste exhaustive de champs à créer. Vous pouvez créer de nouveaux champs si votre boutique nécessite d’afficher des informations supplémentaires concernant vos magasins.

Shopify : créez votre store locator sans app - 3

Voici les différents types à appliquer pour la création de chacun des champs :

  • Name : Single line text
  • Description : Rich text
  • Complete address : Multi-line text
  • Phone number : Single line text
  • Longitude : Decimal
  • Latitude : Decimal
  • Store photo : File
  • Contact email : Single line text
  • Hours : Multi-line text

Création d’un nouveau template

Désormais, vous faudra créer un template pour afficher le rendu de la liste des magasins, car par défaut cela n’est pas pris en compte dans Shopify.
Rendez-vous dans l’éditeur de code de votre thème pour le créer.

Shopify : créez votre store locator sans app - 4

Créez un fichier nommé page.stores.json dans le dossier templates.

Shopify : créez votre store locator sans app - 5

Ajoutez-y ce code ci pour pouvoir retrouver dans votre éditeur de thème votre nouveau template.


{
  "sections": {
    "main": {
      "type": "main-page",
      "settings": {}
    },
    "store-locator": {
      "type": "store-locator",
      "settings": {}
    }
  },
  "order": [
    "main",
    "store-locator"
  ]
}

Création de la page dédiée aux magasins

Rendez-vous dans la gestion des pages de votre boutique pour pouvoir dédier les magasins à une page. Ainsi vos utilisateurs retrouveront et identifieront plus facilement vos boutiques.

Shopify : créez votre store locator sans app - 6

Créez une nouvelle page nommée ‘Stores’ et associez-la au template précédemment créé, à savoir ‘stores’.

Shopify : créez votre store locator sans app - 7

Association de la page au template

Vous voici presque au bout de la démarche, il ne vous reste plus qu’à associer le template à la page.
Rendez-vous dans l’éditeur de votre thème.

Shopify : créez votre store locator sans app - 8

Ainsi vous pourrez créer, depuis l’onglet frontal, votre nouvelle page ‘Stores’.

Shopify : créez votre store locator sans app - 9
Shopify : créez votre store locator sans app - 10
Shopify : créez votre store locator sans app - 11

Intégration de la carte et des magasins

Voilà que nous allons mettre les mains dans le code. Tout d’abord, veuillez créer un script dans votre dossier assets à la racine et nommez-le section-store-locator.js. Faites de même avec le fichier qui servira de fichier de style, section-store-locator.css.
Puis importez votre fichier de style dans votre fichier liquid au début comme ceci :

{{ 'section-store-locator.css' | asset_url | stylesheet_tag }}

Ainsi que le script à la fin du contenu HTML de votre fichier liquid :

<script src="{{ 'section-store-locator.js' | asset_url }}" defer="defer"></script>

Désormais il vous faudra également les assets de leaflet, c’est ce qui nous servira pour afficher la carte et utiliser diverses fonctionnalités pour améliorer l’expérience utilisateur. Je vous conseille de les télécharger pour les avoir en local plutôt que de dépendre d’un CDN qui ne vous appartient pas et donc n’est pas maintenable par vous-même en cas d’évolution.

{{ 'leaflet.min.css' | asset_url | stylesheet_tag }}
{{ 'leaflet.min.js' | asset_url | script_tag }}

Voici les premiers pas pour afficher la liste de vos magasins, commençons par boucler sur vos magasins dans votre fichier .liquid.

<div id="store-locator-list" class="c-store-locator__list">
                {% assign stores = shop.metaobjects.stores.values %}
                {%- for store in stores %}
                    <div class="c-store-locator__item /js js-sl-item"
                         data-store-id="{{ forloop.index }}"
                         data-longitude="{{ store.longitude }}"
                         data-latitude="{{ store.latitude }}">
                        <h3 class="c-store-locator__item-title /js js-sl-item-name"
                            id="store-{{ forloop.index }}-name">{{ store.name }}</h3>
                        <div class="c-store-locator__item-address"
                             id="store-{{ forloop.index }}-address">{{ store.complete_address }}</div>
                        <button class="c-store-locator__item-btn button button--small /js js-sl-item-btn"
                                data-store-index="{{ forloop.index }}"
                                >
                            {{ section.settings.view_store_text | default: 'Voir sur la carte' }}
                        </button>
                    </div>
                {%- endfor -%}
            </div>

Puis à la suite, déclarez votre carte. Nous utilisons ici OpenStreetMap comme solution de carte, avec Leafleat comme tuiles de thème de carte.

<div id="store-locator-map" class="c-store-locator__map"></div>
const map = initializeMap();
    addStoreMarkers();
    setupEventListeners();

    function initializeMap() {
        const map = L.map('store-locator-map', {
            scrollWheelZoom: false,
            zoomControl: false
        });

        L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {}).addTo(map);

        const bounds = L.latLngBounds(stores.map(store => [store.lat, store.lng]));
        map.fitBounds(bounds, {padding: [50, 50]});

        map.whenReady(function () {
            hidePlaceholder();
        });

        return map;
    }

Nous utilisons également le système de markers de leaflet pour afficher nos magasins et les cibler sur carte.

function addStoreMarkers() {
        const customIcon = L.icon({
            iconUrl: '{{ "store-marker.svg" | inline_asset_content }}',
            iconSize: [32, 32],
            iconAnchor: [16, 32],
            popupAnchor: [0, -32]
        });

        stores.forEach(function (store) {
            const marker = L.marker([store.lat, store.lng], {
                icon: customIcon
            })
                .bindPopup(`<strong>${store.name}</strong>`)
                .addTo(map);

            marker.on('click', function () {
                centerOnStore(store.id);
            });

            markers[store.id] = marker;
        });
    }

Voici à quoi ressemble notre page désormais, voici la liste des magasins et la carte. L’un est interactif avec l’autre.

Pour aller plus loin : l’accessibilité

Veillons à améliorer l’accesibilité d’un système complexe pour les lecteurs d’écran, ce serait dommage d’avoir conçu une fonctionnalité intéressante en la rendant invisible pour une partie de nos utilisateurs.
Commençons par appliquer le role= »list » à notre liste ainsi que le role= »listitem » aux items composants notre liste.
Puis ajoutons aria-labelledby= »store-{{ forloop.index }}-name » et aria-describedby= »store-{{ forloop.index }}-address » à chacun de nos éléments.

<div id="store-locator-list" class="c-store-locator__list" role="list">
                {% assign stores = shop.metaobjects.stores.values %}
                {%- for store in stores %}
                    <div class="c-store-locator__item /js js-sl-item"
                         data-store-id="{{ forloop.index }}"
                         data-longitude="{{ store.longitude }}"
                         data-latitude="{{ store.latitude }}"
                         role="listitem"
                         tabindex="0">
                        <h3 class="c-store-locator__item-title /js js-sl-item-name"
                            id="store-{{ forloop.index }}-name">{{ store.name }}</h3>
                        <div class="c-store-locator__item-address"
                             id="store-{{ forloop.index }}-address">{{ store.complete_address }}</div>
                        <button class="c-store-locator__item-btn button button--small /js js-sl-item-btn"
                                data-store-index="{{ forloop.index }}"
                                aria-labelledby="store-{{ forloop.index }}-name"
                                aria-describedby="store-{{ forloop.index }}-address">
                            {{ section.settings.view_store_text | default: 'Voir sur la carte' }}
                        </button>
                    </div>
                {%- endfor -%}
            </div>

Vous retrouverez le contenu complet des différents fichiers dans notre thème Shopify avec une interface poussée, performante et pensée pour mobile également.

Mesurer l’engagement avec vos magasins

Un store locator, c’est bien. Savoir quels magasins intéressent le plus vos visiteurs, c’est mieux. En ajoutant quelques événements analytics, vous pourrez identifier les boutiques les plus consultées et, si vous avez un champ de recherche, les zones géographiques les plus demandées.

Ajoutez ces fonctions dans votre fichier section-store-locator.js :

// Tracker le clic sur un magasin
function trackStoreClick(storeName, storeId) {
    if (typeof gtag !== 'undefined') {
        gtag('event', 'store_click', {
            'store_name': storeName,
            'store_id': storeId
        });
    }
}

// Tracker une recherche de lieu
function trackLocationSearch(searchTerm) {
    if (typeof gtag !== 'undefined') {
        gtag('event', 'store_locator_search', {
            'search_term': searchTerm
        });
    }
}

Puis déclenchez le tracking au clic sur un magasin, que ce soit depuis la liste ou depuis un marker sur la carte :

// Au clic sur le bouton "Voir sur la carte"
document.querySelectorAll('.js-sl-item-btn').forEach(btn => {
    btn.addEventListener('click', function() {
        const item = this.closest('.js-sl-item');
        const storeName = item.querySelector('.js-sl-item-name').textContent;
        const storeId = item.dataset.storeId;
        trackStoreClick(storeName, storeId);
    });
});

// Au clic sur un marker
marker.on('click', function() {
    trackStoreClick(store.name, store.id);
    centerOnStore(store.id);
});
Dans GA4, vous retrouverez ces événements dans Rapports > Engagement > Événements. Vous pourrez ainsi créer des rapports personnalisés pour suivre les performances de chaque point de vente.