Lancement d'un entonnoir de vente auto-hébergé
Faites passer un entonnoir de vente de zéro à publié sur une infrastructure contrôlée par l'opérateur, en utilisant Autonnel (Apache-2.0). Cette compétence est l'étape de construction ; concevez d'abord l'entonnoir avec sales-funnel-blueprint, et confirmez que l'auto-hébergement est le bon choix avec funnel-platform-picker si celui-ci est encore ouvert.
Étape 1 : choisir le mode d'exécution
| Chemin | Coût à faible volume | Charge d'exploitation | Utilisation recommandée |
|---|---|---|---|
| Cloudflare Workers | Effectivement 0 $ plus une base Postgres | Pas de serveurs, pas de correctifs | Par défaut pour la production. Les pages d'entonnoir sont pour la plupart des actifs statiques, que Workers sert gratuitement et sans limite |
| Docker | Coût d'un VPS ou d'un hôte de conteneurs | À vous : mises à jour, sauvegardes, disponibilité | Évaluation locale en deux minutes, ou un serveur que vous gérez déjà et sur lequel vous voulez les données |
| Checkout source (Node) | Coût d'un VPS ou d'un hôte de conteneurs | À vous | Modification d'Autonnel lui-même, ou exécution directe de la construction Node |
Recommander Workers sauf si l'opérateur a une raison spécifique de ne pas le faire : le modèle de tarification correspond presque parfaitement aux entonnoirs de vente, et il élimine toute une catégorie de travail qui fait que les gens évitent l'auto-hébergement.
Utilisez Docker pour un premier aperçu dans tous les cas. C'est le moyen le plus rapide de voir le produit, et rien de ce que vous construisez localement n'est perdu : le même schéma et la même interface d'administration alimentent les deux chemins.
Étape 2a : Cloudflare Workers (le chemin de production quasi gratuit)
Pourquoi le coût est proche de zéro
Le trafic d'un entonnoir est principalement constitué de requêtes pour des pages, des images et des scripts. Sur Workers, ce sont des requêtes d'actifs statiques, qui sont gratuites et illimitées, sans coût de stockage - seules les requêtes qui invoquent le Worker (pages rendues par le serveur, checkout, API) sont facturées. La surface dynamique d'un entonnoir est faible : le formulaire de commande, l'acceptation de l'upsell, la file d'attente de postback.
Limites vérifiées du plan gratuit Cloudflare (vérifiées en 2026-08 ; confirmez les chiffres actuels avant de vous y fier) :
| Ressource | Plan gratuit Workers |
|---|---|
| Requêtes d'actifs statiques | Gratuites et illimitées, sans frais de stockage |
| Invocations de Worker | 100 000 requêtes/jour |
| Hyperdrive (pooling Postgres) | Disponible sur le plan gratuit, 100 000 requêtes de base de données/jour |
| Workers KV (cache de page) | 100 000 lectures/jour, 1 000 écritures/jour, 1 Go de stockage |
| Déclencheurs Cron | Pris en charge (le dépôt fournit un gestionnaire scheduled) |
Ce qui n'est pas gratuit : Postgres. Hyperdrive regroupe les connexions vers une base de données que vous fournissez, vous avez donc toujours besoin d'un fournisseur Postgres. Les fournisseurs gérés ont leurs propres niveaux gratuits avec leurs propres limites, et c'est le seul élément à planifier.
Le premier plafond que vous atteindrez réellement est celui des écritures KV, pas celui des requêtes. 1 000 écritures/jour est généreux pour servir des pages, mais limité pour les publier, car la publication invalide et rafraîchit les entrées mises en cache. Une journée d'édition intensive peut l'épuiser alors que le trafic est loin de toute limite. Si la publication commence à échouer avant le trafic, c'est cette limite, pas un bug.
Déploiement
Le dépôt fournit toute la chaîne d'outils Workers : point d'entrée du Worker avec le gestionnaire cron scheduled (src/cf-worker.ts), génération de wrangler.toml, câblage du cache KV et Hyperdrive pour Postgres.
npx wrangler login
npx wrangler kv namespace create CACHE_KV
# $DATABASE_URL est la chaîne de connexion Postgres de l'opérateur, exportée dans
# son shell - n'écrivez pas les informations d'identification dans cette commande ou dans wrangler.toml.
npx wrangler hyperdrive create autonnel-db --connection-string="$DATABASE_URL"
Chaque commande imprime un identifiant. Mettez-les dans .env à côté du projet :
CF_WORKER_NAME=my-funnels
CF_KV_NAMESPACE_ID=<id de kv namespace create>
CF_HYPERDRIVE_CONFIG_ID=<id de hyperdrive create>
Définissez ensuite les secrets et déployez :
npx wrangler secret put DATABASE_URL
npx wrangler secret put AUTH_SESSION_SECRET # openssl rand -hex 32
npx wrangler secret put CREDENTIALS_ENCRYPTION_KEY # openssl rand -base64 32
npm run deploy:cf
deploy:cf construit et génère d'abord wrangler.toml à partir du modèle, il n'y a donc pas d'étape de génération distincte. Les expressions cron sont lues à partir du registre cron de l'application plutôt que d'être écrites manuellement dans la configuration - ne modifiez pas le wrangler.toml généré à la main, il est écrasé à chaque construction.
Si une variable CF_* est manquante, la génération échoue et nomme la variable. C'est le comportement attendu ; il n'y a pas de valeurs par défaut silencieuses pour celles-ci.
Appliquez le schéma de base de données une fois sur la même base Postgres avant la première visite, puis ouvrez l'URL du Worker et complétez l'assistant /setup pour créer le compte administrateur.
Également disponibles : npm run dev:cf (serveur de développement sur le runtime Workers) et npm run preview:cf (aperçu local via wrangler dev). Préférez-les à astro dev simple lorsque la cible est Workers, car le runtime diffère.
Exploitation ultérieure
Les commandes CLI ci-dessous nécessitent un accès à la base de données, pas un conteneur. À partir d'un checkout avec DATABASE_URL pointant vers la même base Postgres :
npx autonnel admin:create [email protected] 'a-strong-password'
npx autonnel password:reset [email protected]
Étape 2b : Docker (évaluation locale, ou votre propre serveur)
Obtenez le dépôt à partir de https://github.com/autonnel/autonnel (Apache-2.0), extrayez un tag de version, et lisez son docker-compose.yml - il déclare les images et les ports qui seront exécutés. À partir de ce checkout :
docker compose up
Ouvrez http://localhost:4321 et complétez /setup. Le fichier compose démarre Postgres, applique le schéma et exécute l'application. Rien d'autre n'est nécessaire pour démarrer : le stockage, les paiements, le stockage multimédia, l'email et l'IA sont configurés plus tard dans l'interface d'administration, et uniquement pour les fonctionnalités réellement utilisées.
Avant de l'exposer sur un hôte public, placez de vrais secrets dans un fichier .env à côté de docker-compose.yml - les valeurs par défaut fournies sont des valeurs de développement non sécurisées, et elles n'existent que pour que la première exécution locale ne nécessite aucune configuration :
AUTH_SESSION_SECRET=$(openssl rand -hex 32)
CREDENTIALS_ENCRYPTION_KEY=$(openssl rand -base64 32)
ADMIN_DOMAIN=admin.example.com
Générez chaque valeur une fois et conservez-la stable. La rotation de AUTH_SESSION_SECRET invalide les sessions ; la rotation de CREDENTIALS_ENCRYPTION_KEY rend illisibles les informations d'identification du fournisseur stockées, ce qui signifie qu'il faut ressaisir chaque justificatif de paiement et de plateforme.
Des images multi-architectures sont publiées sur GHCR pour un simple docker run avec une base de données existante :
# DATABASE_URL, AUTH_SESSION_SECRET et CREDENTIALS_ENCRYPTION_KEY proviennent de
# l'environnement de l'opérateur - n'écrivez jamais leurs valeurs dans une commande ou un fichier.
docker run -p 4321:4321 \
-e DATABASE_URL \
-e AUTH_SESSION_SECRET \
-e CREDENTIALS_ENCRYPTION_KEY \
-e ADMIN_DOMAIN="admin.example.com" \
ghcr.io/autonnel/autonnel:v1.5.0
Utilisez un tag exact plutôt que :latest, et réappliquez le schéma après avoir extrait un tag plus récent - le service de schéma unique du fichier compose se réexécute à chaque docker compose up. Point de terminaison de santé pour les orchestrateurs : /api/health (couvre la connectivité de la base de données et du cache).
CLI d'administration dans un conteneur :
docker compose exec app node dist/cli/index.js admin:create [email protected] 'a-strong-password'
Étape 2c : checkout source (Node)
Pour modifier Autonnel lui-même, ou exécuter la construction Node sur un hôte que vous possédez déjà. Nécessite Node 22+ et une base Postgres :
npm create autonnel@latest my-funnel
cd my-funnel
cp .env.example .env # définir DATABASE_URL et ADMIN_DOMAIN
pnpm install # pnpm 10+ ; le dépôt épingle les remplacements que npm ignorerait
npm run db:push
npm run dev # ou : npm run build && npm run start
Ceci clone le dépôt et supprime son historique git. Le schéma se trouve dans prisma/schema.prisma dans le checkout ; db:push le synchronise. CLI d'administration : npx autonnel admin:create [email protected] 'a-strong-password' depuis le répertoire du projet.
Étape 3 : configurer uniquement ce dont l'entonnoir a besoin
Dans l'interface d'administration sous Paramètres :
| Paramètre | Nécessaire pour | Options |
|---|---|---|
| E-commerce | Données de produit et de commande | Shopify, WooCommerce, Picocart |
| Paiements | Recevoir de l'argent | Stripe, PayPal |
| Stockage | Téléchargements d'images/vidéos | Tout bucket compatible S3 (R2, S3, MinIO) |
| Reçus, campagnes de relance | SMTP, Resend, AWS SES | |
| LLM | Génération de pages par IA | Tout point de terminaison compatible OpenAI |
| Plateformes publicitaires | Conversions côté serveur (les quatre) ; reporting des dépenses/clics au niveau de l'annonce (Facebook, Google Ads, TikTok uniquement) | Facebook, TikTok, Google Ads, Bing |
Ordre des opérations qui évite les reprises : catalogue d'abord (il contraint ce que le checkout peut vendre), puis paiements, puis stockage, puis email, puis plateformes publicitaires en dernier - le suivi est vérifié par rapport aux commandes réelles, il a donc besoin que le reste fonctionne d'abord. La connexion d'une plateforme publicitaire pour le reporting des dépenses est une étape distincte de son association à un entonnoir pour le postback (voir server-side-conversion-tracking) ; faites les deux si vous voulez les deux.
Sur Workers, R2 est le choix de stockage évident : il est compatible S3 et maintient la sortie des médias à l'intérieur de Cloudflare.
Étape 4 : construire les pages
Les rôles d'un entonnoir correspondent directement à la spécification de l'entonnoir :
| Rôle dans l'entonnoir | Objectif | Plusieurs par entonnoir ? |
|---|---|---|
LANDING | Page(s) d'entrée, une par angle de trafic | Oui |
CHECKOUT | Formulaire de commande | Non - un par entonnoir |
UPSELL | Offres post-achat, ordonnées en chaîne | Oui |
THANKYOU | Confirmation | Non |
ERROR | Échec de paiement / repli | Non |
Ce sont les rôles qu'une page prend à l'intérieur d'un entonnoir. Via l'API, le propre type d'une page est CHECKOUT | THANKYOU | ERROR | UPSELL | CUSTOM - les pages d'accueil sont créées en tant que CUSTOM et deviennent des pages d'accueil en étant liées à un entonnoir en tant que LANDING.
Deux éditeurs sont disponibles : un éditeur visuel basé sur des composants dont la sortie est du JSON différentiel, et du HTML brut pour les pages importées. Préférez l'éditeur de composants pour tout ce qui sera testé en A/B ou modifié plus tard par un agent - les diffs JSON se révisent proprement, les blobs HTML non.
Construisez la page de checkout avant la page d'accueil. Le checkout détermine ce qui peut réellement être vendu et à quel prix, et une page d'accueil écrite en premier promettra quelque chose que le checkout ne peut pas fournir.
Étape 5 : câbler l'entonnoir
- Créez l'entonnoir, puis attachez les pages avec leur rôle et leur ordre.
- Une même page peut être référencée par plusieurs entonnoirs. La seule règle d'unicité imposée par le domaine est qu'un
stepSlugest unique au sein d'un seul entonnoir (et qu'une page apparaît au plus une fois par entonnoir) - il n'y a pas de rejet inter-entonnoir à concevoir. Clonez une page d'accueil uniquement lorsque vous souhaitez que les deux entonnoirs divergent, car une modification d'une page partagée atterrit sur tous les entonnoirs qui la référencent. THANKYOUetERRORsont automatiquement liés à partir des pages existantes lors de la création si elles existent ; si le locataire n'en a pas, créez-les avant la mise en ligne. Un entonnoir sans page d'erreur échoue silencieusement en cas de paiement refusé.- L'URL qui va dans les campagnes publicitaires est le slug propre de la page d'accueil sur un hôte de boutique -
https://shop.example.com/{page.slug}- jamais une URL d'étape/n/./n/{funnelId}/{stepSlug}redirige vers l'avant vers l'étape suivante, elle appartient donc au lien CTA d'une page, pas à une annonce. Écrire le CTA de cette manière maintient le parcours de l'acheteur stable lorsqu'une étape est échangée contre une autre page. - La publication est explicite et versionnée par page et par entonnoir - publier une page ne publie pas la liaison de l'entonnoir.
Étape 6 : instrumenter avant d'envoyer du trafic
Vérifications pré-lancement non négociables :
- Un achat réel de bout en bout, sur un véritable fournisseur de paiement, comprenant : commande de base, un upsell accepté, un upsell refusé, la page de remerciement, l'email de reçu et l'apparition de la commande dans la boutique connectée.
- Un remboursement sur cette commande, pour confirmer que le chemin de remboursement fonctionne par transaction.
- Couverture des identifiants de clic - confirmez que
fbclid/ttclid/gclid/msclkidparviennent à l'enregistrement de commande. Voirserver-side-conversion-tracking. - Conversion côté serveur arrivant dans le débogueur d'événements de chaque plateforme publicitaire, avec l'identifiant de clic attaché et sans doublon avec l'événement navigateur.
- Page d'erreur accessible en forçant une carte refusée.
Sur Workers, ajoutez-en une de plus : confirmez que le gestionnaire cron scheduled se déclenche (les postbacks mis en file d'attente et les campagnes de relance en dépendent). Un déploiement qui a silencieusement perdu ses déclencheurs cron semble sain alors que le travail en arrière-plan s'arrête tranquillement.
Ce n'est qu'ensuite qu'il faut augmenter les dépenses. Un entonnoir qui n'a pas eu de transaction réelle a un taux d'échec inconnu, pas faible.
Étape 7 : l'exploiter à partir d'un agent via MCP
L'instance expose son API d'administration sous forme d'outils MCP à /api/mcp, afin qu'un agent puisse construire et modifier des entonnoirs sans l'interface utilisateur.
{
"mcpServers": {
"autonnel": {
"transport": "http",
"url": "https://<votre-hote-autonnel>/api/mcp",
"headers": { "Authorization": "Bearer <votre-clé-api>" }
}
}
}
L'appel à /api/mcp avec HTTP brut plutôt qu'un client MCP a deux exigences de transport que le SDK cache normalement. Le point de terminaison parle Streamable HTTP : la requête doit comporter Accept: application/json, text/event-stream - toute valeur inférieure est rejetée avec 406 avant que la couche d'outil ne soit atteinte - et un succès revient sous forme d'une trame SSE (event: message / data: {...}), donc l'enveloppe JSON-RPC doit être extraite de data: avant l'analyse.
Un piège supplémentaire devant l'application entière : une instance derrière Cloudflare avec les règles de bot gérées par défaut rejette l'agent utilisateur de la bibliothèque standard Python. Un client urllib envoie Python-urllib/3.x et reçoit 403 avec le corps en texte brut error code: 1010 sur tous les chemins, y compris /api/health, ce qui ressemble exactement à une erreur d'authentification ou d'autorisation et n'est pas du JSON, donc un client qui analyse le corps lève une exception avant de pouvoir voir le statut. Seule cette chaîne d'agent est bloquée - curl, python-requests, httpx, axios, node et un UA vide passent tous. Si vous scriptez cela en Python, définissez un User-Agent explicite ou utilisez requests/httpx ; si chaque appel, y compris non authentifié, renvoie 403, c'est pourquoi, et aucune clé API ne le corrigera.
.mcp.json à la racine du projet pour Claude Code ; claude_desktop_config.json pour Claude Desktop. Générez la clé dans l'administration → Paramètres → Clés API. Chaque appel est limité à l'opérateur correspondant.