Utiliser kelvin°

Remonter les UTM pour le simulateur : widget adresse et bouton

12/8/2025
min

Vous dépensez en Google Ads, campagnes socials, emailings… mais quand arrive l’heure de mesurer la performance : plus de trace des UTM sur votre simulateur ou votre widget adresse.
Résultat ? Attribution marketing cassée, ROI fantôme, et réunions d’analyse qui tournent en rond.

Chez kelvin, on aime quand les choses sont propres et traçables. Alors on a préparé un guide pour que vos UTM restent accrochés jusqu’au clic final — et même au-delà.

Comprendre les UTM

Un UTM (Urchin Tracking Module) est un petit paramètre que l’on accroche à une URL (ex. ?utm_source=google&utm_medium=cpc&utm_campaign=hiver).
Son but : savoir d’où vient votre visiteur et à quelle campagne attribuer la conversion.
Sans lui ? Impossible d’aligner vos chiffres marketing avec la réalité commerciale.

Le scénario catastrophe que tout le monde connaît

« On veut suivre les UTM et les pousser dans HubSpot.
Mais après un clic pub et l’arrivée sur le simulateur/widget, ils disparaissent.
Du coup, impossible de les remonter via Zapier/Make. »

Effets secondaires :

  • Données de tracking incomplètes.

  • Attribution marketing qui s’écroule.

  • Décisions média prises… au doigt mouillé.

Causes fréquentes :

  • Widget embarqué qui recharge une page interne sans propager les paramètres.

  • Redirection ou script JavaScript qui nettoie l’URL.

  • Outil tiers qui ne transmet pas nativement les paramètres.

La méthode : CAPTER → CONSERVER → TRANSMETTRE

  1. CAPTER : récupérer les UTM dès la page d’arrivée.

  2. CONSERVER : stocker en sessionStorage (ou localStorage) pour survivre aux changements d’URL.

  3. TRANSMETTRE : les envoyer partout où c’est utile :

    • Dans la src du simulateur (iframe ou page dédiée)

    • Sur tous les boutons/CTA

    • Dans les formulaires (inputs cachés)

    • Vers HubSpot ou votre CRM via Zapier/Make/API

Tuto intégration : widget adresse + bouton

Ce script capture vos UTM, les garde en mémoire et les injecte dans vos liens, formulaires et iframe du simulateur.

Lien du code : https://jsfiddle.net/kelvintechnologies/6nfh5pxw/

HTML

<p>
  Pour adapter le code Javascript à votre utilisation
  <ul>
    <li>
      Modifiez l'adresse du simulateur. Variable <code>simulatorUrl</code>
    </li>
    <li>
      Si besoin, adaptez la fonction <code>getUtmParameters</code> pour modifier les paramètres de tracking à transférer
    </li>
  </ul>
</p>
<div style="position: relative">
  <input type="text" id="js-klv-address" class="c-form-input-field w-input" placeholder="Saisir une adresse">
  <div id="js-klv-results" class="c-address-results">
  </div>
</div>

Javascript

init_address_completion = (function(addressSelector, resultSelector) {

		// Change simulatorUrl to your simulator URL
    const simulatorUrl = 'https://app.go-kelvin.com/simulator/kelvin/new';
    const addressInput = document.getElementById(addressSelector);
    const resultsDiv = document.getElementById(resultSelector);
    
    // Function to get URL parameters
    const getUtmParameters = () => {
        const urlParams = new URLSearchParams(window.location.search);
        const utmParams = {
            utm_campaign: urlParams.get('utm_campaign'),
            utm_source: urlParams.get('utm_source'),
            utm_content: urlParams.get('utm_content')
        };
        console.log(utmParams);
        return utmParams;
    };

    var fetchAddressesFromText = function(text) {
        fetch(`https://api-adresse.data.gouv.fr/search/?q=${encodeURIComponent(text)}`)
            .then(response => {
                if (!response.ok) {
                    throw new Error(`HTTP error! status: ${response.status}`);
                }
                return response.json();
            })
            .then(data => {
                displayData(data.features);
            })
            .catch(error => {
                console.error('There was a problem with the fetch operation:', error);
            });
    };

    var clearAndHideResults = function(element) {
        element.innerHTML = '';
        element.style.visibility = 'hidden';
    }

    var displayData = function(features) {
        clearAndHideResults(resultsDiv);
        features.forEach(feature => {
            const properties = feature.properties;
            const coordinates = feature.geometry.coordinates;
            const address = {
                full: properties.label,
                latitude: coordinates[1],
                longitude: coordinates[0]
            };
            resultsDiv.innerHTML += row(address);
        });
        if (features.length > 0) {
            resultsDiv.style.visibility = 'visible';
        }
    };

    var row = function(address) {
        let url = `${simulatorUrl}?lat=${address.latitude}&lng=${address.longitude}&display_address=${encodeURIComponent(address.full)}`;
        
        // Add UTM parameters if they exist
        const utmParams = getUtmParameters();
        for (const [key, value] of Object.entries(utmParams)) {
            if (value) {
                url += `&${key}=${encodeURIComponent(value)}`;
            }
        }
        
        return `<div><a href="${url}" target="_blank">${address.full}</a></div>`;
    };

    // Add event listener to input
    addressInput.addEventListener('input', function() {
        if (this.value.length > 2) { // Only search if more than 2 characters are entered
            fetchAddressesFromText(this.value);
        } else {
            clearAndHideResults(resultsDiv);
        }
    });

});
init_address_completion('js-klv-address', 'js-klv-results');

