Workflow n8n

Automatisation n8n : notifications de prix sur Discord

Ce workflow n8n a pour objectif d'automatiser l'envoi de notifications de prix sur Discord, permettant ainsi aux utilisateurs de rester informés des fluctuations de prix sur des produits spécifiques. Dans un contexte où les entreprises cherchent à optimiser leur stratégie de pricing, ce workflow s'avère particulièrement utile pour les e-commerçants et les équipes de vente qui souhaitent réagir rapidement aux changements de prix. Le premier déclencheur de ce workflow est un Cron qui permet d'exécuter le processus à intervalles réguliers. Ensuite, le workflow utilise un nœud HTTP pour récupérer les données de prix actuelles d'un produit via une API. Une fois les données extraites, un traitement est effectué pour vérifier si le prix a changé par rapport à un prix enregistré. Si le prix a baissé, un email est envoyé via le nœud d'envoi d'email pour notifier les utilisateurs d'une meilleure offre. En revanche, si le prix a augmenté, un autre email est envoyé pour informer les utilisateurs de cette hausse. Ce processus permet aux entreprises de garder leurs clients informés, d'augmenter l'engagement client et d'améliorer les taux de conversion. En intégrant ce workflow d'automatisation n8n, les entreprises peuvent ainsi réduire le temps passé à surveiller les prix tout en augmentant leur réactivité face aux fluctuations du marché.

Tags clés :automatisationDiscordnotificationse-commercen8n
Catégorie: Scheduled · Tags: automatisation, Discord, notifications, e-commerce, n8n0

Workflow n8n Discord, notifications, e-commerce : vue d'ensemble

Schéma des nœuds et connexions de ce workflow n8n, généré à partir du JSON n8n.

Workflow n8n Discord, notifications, e-commerce : détail des nœuds

  • HTML Extract

    Ce noeud extrait des données HTML selon les valeurs d'extraction spécifiées.

  • Cron

    Ce noeud déclenche le workflow à des intervalles de temps définis.

  • getActualPrice

    Ce noeud calcule le prix actuel à l'aide d'un code de fonction personnalisé.

  • fetchWeb

    Ce noeud effectue une requête HTTP pour récupérer des données à partir d'une URL spécifiée.

  • FunctionItem

    Ce noeud exécute un code de fonction pour traiter des éléments dans le workflow.

  • Write Binary File1

    Ce noeud écrit des données binaires dans un fichier avec un nom spécifié.

  • Move Binary Data1

    Ce noeud déplace des données binaires vers une nouvelle clé de destination selon le mode choisi.

  • IF1

    Ce noeud évalue des conditions pour déterminer le chemin d'exécution du workflow.

  • checkifexists

    Ce noeud exécute une commande pour vérifier l'existence d'un élément.

  • IF3

    Ce noeud évalue des conditions pour déterminer le chemin d'exécution du workflow.

  • SaveToFile

    Ce noeud écrit des données binaires dans un fichier avec un nom spécifié.

  • JsonToBinary

    Ce noeud déplace des données binaires vers une nouvelle clé de destination selon le mode choisi.

  • changeME

    Ce noeud exécute un code de fonction pour modifier des éléments dans le workflow.

  • initItem

    Ce noeud initialise un élément en exécutant un code de fonction personnalisé.

  • savedItems

    Ce noeud lit des données binaires à partir d'un fichier spécifié.

  • itemsToJSON

    Ce noeud déplace des données binaires vers une nouvelle clé source selon les options définies.

  • IF

    Ce noeud évalue des conditions pour déterminer le chemin d'exécution du workflow.

  • initItem1

    Ce noeud initialise un élément en exécutant un code de fonction personnalisé.

  • IF2

    Ce noeud évalue des conditions pour déterminer le chemin d'exécution du workflow.

  • updateSavedItems

    Ce noeud exécute un code de fonction pour mettre à jour des éléments sauvegardés.

  • updateSavedItems1

    Ce noeud exécute un code de fonction pour mettre à jour des éléments sauvegardés.

  • cleanData

    Ce noeud exécute une commande pour nettoyer des données.

  • IF4

    Ce noeud évalue des conditions pour déterminer le chemin d'exécution du workflow.

  • NotifyBetterPrice

    Ce noeud envoie un email pour notifier un meilleur prix avec les détails spécifiés.

  • NotifyIncorrectPrice

    Ce noeud envoie un email pour notifier un prix incorrect avec les détails spécifiés.

