diff --git a/ezmashup/territoires_stats.php b/ezmashup/territoires_stats.php
index 623cec3ef3538355a263fe234e0d4ee8a4e841cf..0a0168d969a7155ba6b2a5ed0242c7f36c9ba061 100644
--- a/ezmashup/territoires_stats.php
+++ b/ezmashup/territoires_stats.php
@@ -46,17 +46,183 @@ function territoires_stats_feed_initialiser_categorie_defaut(string $plugin) : s
 }
 
 /**
- * Renvoie la configuration par défaut du dossier relatif où trouver les feeds.
+ * Renvoie la configuration par défaut de la racine où trouver les feeds.
  * Cette information est utilisée a minima au chargement des feeds disponibles.
  *
- * Le plugin de statistiques pour les territoires crée dynamiquement les feeds. De fait, il les stocke dans le
- * dossier des données permanentes inaccessibles, _DIR_ETC.
+ * Le plugin crée dynamiquement les feeds. De fait, il les stocke dans le
+ * dossier des données permanentes inaccessibles, _DIR_ETC. Ce dossier n'étant pas accessible via le path de spip
+ * il est nécessaire d'indiquer la racine exacte qui fera l'objet d'un traitement particulier.
  *
  * @param string $plugin Préfixe du plugin utilisateur.
  *
- * @return string Chemin relatif du dossier où chercher les feeds.
+ * @return string Racine où chercher les feeds.
  */