CSS

.c-address-results {
	position: absolute;
  z-index: 20;
  border: 1.5px solid #fff3;
  background-color: #ffff;
  box-shadow: 0 4px 20px #00000008;
  border-radius: .75rem;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: .625rem;
  padding: .625rem .875rem;
  margin-top: 10px;
  visibility: hidden;
}
.c-address-results a {
	color: var(--primary--black);
	font-family: Roboto,sans-serif;
	font-size: 1rem;
	line-height: 100%;
	text-decoration: none;
}

Checklist avant mise en ligne

  • ✅ Test sur un parcours complet depuis une annonce réelle

  • ✅ Vérifier que tous les CTAs et iframe portent bien les UTM

  • ✅ Contrôler que les formulaires envoient les paramètres dans votre CRM

Bonnes pratiques pour ne plus jamais perdre un UTM

  • Standardiser une classe de bouton (.js-kelvin-cta) sur laquelle le script agit

  • Utiliser sessionStorage plutôt que localStorage pour éviter la pollution longue durée

  • Documenter la convention d’UTM en interne

Vous souhaitez accompagner efficacement les projets de rénovation énergétique?
On vous montre comment lors d'une démonstration de kelvin.
Réservez un créneau de demo
Vous souhaitez estimer des projets de rénovation énergétique ?
Testez le simulateur pour voir comment il s’intègre à votre site.
Tester le simulateur

Remonter les UTM pour le simulateur : widget adresse et bouton

August 12, 2025

Vous dépensez en Google Ads, campagnes socials, emailings… mais quand arrive l’heure de mesurer la performance : plus de trace des UTM sur votre simulateur ou votre widget adresse.
Résultat ? Attribution marketing cassée, ROI fantôme, et réunions d’analyse qui tournent en rond.

Chez kelvin, on aime quand les choses sont propres et traçables. Alors on a préparé un guide pour que vos UTM restent accrochés jusqu’au clic final — et même au-delà.

Comprendre les UTM

Un UTM (Urchin Tracking Module) est un petit paramètre que l’on accroche à une URL (ex. ?utm_source=google&utm_medium=cpc&utm_campaign=hiver).
Son but : savoir d’où vient votre visiteur et à quelle campagne attribuer la conversion.
Sans lui ? Impossible d’aligner vos chiffres marketing avec la réalité commerciale.

Le scénario catastrophe que tout le monde connaît

« On veut suivre les UTM et les pousser dans HubSpot.
Mais après un clic pub et l’arrivée sur le simulateur/widget, ils disparaissent.
Du coup, impossible de les remonter via Zapier/Make. »

Effets secondaires :

  • Données de tracking incomplètes.

  • Attribution marketing qui s’écroule.

  • Décisions média prises… au doigt mouillé.

Causes fréquentes :

  • Widget embarqué qui recharge une page interne sans propager les paramètres.

  • Redirection ou script JavaScript qui nettoie l’URL.

  • Outil tiers qui ne transmet pas nativement les paramètres.

La méthode : CAPTER → CONSERVER → TRANSMETTRE

  1. CAPTER : récupérer les UTM dès la page d’arrivée.

  2. CONSERVER : stocker en sessionStorage (ou localStorage) pour survivre aux changements d’URL.

  3. TRANSMETTRE : les envoyer partout où c’est utile :

    • Dans la src du simulateur (iframe ou page dédiée)

    • Sur tous les boutons/CTA

    • Dans les formulaires (inputs cachés)

    • Vers HubSpot ou votre CRM via Zapier/Make/API