Inscris-toi pour voir l'intégralité du workflow

Inscription gratuite

S'inscrire gratuitementBesoin d'aide ?
{
  "nodes": [
    {
      "name": "HTML Extract",
      "type": "n8n-nodes-base.htmlExtract",
      "position": [
        -220,
        -390
      ],
      "parameters": {
        "options": {},
        "extractionValues": {
          "values": [
            {
              "key": "price",
              "cssSelector": "={{$node[\"initItem\"].json[\"selector\"]}}"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "name": "Cron",
      "type": "n8n-nodes-base.cron",
      "position": [
        -1290,
        -390
      ],
      "parameters": {
        "triggerTimes": {
          "item": [
            {
              "mode": "everyX",
              "unit": "minutes",
              "value": 15
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "name": "getActualPrice",
      "type": "n8n-nodes-base.functionItem",
      "position": [
        -20,
        -390
      ],
      "parameters": {
        "functionCode": "const globalData = getWorkflowStaticData('global');\n\nvar price = String(item.price).replace(\",\", \".\");\nprice = parseFloat(price);\n//price = price.replace(/\\D/g, '');\n//item.price = String(item.price).replace(\",\", \".\");\n//item.price = parseFloat(item.price);\n\nitem.priceExists = (price > 0 ? true : false)\nitem.price = price;\n\n// Update its data\nglobalData.actualPrice = item;\n\nreturn item;"
      },
      "typeVersion": 1
    },
    {
      "name": "fetchWeb",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -410,
        -390
      ],
      "parameters": {
        "url": "={{$node[\"initItem\"].json[\"link\"]}}",
        "options": {},
        "responseFormat": "string"
      },
      "typeVersion": 1
    },
    {
      "name": "FunctionItem",
      "type": "n8n-nodes-base.functionItem",
      "position": [
        1020,
        -390
      ],
      "parameters": {
        "functionCode": "const globalData = getWorkflowStaticData('global');\n\nglobalData.iteration = 0;\n//var thiselem = $node[\"initItem\"].json;\n\n//const s1 = {'slug': thiselem.slug, \"link\": thiselem.link, \"selector\": thiselem.selector, \"price\":$node[\"getActualPrice\"].json.price, \"currency\": thiselem.currency};\n//const s2 = {'slug': thiselem.slug+'2', \"link\": thiselem.link, \"selector\": thiselem.selector, \"price\":$node[\"getActualPrice\"].json.price, \"currency\": thiselem.currency};\n//const s3 = {'slug': thiselem.slug+'3', \"link\": thiselem.link, \"selector\": thiselem.selector, \"price\":$node[\"getActualPrice\"].json.price, \"currency\": thiselem.currency};\n\nreturn $node[\"changeME\"].json.myWatchers;\n"
      },
      "typeVersion": 1
    },
    {
      "name": "Write Binary File1",
      "type": "n8n-nodes-base.writeBinaryFile",
      "position": [
        1850,
        -390
      ],
      "parameters": {
        "fileName": "/data/kopacky.json",
        "dataPropertyName": "=price"
      },
      "typeVersion": 1
    },
    {
      "name": "Move Binary Data1",
      "type": "n8n-nodes-base.moveBinaryData",
      "position": [
        1420,
        -390
      ],
      "parameters": {
        "mode": "jsonToBinary",
        "options": {},
        "destinationKey": "price"
      },
      "typeVersion": 1
    },
    {
      "name": "IF1",
      "type": "n8n-nodes-base.if",
      "position": [
        550,
        -370
      ],
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{$node[\"checkifexists\"].json[\"stdout\"]}}",
              "value2": "Exists",
              "operation": "notEqual"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "name": "checkifexists",
      "type": "n8n-nodes-base.executeCommand",
      "position": [
        410,
        -370
      ],
      "parameters": {
        "command": "if [ -r /data/kopacky.json ]; then echo Exists; fi"
      },
      "typeVersion": 1
    },
    {
      "name": "IF3",
      "type": "n8n-nodes-base.if",
      "position": [
        680,
        110
      ],
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{$node[\"checkifexists\"].json[\"stdout\"]}}",
              "value2": "Exists"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "name": "SaveToFile",
      "type": "n8n-nodes-base.writeBinaryFile",
      "position": [
        1650,
        110
      ],
      "parameters": {
        "fileName": "/data/kopacky.json",
        "dataPropertyName": "=price"
      },
      "typeVersion": 1
    },
    {
      "name": "JsonToBinary",
      "type": "n8n-nodes-base.moveBinaryData",
      "position": [
        1500,
        110
      ],
      "parameters": {
        "mode": "jsonToBinary",
        "options": {},
        "destinationKey": "price"
      },
      "typeVersion": 1
    },
    {
      "name": "changeME",
      "type": "n8n-nodes-base.functionItem",
      "color": "#3BDD33",
      "position": [
        -830,
        -390
      ],
      "parameters": {
        "functionCode": "const globalData = getWorkflowStaticData('global');\n\n//{'slug': 'kopacky', 'link': 'https://www.adsport.sk/kopacky-lisovky-adidas-x-19-3-ll-fg-ef0598/#1131861', 'currency': 'EUR'}[]\nvar myWatchers = [\n{'slug': 'kopacky', 'link': 'https://www.adsport.sk/kopacky-lisovky-adidas-x-19-3-ll-fg-ef0598/#1131861', 'selector':'.prices > strong:nth-child(1) > span:nth-child(1)', 'currency': 'EUR'},\n{'slug': 'kopacky2', 'link': 'https://www.adsport.sk/turfy-adidas-ace-tango-17-3-tf-by2203/', 'selector':'.col-xs-4 > strong:nth-child(1) > span:nth-child(1)', 'currency': 'EUR'},\n{'slug': 'mobilcek', 'link': 'https://mobil.bazos.sk/inzerat/112253662/predam-odolny-doogee-s60-52-4g-lte-nfc.php', 'selector':'.listadvlevo > table:nth-child(1) > tbody:nth-child(1) > tr:nth-child(5) > td:nth-child(2) > b:nth-child(2)', 'currency': 'EUR'},\n{'slug': 'ADIZERO RC 2', 'link': 'https://www.adsport.sk/panske-bezecke-topanky-adidas-adizero-rc-2-eg1187/', 'selector':'.col-xs-4 > strong:nth-child(1) > span:nth-child(1)', 'currency': 'EUR'}\n];\n\nitem.myWatchers = myWatchers;\nitem.watchersCount = myWatchers.length;\nglobalData.myWatchers = myWatchers;\n\nreturn item;"
      },
      "typeVersion": 1
    },
    {
      "name": "initItem",
      "type": "n8n-nodes-base.functionItem",
      "position": [
        -620,
        -390
      ],
      "parameters": {
        "functionCode": "const globalData = getWorkflowStaticData('global');\n\nvar counter = globalData.iteration;\n\nitem.myWatchers[counter].watchersCount = item.watchersCount;\nitem.myWatchers[counter].canContinue = (globalData.iteration < item.watchersCount-1 ? true : false);\n//item.myWatchers[counter].canContinue = false;\n\nglobalData.iteration = counter + 1;\n\nreturn item.myWatchers[counter];"
      },
      "typeVersion": 1
    },
    {
      "name": "savedItems",
      "type": "n8n-nodes-base.readBinaryFile",
      "position": [
        850,
        -20
      ],
      "parameters": {
        "filePath": "/data/kopacky.json",
        "dataPropertyName": "savedItems"
      },
      "typeVersion": 1,
      "continueOnFail": true,
      "alwaysOutputData": true
    },
    {
      "name": "itemsToJSON",
      "type": "n8n-nodes-base.moveBinaryData",
      "position": [
        1020,
        -20
      ],
      "parameters": {
        "options": {},
        "sourceKey": "savedItems"
      },
      "typeVersion": 1
    },
    {
      "name": "IF",
      "type": "n8n-nodes-base.if",
      "position": [
        2190,
        -90
      ],
      "parameters": {
        "conditions": {
          "string": [],
          "boolean": [
            {
              "value1": "={{$node[\"initItem\"].json[\"canContinue\"]}}",
              "value2": true
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "name": "initItem1",
      "type": "n8n-nodes-base.functionItem",
      "position": [
        -1060,
        -390
      ],
      "parameters": {
        "functionCode": "const globalData = getWorkflowStaticData('global');\n\nglobalData.iteration = 0;\n\nreturn item;"
      },
      "typeVersion": 1
    },
    {
      "name": "IF2",
      "type": "n8n-nodes-base.if",
      "position": [
        1850,
        110
      ],
      "parameters": {
        "conditions": {
          "number": [
            {
              "value1": "={{$node[\"getActualPrice\"].json[\"price\"]}}",
              "value2": "={{$node[\"updateSavedItems1\"].json[\"oldPrice\"]}}"
            }
          ],
          "string": []
        }
      },
      "typeVersion": 1
    },
    {
      "name": "updateSavedItems",
      "type": "n8n-nodes-base.functionItem",
      "position": [
        1350,
        110
      ],
      "parameters": {
        "functionCode": "const globalData = getWorkflowStaticData('global');\n\nvar myitems = [];\nvar i;\nfor (i = 0; i < item.items.length; i++) { \n  if($node[\"initItem\"].json.slug == item.items[i].slug && $node[\"getActualPrice\"].json.price < item.items[i].price) {\n    item.items[i].price = $node[\"getActualPrice\"].json.price;\n  }\n  myitems.push(item.items[i]);\n} \n\nreturn myitems;\n"
      },
      "typeVersion": 1
    },
    {
      "name": "updateSavedItems1",
      "type": "n8n-nodes-base.functionItem",
      "position": [
        1200,
        -20
      ],
      "parameters": {
        "functionCode": "const globalData = getWorkflowStaticData('global');\nvar oldPrice = null;\nvar myitems = [];\nvar i;\nfor (i = 0; i < item.length; i++) {\n  if($node[\"initItem\"].json.slug == item[i].slug) {\n\n    item[i].link = $node[\"initItem\"].json.link;\n    item[i].selector = $node[\"initItem\"].json.selector;\n    item[i].currency = $node[\"initItem\"].json.currency;\n    \n    if(!item[i].price){\n      item[i].price = $node[\"getActualPrice\"].json.price;\n    }\n    \n    if($node[\"getActualPrice\"].json.price < item[i].price){\n      oldPrice = item[i].price;\n      item[i].price = $node[\"getActualPrice\"].json.price;\n    }\n    \n    \n  }\n  \n  myitems.push(item[i]);\n} \n\n//item.somar = $node[\"initItem\"].json;\n//return globalData.actualPrice;\n\nvar itemm = {};\nitemm.items = myitems;\nitemm.oldPrice = oldPrice;\nreturn itemm;\n"
      },
      "typeVersion": 1
    },
    {
      "name": "cleanData",
      "type": "n8n-nodes-base.executeCommand",
      "notes": "This will remove all storaged data.",
      "position": [
        -1290,
        -560
      ],
      "parameters": {
        "command": "file=\"/data/kopacky.json\"\n[ -f $file ] && rm $file"
      },
      "typeVersion": 1
    },
    {
      "name": "IF4",
      "type": "n8n-nodes-base.if",
      "position": [
        150,
        -390
      ],
      "parameters": {
        "conditions": {
          "string": [],
          "boolean": [
            {
              "value1": "={{$node[\"getActualPrice\"].json[\"priceExists\"]}}"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "name": "NotifyBetterPrice",
      "type": "n8n-nodes-base.emailSend",
      "position": [
        1850,
        -90
      ],
      "parameters": {
        "html": "=<h2>Nová cena je: {{$node[\"getActualPrice\"].json[\"price\"]}} {{$node[\"initItem\"].json[\"currency\"]}}</h2><br>\nPôvodná cena bola: {{$node[\"updateSavedItems1\"].json[\"oldPrice\"]}} {{$node[\"initItem\"].json[\"currency\"]}}<br>\nURL: {{$node[\"initItem\"].json[\"link\"]}}",
        "text": "=",
        "options": {},
        "subject": "=Nová cena - {{$node[\"initItem\"].json[\"slug\"]}} - {{$node[\"getActualPrice\"].json[\"price\"]}} {{$node[\"initItem\"].json[\"currency\"]}}",
        "toEmail": "sthosstudio@gmail.com",
        "fromEmail": "hostovecky@weyou.sk"
      },
      "credentials": {
        "smtp": "hostovecky@weyou.sk"
      },
      "typeVersion": 1
    },
    {
      "name": "NotifyIncorrectPrice",
      "type": "n8n-nodes-base.emailSend",
      "position": [
        270,
        -690
      ],
      "parameters": {
        "html": "=Please check the link or selector for the item with slug <strong>{{$node[\"initItem\"].json[\"slug\"]}}</strong><br>\nURL: {{$node[\"initItem\"].json[\"link\"]}}",
        "text": "=",
        "options": {},
        "subject": "={{$node[\"initItem\"].json[\"slug\"]}} - Getting price issue.",
        "toEmail": "sthosstudio@gmail.com",
        "fromEmail": "hostovecky@weyou.sk"
      },
      "credentials": {
        "smtp": "hostovecky@weyou.sk"
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "IF": {
      "main": [
        [
          {
            "node": "changeME",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF1": {
      "main": [
        [
          {
            "node": "FunctionItem",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "IF3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF2": {
      "main": [
        [
          {
            "node": "NotifyBetterPrice",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "IF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF3": {
      "main": [
        [
          {
            "node": "savedItems",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF4": {
      "main": [
        [
          {
            "node": "NotifyIncorrectPrice",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "checkifexists",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Cron": {
      "main": [
        [
          {
            "node": "initItem1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "changeME": {
      "main": [
        [
          {
            "node": "initItem",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "fetchWeb": {
      "main": [
        [
          {
            "node": "HTML Extract",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "initItem": {
      "main": [
        [
          {
            "node": "fetchWeb",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "initItem1": {
      "main": [
        [
          {
            "node": "changeME",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SaveToFile": {
      "main": [
        [
          {
            "node": "IF2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "savedItems": {
      "main": [
        [
          {
            "node": "itemsToJSON",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "itemsToJSON": {
      "main": [
        [
          {
            "node": "updateSavedItems1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "FunctionItem": {
      "main": [
        [
          {
            "node": "Move Binary Data1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTML Extract": {
      "main": [
        [
          {
            "node": "getActualPrice",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "JsonToBinary": {
      "main": [
        [
          {
            "node": "SaveToFile",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "checkifexists": {
      "main": [
        [
          {
            "node": "IF1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "getActualPrice": {
      "main": [
        [
          {
            "node": "IF4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "updateSavedItems": {
      "main": [
        [
          {
            "node": "JsonToBinary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Move Binary Data1": {
      "main": [
        [
          {
            "node": "Write Binary File1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "NotifyBetterPrice": {
      "main": [
        [
          {
            "node": "IF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "updateSavedItems1": {
      "main": [
        [
          {
            "node": "updateSavedItems",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Write Binary File1": {
      "main": [
        [
          {
            "node": "IF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "NotifyIncorrectPrice": {
      "main": [
        [
          {
            "node": "checkifexists",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Workflow n8n Discord, notifications, e-commerce : pour qui est ce workflow ?

Ce workflow s'adresse principalement aux e-commerçants, aux équipes de vente et aux professionnels du marketing digital qui cherchent à optimiser leur communication avec les clients. Il est idéal pour les entreprises de taille petite à moyenne, avec un niveau technique intermédiaire requis pour sa mise en place.

Workflow n8n Discord, notifications, e-commerce : problème résolu

Ce workflow résout le problème de la surveillance manuelle des prix, qui peut être chronophage et source d'erreurs. En automatisant ce processus, les utilisateurs peuvent réduire les risques de manquer des opportunités de vente en raison de changements de prix. Les notifications en temps réel permettent également d'améliorer la satisfaction client, en offrant une transparence sur les fluctuations de prix.

Workflow n8n Discord, notifications, e-commerce : étapes du workflow

Étape 1 : Le workflow est déclenché par un Cron qui exécute le processus à intervalles réguliers.

  • Étape 1 : Une requête HTTP est faite pour récupérer le prix actuel d'un produit.
  • Étape 2 : Les données extraites sont traitées pour vérifier si le prix a changé.
  • Étape 3 : Si le prix a baissé, un email est envoyé pour notifier les utilisateurs d'une meilleure offre.
  • Étape 4 : Si le prix a augmenté, un autre email est envoyé pour informer les utilisateurs de cette hausse.
  • Étape 5 : Les données sont sauvegardées pour un suivi futur.

Workflow n8n Discord, notifications, e-commerce : guide de personnalisation

Pour personnaliser ce workflow, commencez par modifier l'URL dans le nœud HTTP pour pointer vers l'API de votre choix. Vous pouvez également ajuster les paramètres du Cron pour définir la fréquence des vérifications de prix. Pour les notifications, personnalisez les adresses email dans les nœuds d'envoi d'email afin de cibler les utilisateurs souhaités. Enfin, adaptez les conditions dans les nœuds de vérification de prix pour répondre à vos critères spécifiques.