[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"theme-db":3,"$fPYzRo4vs3Wmu5ZeLOpeIbpinPflWOSMzZ-2jv8d83GA":22,"$fKnz2vuX4bZz1LbUTiuFsvSZ3e07l5_5fqNYp4Tzdhi8":60,"megamenu":141,"header-db":197,"$fEk9GvpiykEuCDp0Ycp5wEVyQhc4JCV3ba9IbSeEhU5c":210,"footer-db":224},{"theme":4},{"colors":5,"typography":13,"ui":17,"defaultColorMode":21},{"primary":6,"secondary":7,"background":8,"foreground":9,"muted":10,"headerBg":11,"footerBg":12,"topBarBg":9,"topBarText":11},"#4F46E5","#0D9488","#F9FAFB","#111827","#6B7280","#ffffff","#020617",{"fontFamily":14,"fontUrl":15,"baseFontSize":16},"Inter, system-ui, sans-serif","https:\u002F\u002Ffonts.googleapis.com\u002Fcss2?family=Inter:wght@400;500;600;700&family=Playfair+Display:ital,wght@0,400;0,700;0,800;0,900;1,400;1,700&display=swap","16px",{"borderRadius":18,"contentWidth":19,"shadow":20},"lg","7xl",true,"light",{"title":23,"slug":24,"metaDescription":25,"category":26,"tags":27,"difficulty":33,"psVersions":34,"content":38,"faq":39,"tldr":55,"readingTime":56,"generatedAt":57,"publishDate":57,"relatedArticles":58,"sourceCategory":59},"Intégrer un flux de blog externe dans PrestaShop via une page CMS","integrer-blog-externe-page-cms-prestashop","Comment intégrer un blog externe (Tumblr, WordPress, Medium) dans PrestaShop via une page CMS : injection JavaScript conditionnelle, styles et bonnes pratiques.","developpement",[28,29,30,31,32],"cms","javascript","intégration","blog externe","template smarty","intermediaire",[35,36,37],"1.6","1.7","8.x","\u003Ch2>Pourquoi intégrer un blog externe dans PrestaShop ?\u003C\u002Fh2>\n\u003Cp>Certains marchands PrestaShop préfèrent maintenir leur blog sur une plateforme dédiée (Tumblr, WordPress, Medium) tout en affichant ce contenu directement sur leur boutique. L'objectif : centraliser l'expérience utilisateur sans forcer le visiteur à quitter le site marchand.\u003C\u002Fp>\n\u003Cp>Cette approche présente des avantages concrets : profiter de l'écosystème éditorial d'une plateforme de blogging tout en conservant le header, le footer et la navigation de la boutique PrestaShop. En revanche, elle nécessite une intégration propre pour éviter les conflits JavaScript et les incohérences visuelles.\u003C\u002Fp>\n\u003Ch2>Stratégie d'intégration : page CMS conditionnelle\u003C\u002Fh2>\n\u003Cp>La méthode la plus fiable consiste à créer une page CMS dédiée dans PrestaShop, puis à injecter le contenu du blog externe uniquement sur cette page via une condition Smarty dans le template.\u003C\u002Fp>\n\u003Ch3>Étape 1 : créer la page CMS dans le back-office\u003C\u002Fh3>\n\u003Cp>Rendez-vous dans \u003Cstrong>Catalogue > Pages\u003C\u002Fstrong> (PrestaShop 8.x) ou \u003Cstrong>Préférences > CMS\u003C\u002Fstrong> (1.6). Créez une nouvelle page avec un titre comme « Blog » et notez son \u003Cstrong>identifiant\u003C\u002Fstrong> (ID). Le contenu de cette page sera remplacé dynamiquement par le template, vous pouvez donc laisser le champ contenu vide ou y placer un message de fallback.\u003C\u002Fp>\n\u003Ch3>Étape 2 : modifier le template CMS avec une condition Smarty\u003C\u002Fh3>\n\u003Cp>Dans votre thème, ouvrez le fichier template responsable de l'affichage des pages CMS :\u003C\u002Fp>\n\u003Cul>\n\u003Cli>**PrestaShop 1.6** : `themes\u002Fvotre_theme\u002Fcms.tpl`\u003C\u002Fli>\n\u003Cli>**PrestaShop 1.7 \u002F 8.x** : `themes\u002Fvotre_theme\u002Ftemplates\u002Fcms\u002Fpage.tpl`\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>L'idée est de remplacer le contenu standard par l'injection du script externe, uniquement pour la page CMS concernée :\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-smarty\">\n{* PrestaShop 1.6 — cms.tpl *}\n&lt;div class=\"pb-left-column col-xs-12 col-sm-8 col-md-8\"&gt;\n  {if $cms-&gt;id != 42}\n    {* Affichage normal pour toutes les autres pages CMS *}\n    {$cms-&gt;content}\n  {else}\n    {* Page blog externe : injection du widget *}\n    &lt;div id=\"external-blog-container\"&gt;\n      {literal}\n        &lt;script type=\"text\u002Fjavascript\" src=\"https:\u002F\u002Fvotre-blog.example.com\u002Fjs\"&gt;&lt;\u002Fscript&gt;\n      {\u002Fliteral}\n    &lt;\u002Fdiv&gt;\n  {\u002Fif}\n&lt;\u002Fdiv&gt;\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Remplacez \u003Ccode>42\u003C\u002Fcode> par l'ID réel de votre page CMS.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Pour PrestaShop 1.7 et 8.x\u003C\u002Fstrong>, la syntaxe du template diffère légèrement :\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-smarty\">\n{* PrestaShop 8.x — templates\u002Fcms\u002Fpage.tpl *}\n{extends file='page.tpl'}\n\n{block name='page_content'}\n  {if $cms.id != 42}\n    {$cms.content nofilter}\n  {else}\n    &lt;div id=\"external-blog-container\"&gt;\n      {literal}\n        &lt;script type=\"text\u002Fjavascript\" src=\"https:\u002F\u002Fvotre-blog.example.com\u002Fjs\"&gt;&lt;\u002Fscript&gt;\n      {\u002Fliteral}\n    &lt;\u002Fdiv&gt;\n  {\u002Fif}\n{\u002Fblock}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cblockquote>\u003Cp>\u003Cstrong>Point important :\u003C\u002Fstrong> La balise \u003Ccode>{literal}\u003C\u002Fcode> est indispensable pour empêcher Smarty d'interpréter le code JavaScript comme du code template. Sans elle, toute accolade \u003Ccode>{}\u003C\u002Fcode> dans le script provoquera une erreur de compilation Smarty.\u003C\u002Fp>\u003C\u002Fblockquote>\n\u003Ch3>Étape 3 : résoudre le problème du JavaScript déplacé en bas de page\u003C\u002Fh3>\n\u003Cp>PrestaShop dispose d'une option de performance qui déplace automatiquement les scripts JavaScript en fin de page. Cette optimisation, activée par défaut dans de nombreuses configurations, peut empêcher le widget du blog externe de fonctionner correctement si celui-ci dépend de l'ordre d'exécution des scripts.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Vérification\u003C\u002Fstrong> : rendez-vous dans \u003Cstrong>Paramètres avancés > Performances\u003C\u002Fstrong> et examinez l'option \u003Cstrong>« Déplacer le JavaScript en fin de page »\u003C\u002Fstrong>.\u003C\u002Fp>\n\u003Cp>Si votre widget ne s'affiche pas alors que le code est correctement injecté, cette option est probablement la cause. Deux solutions :\u003C\u002Fp>\n\u003Col>\n\u003Cli>**Désactiver l'option globalement** (déconseillé, impact sur les performances de toutes les pages)\u003C\u002Fli>\n\u003Cli>**Charger le script de manière asynchrone** avec un contrôle explicite de l'initialisation :\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cpre>\u003Ccode class=\"language-javascript\">\n\u002F\u002F Chargement différé contrôlé\ndocument.addEventListener('DOMContentLoaded', function() {\n  var container = document.getElementById('external-blog-container');\n  if (container) {\n    var script = document.createElement('script');\n    script.src = 'https:\u002F\u002Fvotre-blog.example.com\u002Fjs';\n    script.async = true;\n    container.appendChild(script);\n  }\n});\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Cette seconde méthode est préférable : elle ne charge le script que lorsque le DOM est prêt et uniquement si le conteneur existe sur la page.\u003C\u002Fp>\n\u003Ch2>Harmoniser les styles CSS entre le blog et PrestaShop\u003C\u002Fh2>\n\u003Cp>Une fois le contenu du blog injecté, vous constaterez probablement des incohérences visuelles. Les styles du blog externe entrent en conflit avec ceux du thème PrestaShop.\u003C\u002Fp>\n\u003Cp>La solution consiste à surcharger les styles du blog dans la feuille de styles de votre thème. L'approche la plus robuste utilise un sélecteur de contexte combiné à des déclarations \u003Ccode>!important\u003C\u002Fcode> pour garantir la priorité :\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-css\">\n\u002F* themes\u002Fvotre_theme\u002Fassets\u002Fcss\u002Fcustom.css *\u002F\n\n\u002F* Conteneur principal du blog externe *\u002F\n#external-blog-container {\n  max-width: 800px;\n  margin: 0 auto;\n  font-family: inherit; \u002F* Hérite de la police du thème PrestaShop *\u002F\n}\n\n\u002F* Surcharge des styles spécifiques du blog *\u002F\n#external-blog-container .post-title {\n  font-size: 1.5rem !important;\n  color: var(--primary-color, #333) !important;\n  margin-bottom: 1rem !important;\n}\n\n#external-blog-container .post-body {\n  line-height: 1.7 !important;\n  color: var(--text-color, #555) !important;\n}\n\n#external-blog-container img {\n  max-width: 100% !important;\n  height: auto !important;\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cblockquote>\u003Cp>\u003Cstrong>Bonne pratique :\u003C\u002Fstrong> Préférez cibler vos surcharges avec le sélecteur du conteneur (\u003Ccode>#external-blog-container .classe\u003C\u002Fcode>) plutôt que de cibler les classes du blog globalement. Cela évite les effets de bord sur le reste de votre boutique.\u003C\u002Fp>\u003C\u002Fblockquote>\n\u003Cp>Pour identifier les classes et identifiants CSS utilisés par le blog externe, ouvrez les outils de développement de votre navigateur (F12), inspectez le contenu injecté et relevez les sélecteurs à surcharger.\u003C\u002Fp>\n\u003Ch2>Approche moderne : API et rendu côté serveur\u003C\u002Fh2>\n\u003Cp>L'injection par script tiers présente des limites : dépendance à un service externe, contenu non indexable par Google, temps de chargement supplémentaire. En 2024-2025, une approche plus robuste consiste à consommer l'API du blog et à générer le HTML côté serveur.\u003C\u002Fp>\n\u003Ch3>Exemple avec un module PrestaShop et l'API Tumblr v2\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-php\">\n&lt;?php\n\u002F\u002F modules\u002Fmonblogexterne\u002Fmonblogexterne.php\n\nclass MonBlogExterne extends Module\n{\n    public function __construct()\n    {\n        $this-&gt;name = 'monblogexterne';\n        $this-&gt;version = '1.0.0';\n        $this-&gt;author = 'Alexandre Carette';\n        parent::__construct();\n        $this-&gt;displayName = $this-&gt;l('Blog Externe');\n    }\n\n    public function hookDisplayCMSPage($params)\n    {\n        $cmsId = (int) Tools::getValue('id_cms');\n        if ($cmsId !== 42) {\n            return '';\n        }\n\n        $posts = $this-&gt;fetchBlogPosts();\n        $this-&gt;context-&gt;smarty-&gt;assign(['posts' =&gt; $posts]);\n        return $this-&gt;display(__FILE__, 'views\u002Ftemplates\u002Fhook\u002Fblog.tpl');\n    }\n\n    private function fetchBlogPosts(): array\n    {\n        $cacheKey = 'external_blog_posts';\n        $cached = Cache::retrieve($cacheKey);\n        if ($cached) {\n            return json_decode($cached, true);\n        }\n\n        $apiUrl = 'https:\u002F\u002Fapi.tumblr.com\u002Fv2\u002Fblog\u002Fvotre-blog\u002Fposts?api_key=VOTRE_CLE';\n        $response = Tools::file_get_contents($apiUrl);\n        $data = json_decode($response, true);\n\n        $posts = [];\n        if (!empty($data['response']['posts'])) {\n            foreach ($data['response']['posts'] as $post) {\n                $posts[] = [\n                    'title' =&gt; $post['title'] ?? '',\n                    'body' =&gt; $post['body'] ?? '',\n                    'date' =&gt; date('d\u002Fm\u002FY', $post['timestamp']),\n                    'url' =&gt; $post['post_url'],\n                ];\n            }\n        }\n\n        Cache::store($cacheKey, json_encode($posts), 3600);\n        return $posts;\n    }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Cette approche offre un contenu indexable par les moteurs de recherche, un chargement plus rapide grâce au cache, et une indépendance vis-à-vis du JavaScript client.\u003C\u002Fp>\n\u003Ch2>Checklist d'intégration\u003C\u002Fh2>\n\u003Cul>\n\u003Cli>[ ] Créer la page CMS et noter son ID\u003C\u002Fli>\n\u003Cli>[ ] Modifier le template CMS avec la condition Smarty\u003C\u002Fli>\n\u003Cli>[ ] Vérifier le paramètre « JavaScript en fin de page »\u003C\u002Fli>\n\u003Cli>[ ] Tester l'affichage sur mobile et desktop\u003C\u002Fli>\n\u003Cli>[ ] Surcharger les styles CSS du blog dans le thème\u003C\u002Fli>\n\u003Cli>[ ] Vérifier que les autres pages CMS ne sont pas impactées\u003C\u002Fli>\n\u003Cli>[ ] Valider l'indexation Google (contenu visible sans JS si possible)\u003C\u002Fli>\n\u003Cli>[ ] Mettre en place un cache si vous utilisez l'approche API\u003C\u002Fli>\n\u003C\u002Ful>",[40,43,46,49,52],{"q":41,"a":42},"Comment afficher un blog externe uniquement sur une page CMS spécifique dans PrestaShop ?","Utilisez une condition Smarty dans le template CMS de votre thème pour vérifier l'identifiant de la page. Avec {if $cms->id != VOTRE_ID}, vous affichez le contenu standard sur toutes les pages sauf celle du blog, où vous injectez le widget ou le script externe à la place.",{"q":44,"a":45},"Pourquoi mon widget JavaScript externe ne s'affiche pas sur ma page CMS PrestaShop ?","La cause la plus fréquente est l'option « Déplacer le JavaScript en fin de page » activée dans Paramètres avancés > Performances. Cette option réorganise l'ordre d'exécution des scripts et peut empêcher les widgets tiers de fonctionner. Désactivez-la temporairement pour confirmer le diagnostic, puis privilégiez un chargement asynchrone via document.addEventListener('DOMContentLoaded') pour une solution pérenne.",{"q":47,"a":48},"Comment harmoniser le design d'un blog externe intégré dans PrestaShop ?","Inspectez le contenu injecté avec les outils de développement du navigateur pour identifier les classes et identifiants CSS du blog. Ajoutez ensuite des surcharges ciblées dans la feuille de styles de votre thème en utilisant un sélecteur de contexte (par exemple #external-blog-container .classe) combiné à !important pour garantir la priorité sur les styles du blog.",{"q":50,"a":51},"Faut-il utiliser {literal} dans les templates Smarty pour injecter du JavaScript ?","Oui, c'est indispensable. Smarty interprète les accolades {} comme des balises template. Sans {literal}, tout code JavaScript contenant des accolades (fonctions, objets, conditions) provoquera une erreur de compilation Smarty. Encadrez systématiquement vos blocs JavaScript avec {literal}...{\u002Fliteral} dans les fichiers .tpl.",{"q":53,"a":54},"Quelle est la meilleure alternative à l'injection de script pour intégrer un blog dans PrestaShop 8 ?","L'approche recommandée en PrestaShop 8.x est de créer un module qui consomme l'API du blog externe (Tumblr API v2, WordPress REST API, etc.) et génère le HTML côté serveur via un hook. Cette méthode offre un contenu indexable par Google, de meilleures performances grâce au cache serveur, et une meilleure fiabilité car elle ne dépend pas du JavaScript côté client.","Pour intégrer un blog externe dans PrestaShop, créez une page CMS dédiée et utilisez une condition Smarty dans le template pour injecter le contenu uniquement sur cette page. Attention au paramètre de déplacement JavaScript en fin de page qui peut bloquer le widget. En PrestaShop 8.x, préférez un module consommant l'API du blog pour un rendu côté serveur indexable et performant.",6,"2026-03-21T14:35:21.000Z",[],"PrestaShop pour les développeurs",{"columns":61},[62,78,108,129],{"title":63,"links":64},"Plateforme",[65,69,72,75],{"label":66,"href":67,"external":68},"Offre Starter (2 500 €)","\u002Foffre-starter",false,{"label":70,"href":71,"external":68},"Devenir Ambassadeur","\u002Fambassadeur",{"label":73,"href":74,"external":68},"Modules PrestaShop","\u002Fmodules",{"label":76,"href":77,"external":20},"CodeMyShop.com","https:\u002F\u002Fcodemyshop.com",{"title":79,"links":80},"Le Synedre",[81,84,87,90,93,96,99,102,105],{"label":82,"href":83,"external":68},"L'histoire","\u002Fsynedre",{"label":85,"href":86,"external":68},"Constitution","\u002Fsynedre\u002Fconstitution",{"label":88,"href":89,"external":68},"L'équipe","\u002Fequipe",{"label":91,"href":92,"external":68},"Le réacteur en direct","\u002Freacteur",{"label":94,"href":95,"external":68},"Le Drill (entraînement)","\u002Fdrill",{"label":97,"href":98,"external":68},"Protocole de réunion","\u002Fsynedre\u002Freunion",{"label":100,"href":101,"external":68},"Les agents IA","\u002Fagents-ia",{"label":103,"href":104,"external":68},"La Conduite","\u002Fsynedre\u002Fconduite",{"label":106,"href":107,"external":68},"Charte plateforme","\u002Fsynedre\u002Fcharte",{"title":109,"links":110},"Ressources",[111,114,117,120,123,126],{"label":112,"href":113,"external":68},"Blog","\u002Fblog",{"label":115,"href":116,"external":68},"Academy","\u002Facademy",{"label":118,"href":119,"external":68},"Dictionnaire","\u002Fdictionnaire",{"label":121,"href":122,"external":68},"Expertise PrestaShop","\u002Fexpertise",{"label":124,"href":125,"external":68},"Flywheel","\u002Fflywheel",{"label":127,"href":128,"external":68},"Manifeste","\u002Fmanifeste",{"title":130,"links":131},"À propos",[132,135,138],{"label":133,"href":134,"external":68},"Alexandre Carette","\u002Fa-propos",{"label":136,"href":137,"external":68},"Dossier de presse","\u002Fpresse",{"label":139,"href":140,"external":68},"Contact","\u002Fcontact",{"items":142},[143,152,158,164,172,180,186,191],{"id":144,"type":145,"label":146,"href":122,"icon":148,"description":148,"badge":148,"groupTitle":148,"style":148,"gridColumns":148,"cssClass":148,"psCategoryId":148,"showPsChildren":68,"position":149,"children":150,"psChildren":151},41,"link",{"fr":147},"Expertise",null,0,[],[],{"id":153,"type":145,"label":154,"href":113,"icon":148,"description":148,"badge":148,"groupTitle":148,"style":148,"gridColumns":148,"cssClass":148,"psCategoryId":148,"showPsChildren":68,"position":155,"children":156,"psChildren":157},42,{"fr":112},1,[],[],{"id":159,"type":145,"label":160,"href":74,"icon":148,"description":148,"badge":148,"groupTitle":148,"style":148,"gridColumns":148,"cssClass":148,"psCategoryId":148,"showPsChildren":68,"position":161,"children":162,"psChildren":163},43,{"fr":73},2,[],[],{"id":165,"type":145,"label":166,"href":168,"icon":148,"description":148,"badge":148,"groupTitle":148,"style":148,"gridColumns":148,"cssClass":148,"psCategoryId":148,"showPsChildren":68,"position":169,"children":170,"psChildren":171},44,{"fr":167},"Outils IA","\u002Foutils-ia",3,[],[],{"id":173,"type":145,"label":174,"href":67,"icon":148,"description":148,"badge":148,"groupTitle":148,"style":176,"gridColumns":148,"cssClass":148,"psCategoryId":148,"showPsChildren":68,"position":177,"children":178,"psChildren":179},45,{"fr":175},"Offre Starter ✨",{"highlight":20},4,[],[],{"id":181,"type":145,"label":182,"href":116,"icon":148,"description":148,"badge":148,"groupTitle":148,"style":148,"gridColumns":148,"cssClass":148,"psCategoryId":148,"showPsChildren":68,"position":183,"children":184,"psChildren":185},46,{"fr":115},5,[],[],{"id":187,"type":145,"label":188,"href":134,"icon":148,"description":148,"badge":148,"groupTitle":148,"style":148,"gridColumns":148,"cssClass":148,"psCategoryId":148,"showPsChildren":68,"position":56,"children":189,"psChildren":190},47,{"fr":130},[],[],{"id":192,"type":145,"label":193,"href":140,"icon":148,"description":148,"badge":148,"groupTitle":148,"style":148,"gridColumns":148,"cssClass":148,"psCategoryId":148,"showPsChildren":68,"position":194,"children":195,"psChildren":196},48,{"fr":139},7,[],[],{"header":198},{"logo":199,"topBar":204,"contactEmail":207,"features":208,"navBar":148},{"src":200,"alt":201,"text":133,"href":202,"class":203},"\u002Flogo-ac.svg","Alexandre Carette — Architecte E-commerce Souverain","\u002F","h-10 w-10",{"message":148,"showLanguages":68,"align":205,"languages":206},"left",[],"contact@alexandrecarette.fr",{"showSearch":68,"showWishlist":68,"showLogin":20,"showContact":68,"showCart":68,"stickyHeader":20,"headerLayout":209},"inline",{"academy":211,"blog":212,"expertise":223},[],[213,217,220],{"title":214,"url":215,"score":155,"type":216},"PrestaShop headless avec Nuxt 3 : pourquoi séparer back et front","\u002Fblog\u002Fprestashop\u002Farchitecture\u002Fprestashop-headless-nuxt-separation-front-back","blog",{"title":218,"url":219,"score":155,"type":216},"PrestaShop headless : Nuxt 3, pas Next.js — le choix souverain","\u002Fblog\u002Fprestashop\u002Farchitecture\u002Fprestashop-headless-nuxt-nextjs-souverainete",{"title":221,"url":222,"score":155,"type":216},"Sylius rachète PrestaShop : ce que ça change pour vous","\u002Fblog\u002Fprestashop\u002Farchitecture\u002Fsylius-rachat-prestashop-headless-souverainete",[],{"footer":225},{"theme":226,"description":148,"hours":148,"logo":227,"contact":228,"social":229,"bottomBar":239},"dark",{"src":200,"href":202,"alt":133},{"email":148,"phone":148,"address":148,"cta":148},[230,233,236],{"platform":231,"href":232,"label":231},"linkedin","https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Falexandre-carette\u002F",{"platform":234,"href":235,"label":234},"malt","https:\u002F\u002Fwww.malt.fr\u002Fprofile\u002Falexandrecarette",{"platform":237,"href":238,"label":237},"github","https:\u002F\u002Fgithub.com\u002Fprest4cafe",{"copyright":148}]