Tuto intégration : widget adresse + bouton

Ce script capture vos UTM, les garde en mémoire et les injecte dans vos liens, formulaires et iframe du simulateur.

Lien du code : https://jsfiddle.net/kelvintechnologies/6nfh5pxw/

HTML

<p>
  Pour adapter le code Javascript à votre utilisation
  <ul>
    <li>
      Modifiez l'adresse du simulateur. Variable <code>simulatorUrl</code>
    </li>
    <li>
      Si besoin, adaptez la fonction <code>getUtmParameters</code> pour modifier les paramètres de tracking à transférer
    </li>
  </ul>
</p>
<div style="position: relative">
  <input type="text" id="js-klv-address" class="c-form-input-field w-input" placeholder="Saisir une adresse">
  <div id="js-klv-results" class="c-address-results">
  </div>
</div>

Javascript

init_address_completion = (function(addressSelector, resultSelector) {

		// Change simulatorUrl to your simulator URL
    const simulatorUrl = 'https://app.go-kelvin.com/simulator/kelvin/new';
    const addressInput = document.getElementById(addressSelector);
    const resultsDiv = document.getElementById(resultSelector);
    
    // Function to get URL parameters
    const getUtmParameters = () => {
        const urlParams = new URLSearchParams(window.location.search);
        const utmParams = {
            utm_campaign: urlParams.get('utm_campaign'),
            utm_source: urlParams.get('utm_source'),
            utm_content: urlParams.get('utm_content')
        };
        console.log(utmParams);
        return utmParams;
    };

    var fetchAddressesFromText = function(text) {
        fetch(`https://api-adresse.data.gouv.fr/search/?q=${encodeURIComponent(text)}`)
            .then(response => {
                if (!response.ok) {
                    throw new Error(`HTTP error! status: ${response.status}`);
                }
                return response.json();
            })
            .then(data => {
                displayData(data.features);
            })
            .catch(error => {
                console.error('There was a problem with the fetch operation:', error);
            });
    };

    var clearAndHideResults = function(element) {
        element.innerHTML = '';
        element.style.visibility = 'hidden';
    }

    var displayData = function(features) {
        clearAndHideResults(resultsDiv);
        features.forEach(feature => {
            const properties = feature.properties;
            const coordinates = feature.geometry.coordinates;
            const address = {
                full: properties.label,
                latitude: coordinates[1],
                longitude: coordinates[0]
            };
            resultsDiv.innerHTML += row(address);
        });
        if (features.length > 0) {
            resultsDiv.style.visibility = 'visible';
        }
    };

    var row = function(address) {
        let url = `${simulatorUrl}?lat=${address.latitude}&lng=${address.longitude}&display_address=${encodeURIComponent(address.full)}`;
        
        // Add UTM parameters if they exist
        const utmParams = getUtmParameters();
        for (const [key, value] of Object.entries(utmParams)) {
            if (value) {
                url += `&${key}=${encodeURIComponent(value)}`;
            }
        }
        
        return `<div><a href="${url}" target="_blank">${address.full}</a></div>`;
    };

    // Add event listener to input
    addressInput.addEventListener('input', function() {
        if (this.value.length > 2) { // Only search if more than 2 characters are entered
            fetchAddressesFromText(this.value);
        } else {
            clearAndHideResults(resultsDiv);
        }
    });

});
init_address_completion('js-klv-address', 'js-klv-results');

CSS

.c-address-results {
	position: absolute;
  z-index: 20;
  border: 1.5px solid #fff3;
  background-color: #ffff;
  box-shadow: 0 4px 20px #00000008;
  border-radius: .75rem;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: .625rem;
  padding: .625rem .875rem;
  margin-top: 10px;
  visibility: hidden;
}
.c-address-results a {
	color: var(--primary--black);
	font-family: Roboto,sans-serif;
	font-size: 1rem;
	line-height: 100%;
	text-decoration: none;
}

Checklist avant mise en ligne

  • ✅ Test sur un parcours complet depuis une annonce réelle

  • ✅ Vérifier que tous les CTAs et iframe portent bien les UTM

  • ✅ Contrôler que les formulaires envoient les paramètres dans votre CRM

Bonnes pratiques pour ne plus jamais perdre un UTM

  • Standardiser une classe de bouton (.js-kelvin-cta) sur laquelle le script agit

  • Utiliser sessionStorage plutôt que localStorage pour éviter la pollution longue durée

  • Documenter la convention d’UTM en interne

Ressources

Découvrez les articles similaires