-function territoires_stats_feed_initialiser_dossier(string $plugin) : string {
+function territoires_stats_feed_initialiser_racine(string $plugin) : string {
 	// Le plugin range les feeds créés dynamiquement dans _DIR_ETC.
-	return _DIR_ETC . $plugin . '/feeds/';
+	return _DIR_ETC . $plugin . '/';
+}
+
+/**
+ * Finalise l'exécution d'un feed uniquement si celle-ci s'est correctement déroulée.
+ *
+ * Le plugin rajoute la consignation des données statistiques.
+ *
+ * @package SPIP\MASHUP\SERVICE
+ *
+ * @uses unite_peuplement_consigne_identifier()
+ * @uses ezmashup_chercher_service()
+ *
+ * @param array  $feed   Configuration du feed
+ *
+ * @return void
+ */
+function territoires_stats_feed_completer_execution(array $feed) : void {
+	// Retrouver les éléments de l'unite de peuplement concernée
+	$type = $feed['tags']['type'] ?? '';
+	$pays = $feed['tags']['pays'] ?? '';
+
+	// Identification de la meta et de la variable de consigne
+	include_spip('inc/unite_peuplement');
+	$id_consigne = unite_peuplement_consigne_identifier('territoires', $type, $pays);
+	if (
+		include_spip('inc/config')
+		and ($consigne = lire_config($id_consigne, []))
+	) {
+		// Ajout de la consignation du feed de données statistiques en fonction du contexte de la consigne
+		if (!in_array('stat', $consigne['ext'])) {
+			$consigne['ext'][] = 'stat';
+		}
+		if (
+			empty($consigne['sta'])
+			or !in_array($feed['feed_id'], $consigne['sta'])
+		) {
+			$consigne['sta'][] = $feed['feed_id'];
+		}
+
+		// On met à jour la meta
+		ecrire_config($id_consigne, $consigne);
+	}
+}
+
+/**
+ * Finalise le vidage d'un feed uniquement si celui-ci s'est correctement déroulé.
+ *
+ * Le plugin Mashup Factory ne fait rien de particulier actuellement.
+ *
+ * @package SPIP\MASHUP\SERVICE
+ *
+ * @uses ezmashup_chercher_service()
+ *
+ * @param array  $feed   Configuration du feed
+ *
+ * @return void
+ */
+function territoires_stats_feed_completer_vidage(array $feed) : void {
+	// Retrouver les éléments de l'unite de peuplement concernée
+	$type = $feed['tags']['type'] ?? '';
+	$pays = $feed['tags']['pays'] ?? '';
+
+	// Identification de la meta et de la variable de consigne
+	include_spip('inc/unite_peuplement');
+	$id_consigne = unite_peuplement_consigne_identifier('territoires', $type, $pays);
+	if (
+		include_spip('inc/config')
+		and ($consigne = lire_config($id_consigne, []))
+		and in_array($feed['feed_id'], $consigne['sta'])
+	) {
+		// Retrait de la consignation du feed de données statistiques
+		$index = array_search($feed['feed_id'], $consigne['sta']);
+		if ($index !== false) {
+			unset($consigne['sta'][$index]);
+		}
+
+		// Si la liste des feeds est vide on supprime l'index 'sta' et on retire le type d'extra 'stat' de la liste
+		if (!$consigne['sta']) {
+			unset($consigne['sta']);
+			$index = array_search('stat', $consigne['ext']);
+			if ($index !== false) {
+				unset($consigne['ext'][$index]);
+			}
+		}
+
+		// On met à jour la meta
+		ecrire_config($id_consigne, $consigne);
+	}
+}
+
+// -----------------------------------------------------------------------
+// ------------------------- SOURCE DATASETS -----------------------------
+// -----------------------------------------------------------------------
+
+/**
+ * Complète un item de la source venant d'être extrait.
+ *
+ * Le plugin gère les cas où le code identifiant les territoires ne sont pas les codes ISO comme l'attend la
+ * table spip_territoires_extras (par exemple, le code INSEE en France).
+ *
+ * @param array  $item   Item d'un dataset source
+ * @param array  $feed   Configuration du feed
+ *
+ * @return array Item mis à jour
+ */
+function territoires_stats_item_completer(array $item, array $feed) : array {
+	static $type_id = null;
+	static $type = null;
+	static $pays = null;
+	static $codes_to_iso = [];
+
+	// Détermination du tag type_id qui indique quel est le code utilisé pour identifier les territoires et des autres
+	// information sur les territoires
+	if (null === $type_id) {
+		$type_id = $feed['tags']['type_id'] ?? '';
+	}
+	if (null === $type) {
+		$type = $feed['tags']['type'] ?? '';
+	}
+	if (null === $pays) {
+		$pays = $feed['tags']['pays'] ?? '';
+	}
+	if (
+		$type_id
+		and $type
+	) {
+		if ($type_id !== 'iso_territoire') {
+			// Si le code utilisé n'est pas le code primaire du territoire, on cherche celui-ci, sinon on renvoie l'item tel que.
+			if (!$codes_to_iso) {
+				// On recherche la liste des correspondances du code alternatif vers le code iso en une seule fois
+				// dans le même hit
+				// Quelque soit la demande, on récupère toutes les informations du territoire.
+				$select = ['iso_territoire', 'valeur'];
+				$where = [
+					'type_extra=' . sql_quote('code'),
+					'extra=' . sql_quote($type_id),
+					'type=' . sql_quote($type),
+				];
+				if ($pays) {
+					$where[] = 'iso_pays=' . sql_quote($pays);
+				}
+				$extras = sql_allfetsel($select, 'spip_territoires_extras', $where);
+				if ($extras) {
+					$codes_to_iso = array_column($extras, 'iso_territoire', 'valeur');
+				}
+			}
+
+			// On extrait le code utilisé pour trouver son id primaire : si il n'existe pas on rejette l'item
+			$code = $item['reg_code'][0] ?? '';
+			if (
+				$code
+				and isset($codes_to_iso[$code])
+			) {
+				$item['reg_code'][0] = $codes_to_iso[$code];
+			} else {
+				// Le code primaire est introuvable, on ne retient pas cet item
+				$item = [];
+			}
+		}
+	} else {
+		// Le tag type_id est absent, c'est une erreur du feed on ne retient aucun item de la source
+		$item = [];
+	}
+
+	return $item;
 }
diff --git a/formulaires/creer_feed_territoires.html b/formulaires/creer_feed_territoires.html
new file mode 100644
index 0000000000000000000000000000000000000000..0024ce15a12cac5a1d69aa7686327afcd84262c1
--- /dev/null
+++ b/formulaires/creer_feed_territoires.html
@@ -0,0 +1,94 @@
+<div class="formulaire_spip formulaire_editer formulaire_#FORM">
+	<h3 class="titrem"><:territoires_stats:titre_creer_feed:></h3>
+
+	[<p class="reponse_formulaire reponse_formulaire_erreur">(#ENV*{message_erreur})</p>]
+
+	<form method="post" action="#ENV{action}">
+	<div>
+		#ACTION_FORMULAIRE{#ENV{action}}
+		<fieldset>
+			<legend><:territoires_stats:legende_feed_identite:></legend>
+			<div class="editer-groupe">
+				[(#SAISIE{input, feed_id,
+					label=<:territoires_stats:label_feed_id:>,
+					explication=<:territoires_stats:explication_feed_id:>,
+					obligatoire=oui,
+					maxlength=255
+				})]
+
+				[(#SAISIE{radio, type,
+					explication=<:cartes_territoires:explication_type_territoire:>,
+					label=<:cartes_territoires:label_type_territoire:>,
+					data=#ENV{_types_territoire},
+					defaut=#ENV{_type_territoire_defaut}
+				})]
+
+			<BOUCLE_pays_type(DATA) {source table, #ENV{_pays}}>
+				<div id="pays_#CLE" class="editer-pays">
+					[(#SAISIE{radio_flex, pays_#CLE,
+						explication=#ENV{_explication_checkbox},
+						label=<:cartes_territoires:label_pays_type:>,
+						data=#VALEUR,
+						conteneur_class=#ENV{_classe_conteneur},
+						multi_cols=#ENV{_choix_multi_col/#CLE},
+						extraire_multi=oui,
+					})]
+				</div>
+			</BOUCLE_pays_type>
+			</div>
+		</fieldset>
+
+		<p class="boutons">
+			<input type="submit" class="submit" value="<:info_etape_suivante:>" />
+		</p>
+	</div>
+	</form>
+</div>
+<script type="text/javascript">
+//<![CDATA[
+	jQuery(document).ready(function() {
+		// Liste des types associés à un pays
+		const types_pays = ['subdivision', 'infrasubdivision', 'protected_area'];
+
+		// Afficher le bloc correspondant au types de carte et de territoire passé ou rien sinon.
+		function afficher_bloc_pays(type_carte, type_territoire) {
+			if (type_carte === 'carte') {
+				jQuery("div.editer-pays").hide();
+			} else {
+				if (types_pays.includes(type_territoire)) {
+					for (let t of types_pays) {
+						let id = 'div#pays_' + t;
+						if (t === type_territoire) {
+							jQuery(id).show();
+						} else {
+							jQuery(id).hide();
+						}
+					}
+				} else {
+					jQuery("div.editer-pays").hide();
+				}
+			}
+		}
+
+		afficher_bloc_pays(
+			jQuery("input[name='type_carte']:checked").val(),
+			jQuery("input[name='type']:checked").val()
+		);
+
+		jQuery("input[name='type_carte']").change(function() {
+			afficher_bloc_pays(
+				jQuery("input[name='type_carte']:checked").val(),
+				jQuery("input[name='type']:checked").val()
+			);
+			jQuery(this).blur();
+		});
+		jQuery("input[name='type']").change(function() {
+			afficher_bloc_pays(
+				jQuery("input[name='type_carte']:checked").val(),
+				jQuery("input[name='type']:checked").val()
+			);
+			jQuery(this).blur();
+		});
+	});
+//]]>
+</script>
diff --git a/formulaires/creer_feed_territoires.php b/formulaires/creer_feed_territoires.php
new file mode 100644
index 0000000000000000000000000000000000000000..b653a773234e6f5ab04da6212c8ed3e94bb6f541
--- /dev/null
+++ b/formulaires/creer_feed_territoires.php
@@ -0,0 +1,71 @@
+<?php
+/**
+ * Gestion du formulaire (assistant) de création d'un feed de données statistiques pour des territoires.
+ */
+if (!defined('_ECRIRE_INC_VERSION')) {
+	return;
+}
+
+/**
+ * Chargement des données :.
+ *
+ * @return array Tableau des données à charger par le formulaire.
+ */
+function formulaires_creer_feed_territoires_charger() : array {
+	// Initialisation des paramètres d'affichage
+	// -- Liste des types de territoire.
+	include_spip('inc/config');
+	$types_territoire = lire_config('territoires/types');
+	foreach ($types_territoire as $_type) {
+		$valeurs['_types_territoire'][$_type] = spip_ucfirst(_T("territoire:type_{$_type}"));
+	}
+	$valeurs['_type_territoire_defaut'] = 'country';
+
+	// -- Détermination des pays disponibles pour les types subdivision, infrasubdivision et protected_area
+	//    et structuration des colonnes du choix radio.
+	$select = ['t1.iso_pays', 't2.nom_usage'];
+	$from = ['spip_territoires AS t1', 'spip_territoires AS t2'];
+	$where = ['t2.iso_territoire=t1.iso_pays'];
+	foreach ($types_territoire as $_type) {
+		if (lire_config("territoires/{$_type}/populated_by_country", false)) {
+			$where[1] = 't1.type=' . sql_quote($_type);
+			$pays = sql_allfetsel($select, $from, $where, 't1.iso_pays');
+			$valeurs['_pays'][$_type] = array_column($pays, 'nom_usage', 'iso_pays');
+			$valeurs['_choix_multi_col'][$_type] = 1 + intdiv(count($valeurs['_pays'][$_type]), 10);
+			if ($valeurs['_choix_multi_col'][$_type] > 3) {
+				$valeurs['_choix_multi_col'][$_type] = 3;
+			}
+		}
+	}
+
+	return $valeurs;
+}
+
+/**
+ * Vérification du formulaire :.
+ *
+ * @return array Message d'erreur si aucun pays choisi alors que la configuration du type de teritoire l'oblige.
+ *               Sinon, chargement des champs utiles à l'étape 2 :
+ */
+function formulaires_creer_feed_territoires_verifier() : array {
+	// Initialisation des erreurs de vérification.
+	$erreurs = [];
+
+
+	return $erreurs;
+}
+
+/**
+ * Exécution du formulaire : .
+ *
+ * @return array Tableau retourné par le formulaire contenant toujours un message de bonne exécution ou
+ *               d'erreur. L'indicateur editable est toujours à vrai.
+ */
+function formulaires_creer_feed_territoires_traiter() : array {
+	// Initialisation du retour de la fonction
+	$retour = [];
+
+	// Récupération des paramètres de base de la carte et début de consolidation des champs de l'objet carte
+
+	return $retour;
+}
diff --git a/formulaires/editer_carte_territoires.html b/formulaires/editer_carte_territoires.html
new file mode 100644
index 0000000000000000000000000000000000000000..9753a2853b1c67bd1519707dc46ae35d251a9218
--- /dev/null
+++ b/formulaires/editer_carte_territoires.html
@@ -0,0 +1,35 @@
+<div class='formulaire_spip formulaire_editer formulaire_#FORM formulaire_#FORM-#ENV{id_carte}'>
+	[<p class="reponse_formulaire reponse_formulaire_ok">(#ENV**{message_ok})</p>]
+	[<p class="reponse_formulaire reponse_formulaire_erreur">(#ENV*{message_erreur})</p>]
+
+	[(#ENV{editable})
+	<form method="post" action="#ENV{action}"><div>
+		#ACTION_FORMULAIRE
+		<input type="hidden" name="id_carte" value="#ENV{id_carte}" />
+		<div class="editer-groupe">
+			[(#SAISIE{input, titre,
+				label=<:carte_territoires:champ_titre_label:>
+			})]
+
+			[(#SAISIE{textarea, descriptif,
+				label=<:carte_territoires:champ_descriptif_label:>,
+				rows=5,
+				class=inserer_barre_edition
+			})]
+
+			[(#ENV{type_carte}|=={carte}|non)
+				[(#SAISIE{checkbox_flex, exclusions,
+					explication=<:cartes_territoires:explication_etape_2_complement:>,
+					data=#ENV{_exclusions},
+					defaut=#ENV{_exclusions_defaut},
+					extraire_multi=oui,
+					conteneur_class=pleine_largeur,
+				})]
+			]
+		</div>
+		[(#REM) ajouter les saisies supplementaires : extra et autre, a cet endroit ]
+		<!--extra-->
+		<p class="boutons"><input type="submit" class="submit" value="<:bouton_enregistrer|attribut_html:/>" /></p>
+	</div></form>
+	]
+</div>
diff --git a/formulaires/editer_carte_territoires.php b/formulaires/editer_carte_territoires.php
new file mode 100644
index 0000000000000000000000000000000000000000..51d8a52c1013208a6b6e1ae1ee8ae7671e09e556
--- /dev/null
+++ b/formulaires/editer_carte_territoires.php
@@ -0,0 +1,111 @@
+<?php
+/**
+ * Gestion du formulaire de d'édition de carte_territoires.
+ */
+if (!defined('_ECRIRE_INC_VERSION')) {
+	return;
+}
+
+include_spip('inc/actions');
+include_spip('inc/editer');
+
+/**
+ * Identifier le formulaire en faisant abstraction des paramètres qui ne représentent pas l'objet edité.
+ *
+ * @param int|string $id_carte    Identifiant du carte_territoires. 'new' pour un nouveau carte_territoires.
+ * @param string     $retour      URL de redirection après le traitement
+ * @param int        $lier_trad   Identifiant éventuel d'un carte_territoires source d'une traduction
+ * @param string     $config_fonc Nom de la fonction ajoutant des configurations particulières au formulaire
+ * @param array      $row         Valeurs de la ligne SQL de l'objet carte_territoires, si connu
+ * @param string     $hidden      Contenu HTML ajouté en même temps que les champs cachés du formulaire.
+ *
+ * @return string Hash du formulaire
+ */
+function formulaires_editer_carte_territoires_identifier_dist($id_carte = 'new', $retour = '', $lier_trad = 0, $config_fonc = '', $row = [], $hidden = '') {
+	return serialize([(int) $id_carte]);
+}
+
+/**
+ * Chargement du formulaire d'édition de carte_territoires.
+ *
+ * Déclarer les champs postés et y intégrer les valeurs par défaut
+ *
+ * @uses formulaires_editer_objet_charger()
+ *
+ * @param int|string $id_carte    Identifiant du carte_territoires. 'new' pour un nouveau carte_territoires.
+ * @param string     $retour      URL de redirection après le traitement
+ * @param int        $lier_trad   Identifiant éventuel d'un carte_territoires source d'une traduction
+ * @param string     $config_fonc Nom de la fonction ajoutant des configurations particulières au formulaire
+ * @param array      $row         Valeurs de la ligne SQL de l'objet carte_territoires, si connu
+ * @param string     $hidden      Contenu HTML ajouté en même temps que les champs cachés du formulaire.
+ *
+ * @return array Environnement du formulaire
+ */
+function formulaires_editer_carte_territoires_charger_dist($id_carte = 'new', $retour = '', $lier_trad = 0, $config_fonc = '', $row = [], $hidden = '') {
+	// Charger l'objet Carte de territoires de façon standard
+	$valeurs = formulaires_editer_objet_charger('carte_territoires', $id_carte, '', $lier_trad, $retour, $config_fonc, $row, $hidden);
+
+	// Rajouter la liste des territoires et des exclusions si la carte est de type 'territoire'
+	if (
+		$valeurs
+		and !empty($valeurs['type_carte'])
+		and ($valeurs['type_carte'] === 'territoire')
+	) {
+		// -- liste des territoires inclus
+		include_spip('inc/carte_territoires');
+		$territoires_inclus = carte_territoires_detourer($valeurs['id_carte'], 'iso_territoire');
+		// -- liste des territoires exclus si il y en a
+		$parametres = json_decode($valeurs['parametres'], true);
+		$territoires_exclus = $parametres['exclusions'] ?? [];
+		// -- Construire la liste de tous les territoires avec leur nom
+		$territoires = array_merge($territoires_inclus, $territoires_exclus);
+		$territoires = sql_allfetsel('iso_territoire, nom_usage', 'spip_territoires', sql_in('iso_territoire', $territoires), '');
+		$territoires = array_column($territoires, 'nom_usage', 'iso_territoire');
+		asort($territoires);
+
+		$valeurs['_exclusions'] = $territoires;
+		$valeurs['_exclusions_defaut'] = $territoires_exclus;
+	}
+
+	return $valeurs;
+}
+
+/**
+ * Vérifications du formulaire d'édition de carte_territoires.
+ *
+ * Vérifier les champs postés et signaler d'éventuelles erreurs
+ *
+ * @uses formulaires_editer_objet_verifier()
+ *
+ * @param int|string $id_carte    Identifiant du carte_territoires. 'new' pour un nouveau carte_territoires.
+ * @param string     $retour      URL de redirection après le traitement
+ * @param int        $lier_trad   Identifiant éventuel d'un carte_territoires source d'une traduction
+ * @param string     $config_fonc Nom de la fonction ajoutant des configurations particulières au formulaire
+ * @param array      $row         Valeurs de la ligne SQL de l'objet carte_territoires, si connu
+ * @param string     $hidden      Contenu HTML ajouté en même temps que les champs cachés du formulaire.
+ *
+ * @return array Tableau des erreurs
+ */
+function formulaires_editer_carte_territoires_verifier_dist($id_carte = 'new', $retour = '', $lier_trad = 0, $config_fonc = '', $row = [], $hidden = '') {
+	return formulaires_editer_objet_verifier('carte_territoires', $id_carte);
+}
+
+/**
+ * Traitement du formulaire d'édition de carte_territoires.
+ *
+ * Traiter les champs postés
+ *
+ * @uses formulaires_editer_objet_traiter()
+ *
+ * @param int|string $id_carte    Identifiant du carte_territoires. 'new' pour un nouveau carte_territoires.
+ * @param string     $retour      URL de redirection après le traitement
+ * @param int        $lier_trad   Identifiant éventuel d'un carte_territoires source d'une traduction
+ * @param string     $config_fonc Nom de la fonction ajoutant des configurations particulières au formulaire
+ * @param array      $row         Valeurs de la ligne SQL de l'objet carte_territoires, si connu
+ * @param string     $hidden      Contenu HTML ajouté en même temps que les champs cachés du formulaire.
+ *
+ * @return array Retours des traitements
+ */
+function formulaires_editer_carte_territoires_traiter_dist($id_carte = 'new', $retour = '', $lier_trad = 0, $config_fonc = '', $row = [], $hidden = '') {
+	return formulaires_editer_objet_traiter('carte_territoires', $id_carte, '', $lier_trad, $retour, $config_fonc, $row, $hidden);
+}
diff --git a/lang/territoires_stats_fr.php b/lang/territoires_stats_fr.php
index a7e5f44ff517ef13c9616790b82036f92245451c..62679f7253d814787b59359a4bb0f721345d2f18 100644
--- a/lang/territoires_stats_fr.php
+++ b/lang/territoires_stats_fr.php
@@ -5,7 +5,23 @@ if (!defined('_ECRIRE_INC_VERSION')) {
 
 $GLOBALS[$GLOBALS['idx_lang']] = array(
 
+	// B
+	'bouton_recharger' => 'Recharger la configuration des jeux de données',
+
+	// I
+	'icone_creer_feed' => 'Créer un jeu de données',
+	'info_0_feed' => 'Aucun jeu de données',
+	'info_1_feed' => '1 jeu de données',
+	'info_feed_aucun' => 'Utilisez les boutons pour créer des jeux de données',
+	'info_nb_feed' => '@nb@ jeux de données',
+
 	// L
 	'label_feed_category_territory_data' => 'Données statistiques sur les territoires',
 
+	// M
+	'menu_peupler' => 'Ajouter des jeux de données',
+
+	// T
+	'titre_page_peupler' => 'Gestion des jeux de données sur les territoires',
+	'titre_liste_extras_stat' => 'Données statistiques',
 );
diff --git a/paquet.xml b/paquet.xml
index 70444add40d3d92a8b8d9c74a61538525e2f0428..d19360523f461306119ccfebb44ffdb79144c72f 100644
--- a/paquet.xml
+++ b/paquet.xml
@@ -14,7 +14,9 @@
 	<licence lien="http://www.gnu.org/licenses/gpl-3.0.html">GPL</licence>
 
 	<pipeline nom="declarer_tables_auxiliaires" inclure="base/territoires_stats.php" />
+    <pipeline nom="affiche_milieu" inclure="territoires_stats_pipelines.php" />
+    <pipeline nom="post_depeupler_territoire" inclure="territoires_stats_pipelines.php" />
 
-	<necessite nom="ezmashup" compatibilite="[1.0.0;]" />
+	<necessite nom="ezmashup" compatibilite="[1.0.2;]" />
     <necessite nom="territoires" compatibilite="[1.5.6;]" />
 </paquet>
diff --git a/prive/squelettes/contenu/feed_territoires_creer.html b/prive/squelettes/contenu/feed_territoires_creer.html
new file mode 100644
index 0000000000000000000000000000000000000000..8e646847ddad1d141f011506ea2c84f5a693bdfa
--- /dev/null
+++ b/prive/squelettes/contenu/feed_territoires_creer.html
@@ -0,0 +1,6 @@
+[(#AUTORISER{creer, feedterritoires}|sinon_interdire_acces)]
+<h1 class="grostitre"><:territoires_stats:titre_page_creer:></h1>
+
+[<div class="noajax">
+	(#FORMULAIRE_CREER_FEED_TERRITOIRES)
+</div>]
diff --git a/prive/squelettes/contenu/peupler_statistiques.html b/prive/squelettes/contenu/peupler_statistiques.html
new file mode 100644
index 0000000000000000000000000000000000000000..8f32e8859481c4b3f0b5a7b0fe3da0d1e9d994d4
--- /dev/null
+++ b/prive/squelettes/contenu/peupler_statistiques.html
@@ -0,0 +1,20 @@
+[(#AUTORISER{voir, _feeds}|sinon_interdire_acces)]
+#SET{categorie, territory_data}
+
+<h1 class="grostitre">
+	<:territoires_stats:titre_page_peupler:>
+</h1>
+
+[(#AUTORISER{creer, feed, '', #NULL, #ARRAY{plugin, territoires_stats}})
+	[(#URL_ECRIRE{territoires_feed_creer}|icone_verticale{<:territoires_stats:icone_creer_feed:/>,territoires_feed,new,right})]
+	<div class="clearfix"></div>
+]
+
+[(#REM) <!-- Affichage du formulaire d'admin des feeds filtré sur la catégorie des statistiques des territoires --> ]
+[<div class="ajax noscroll">
+	(#FORMULAIRE_ADMIN_FEEDS{territoires_stats, #GET{categorie}, #ENV{feed_id}, territoires_stats})
+</div>]
+
+[(#AUTORISER{creer, feed, '', #NULL, #ARRAY{plugin, territoires_stats}})
+	[(#URL_ECRIRE{territoires_feed_creer}|icone_verticale{<:territoires_stats:icone_creer_feed:/>,territoires_feed,new,right})]
+]
diff --git a/prive/squelettes/navigation/peupler_statistiques.html b/prive/squelettes/navigation/peupler_statistiques.html
new file mode 100644
index 0000000000000000000000000000000000000000..60a64ade2e287d12ccaa0a37692d43aaaaaa72b1
--- /dev/null
+++ b/prive/squelettes/navigation/peupler_statistiques.html
@@ -0,0 +1,10 @@
+[(#REM) <!-- Menu des onglets --> ]
+<INCLURE{fond=prive/squelettes/inclure/inc-navigation_territoires,
+	env} />
+
+[(#REM) <!-- Bouton de rechargement des feeds dans un bloc de raccourcis. --> ]
+#BOITE_OUVRIR{'','raccourcis'}
+	[(#REM) <!-- Inutile d'utiliser l'autorisation car elle est déjà incluse dans le contenu de la page -->]
+	[(#URL_ACTION_AUTEUR{recharger_feeds, territoires_stats, #SELF}
+		|icone_horizontale{<:territoires_stats:bouton_recharger:>, territoires_feed-24, '', #LANG_LEFT})]
+#BOITE_FERMER
diff --git a/prive/themes/spip/images/territoires_feed-xx.svg b/prive/themes/spip/images/territoires_feed-xx.svg
new file mode 100644
index 0000000000000000000000000000000000000000..8b59fad611162c10c34311e6354e94c68d068abc
--- /dev/null
+++ b/prive/themes/spip/images/territoires_feed-xx.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="64" height="64" viewBox="0, 0, 64, 64">
+  <g id="Calque_1">
+    <path d="M34.111,2.037 L39.351,7.277 L24.381,22.247 L16.971,14.836 L7.24,24.568 L2,19.327 L16.971,4.357 L24.381,11.768 L34.111,2.037 z" fill="#666666"/>
+    <path d="M1.375,20.806 L10.562,20.806 L10.562,33.25 L1.375,33.25 L1.375,20.806 z M12.094,5.25 L21.281,5.25 L21.281,33.25 L12.094,33.25 L12.094,5.25 z M22.812,13.028 L32,13.028 L32,33.25 L22.812,33.25 L22.812,13.028 z" fill="#000000" id="bar-chart-2-fill" display="none"/>
+    <path d="M28.5,36.3 L39.2,18.5 L62,61.4 L2,61.4 L22,24.3 L28.5,36.3 z M31.7,42.1 L39.1,55.7 L52.5,55.7 L38.9,30.2 L31.7,42.1 z M11.6,55.7 L32.5,55.7 L22,36.3 L11.6,55.7 z" fill="#2187E1"/>
+  </g>
+</svg>
diff --git a/territoires_stats_pipelines.php b/territoires_stats_pipelines.php
new file mode 100644
index 0000000000000000000000000000000000000000..ec95b7199f2a963e93507a0aaff06920e220fd7d
--- /dev/null
+++ b/territoires_stats_pipelines.php
@@ -0,0 +1,119 @@
+<?php
+/**
+ * Utilisations de pipelines par Territoires.
+ *
+ * @package    SPIP\TERRITOIRES\PIPELINES
+ */
+if (!defined('_ECRIRE_INC_VERSION')) {
+	return;
+}
+
+/**
+ * Ajout de contenu sur certaines pages, notamment des formulaires de liaisons entre objets.
+ * Le plugin ajoute les éventuels données statistiques complémentaires.
+ *
+ * @pipeline affiche_milieu
+ *
+ * @param array $flux Données du pipeline
+ *
+ * @return array Données du pipeline modifiées pour refléter le traitement.
+ */
+function territoires_stats_affiche_milieu(array $flux) : array {
+	if (isset($flux['args']['exec'])) {
+		$texte = '';
+		$exec = trouver_objet_exec($flux['args']['exec']);
+
+		if (
+			$exec
+			and ($exec['edition'] !== true) // page visu
+			and ($id_table = $exec['id_table_objet'])
+			and ($objet = $exec['type'])
+			and isset($flux['args'][$id_table])
+			and ($id_objet = (int) ($flux['args'][$id_table]))
+		) {
+			// Insertion des extras de type 'stat' chargés pour ce type de territoire
+			include_spip('inc/config');
+			if ($objet === 'territoire') {
+				// -- acquisition de l'objet
+				include_spip('action/editer_objet');
+				$territoire = objet_lire('territoire', $id_objet);
+				// -- Attention pour le type pays il ne faut pas passer le champ iso_pays à l'unité de peuplement
+				$pays = lire_config("territoires/{$territoire['type']}/populated_by_country", false)
+					? $territoire['iso_pays']
+					: '';
+				// -- tester si les extras 'info' sont chargées pour le type de territoire
+				include_spip('inc/territoires_unite_peuplement');
+				$extra_peuple = unite_peuplement_extra_est_charge($territoire['type'], $pays, 'stat');
+				if ($extra_peuple) {
+					$texte .= recuperer_fond(
+						'prive/objets/liste/territoires_extras',
+						[
+							'iso_territoire' => $territoire['iso_territoire'],
+							'type_extra'     => 'stat',
+							'titre'          => _T('territoires_stats:titre_liste_extras_stat')
+						]
+					);
+				}
+			}
+
+			// Insertion dans la fiche objet.
+			if ($texte) {
+				if ($p = strpos($flux['data'], '<!--affiche_extra-->')) {
+					$flux['data'] = substr_replace($flux['data'], $texte, $p, 0);
+				} elseif ($p = strpos($flux['data'], '<!--affiche_milieu-->')) {
+					$flux['data'] = substr_replace($flux['data'], $texte, $p, 0);
+				} else {
+					$flux['data'] .= $texte;
+				}
+			}
+		}
+	}
+
+	return $flux;
+}
+
+/**
+ * Complément à la fonction de dépeuplement des territoires.
+ *
+ * Le plugin supprime les feeds associées à l'unité de peuplement concernée.
+ *
+ * @pipeline post_depeupler_territoire
+ *
+ * @param array $flux Données du pipeline
+ *
+ * @return array Données du pipeline telles que reçues.
+ */
+function territoires_stats_post_depeupler_territoire(array $flux) : array {
+	// Vider les extras de type 'stat' pour l'unité de traitement concernée
+	if (
+		!empty($flux['args']['type'])
+		and isset($flux['args']['pays'])
+	) {
+		$type = $flux['args']['type'];
+		$pays = $flux['args']['pays'];
+
+		// On vérifie que des données statistiques exitent pour l'unite de peuplement
+		include_spip('inc/territoires_unite_peuplement');
+		$extra_peuple = unite_peuplement_extra_est_charge($type, $pays, 'stat');
+		if ($extra_peuple) {
+			// Identification de la meta et de la variable de consigne
+			include_spip('inc/unite_peuplement');
+			$id_consigne = unite_peuplement_consigne_identifier('territoires', $type, $pays);
+			if (
+				include_spip('inc/config')
+				and ($consigne = lire_config($id_consigne, []))
+			) {
+				// On récupère la liste des feeds constitutifs des jeux de données
+				$feeds = $consigne['sta'];
+
+				// On supprime les extras de ces jeux de données
+				$where = sql_in('feed_id', $feeds);
+				sql_delete('spip_territoires_extras', $where);
+			}
+
+		}
+
+	}
+
+	return $flux;
+}