Workflow n8n

Automatisation Strava avec n8n : envoi de rapports par email

Ce workflow n8n a pour objectif d'automatiser l'envoi de rapports d'activités sportives depuis Strava vers une adresse email via Gmail. Dans un contexte où les entraîneurs et les athlètes cherchent à optimiser leur communication, cette automatisation permet de gagner du temps et d'améliorer le suivi des performances. En intégrant Strava, Google Gemini et Gmail, ce workflow facilite la création de rapports personnalisés basés sur les données d'activité des utilisateurs. Étape 1 : Le déclencheur 'Strava Trigger' s'active lorsqu'un nouvel événement d'activité est enregistré. Étape 2 : Les données de l'activité sont ensuite traitées par le modèle de chat Google Gemini, qui génère un texte descriptif. Étape 3 : Ce texte est combiné avec d'autres éléments pour créer un rapport complet. Étape 4 : Le rapport est ensuite converti en HTML pour un rendu optimal dans l'email. Étape 5 : L'email est envoyé via le noeud Gmail, permettant ainsi une communication fluide entre l'athlète et son coach. Les bénéfices business incluent une meilleure réactivité dans le suivi des performances et une communication simplifiée, ce qui renforce l'engagement des utilisateurs. Tags clés : automatisation, Strava, Gmail.

Catégorie: Webhook · Tags: automatisation, Strava, Gmail, email, n8n0

Vue d'ensemble du workflow n8n

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

Détail des nœuds du workflow n8n

  • Strava Trigger

    Ce noeud déclenche le workflow en écoutant les événements de Strava.

  • Google Gemini Chat Model

    Ce noeud utilise le modèle de chat Google Gemini pour traiter des requêtes textuelles.

  • Gmail

    Ce noeud envoie un email via Gmail avec le sujet et le message spécifiés.

  • Combine Everything

    Ce noeud combine les données d'entrée en exécutant un code JavaScript.

  • Fitness Coach

    Ce noeud agit comme un coach de fitness en utilisant un agent pour traiter le texte fourni.

  • Structure Output

    Ce noeud structure la sortie en exécutant un code JavaScript.

  • Conver to HTML

    Ce noeud convertit des données en format HTML en exécutant un code JavaScript.

  • Send Email

    Ce noeud envoie un email avec le contenu HTML et les détails de l'expéditeur et du destinataire.

  • Code

    Ce noeud exécute un code JavaScript pour effectuer des traitements de données.

  • Sticky Note

    Ce noeud crée une note autocollante avec les paramètres de couleur, taille et contenu spécifiés.

  • Sticky Note12

    Ce noeud crée une note autocollante avec des spécifications similaires à celles du noeud précédent.

  • Sticky Note13

    Ce noeud crée une note autocollante avec des spécifications similaires à celles des noeuds précédents.

  • Sticky Note11

    Ce noeud crée une note autocollante avec des spécifications similaires à celles des noeuds précédents.

  • Sticky Note16

    Ce noeud crée une note autocollante avec des spécifications similaires à celles des noeuds précédents.

  • WhatsApp Business Cloud

    Ce noeud envoie un message via WhatsApp Business Cloud avec les options et le contenu spécifiés.

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

Inscription gratuite

S'inscrire gratuitementBesoin d'aide ?
{
  "meta": {
    "instanceId": "32d80f55a35a7b57f8e47a2ac19558d9f5bcec983a5519d9c29ba713ff4f12c7",
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "d9e3e2af-1db4-4ef1-a12a-c56df545e09e",
      "name": "Strava Trigger",
      "type": "n8n-nodes-base.stravaTrigger",
      "position": [
        -60,
        0
      ],
      "webhookId": "c656f7eb-6176-48b1-a68f-7e169699cecb",
      "parameters": {
        "event": "update",
        "object": "activity",
        "options": {}
      },
      "credentials": {
        "stravaOAuth2Api": {
          "id": "lI69z0e9sP9DBcrp",
          "name": "Strava account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "344106a7-f1ce-4ef0-be60-8b0dc6c92fe4",
      "name": "Google Gemini Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        560,
        180
      ],
      "parameters": {
        "options": {},
        "modelName": "models/gemini-2.0-flash-exp"
      },
      "credentials": {
        "googlePalmApi": {
          "id": "MqxJQHgdP5sIvdos",
          "name": "Google Gemini(PaLM) - ali@amjid"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "5ea7c2b8-0ddc-414e-b90c-d1269e074d16",
      "name": "Gmail",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1420,
        -200
      ],
      "webhookId": "70ab1218-b5a1-47e7-9e9e-89c5c4f84c15",
      "parameters": {
        "sendTo": "amjid@amjidali.com",
        "message": "={{ $json.html }}",
        "options": {
          "appendAttribution": false
        },
        "subject": "="
      },
      "credentials": {
        "gmailOAuth2": {
          "id": "dYWFonU1YWbQ9MHf",
          "name": "Gmail account ali@amjidali"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "540e2273-c094-4339-a9d9-41cecbaa55d8",
      "name": "Combine Everything",
      "type": "n8n-nodes-base.code",
      "position": [
        280,
        0
      ],
      "parameters": {
        "jsCode": "// Recursive function to flatten JSON into a single string\nfunction flattenJson(obj, prefix = '') {\n    let str = '';\n    for (const key in obj) {\n        if (typeof obj[key] === 'object' && obj[key] !== null) {\n            str += flattenJson(obj[key], `${prefix}${key}.`);\n        } else {\n            str += `${prefix}${key}: ${obj[key]}\\n`;\n        }\n    }\n    return str;\n}\n\n// Get input data\nconst data = $input.all();\n\n// Initialize a variable to store the final output\nlet output = '';\n\n// Process each item\ndata.forEach(item => {\n    output += flattenJson(item.json);\n    output += '\\n---\\n'; // Separator between records\n});\n\n// Return the merged string as output\nreturn [{ json: { data: output } }];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "9db17380-36ee-4d8c-842c-f33215bb5e78",
      "name": "Fitness Coach",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        560,
        0
      ],
      "parameters": {
        "text": "=You are an Triathlon Coach specializing in guiding the athlete on running, swimming, and cycling. Your role is to analyze Strava data and provide personalized coaching to help users improve their performance. Your responses must be motivational, data-driven, and tailored to the user's fitness level, goals, and recent activity trends.\n\n#### Key Abilities:\n1. **Analyze Activity Data**:\n   - Evaluate performance metrics such as distance, pace, heart rate, power, elevation, cadence, and swim strokes.\n   - Identify trends, strengths, and areas for improvement.\n\n2. **Provide Feedback**:\n   - Break down the user's activities and explain their performance in detail (e.g., pacing consistency, effort levels, technique).\n   - Highlight achievements and areas that need focus.\n\n3. **Create Improvement Plans**:\n   - Suggest actionable steps to improve fitness, endurance, speed, or technique based on the user's goals and performance data.\n   - Recommend specific workouts, recovery plans, or cross-training exercises tailored to the user's needs.\n\n4. **Set Goals and Challenges**:\n   - Help the user set realistic short-term and long-term goals (e.g., achieving a new personal best, improving endurance, or preparing for a triathlon).\n   - Suggest weekly or monthly challenges to stay motivated.\n\n5. **Motivational Coaching**:\n   - Provide positive reinforcement and encouragement.\n   - Help the user maintain consistency and avoid burnout.\n\n6. ** Data Analysis **\n - Do some data formatting also when doing activities ensure to analyze the duration, time, pace etc, too many seonds will not make differnece, try to see the duration which is easy to understand, moreoover, the time of the day when i did activity and so on.\n\n***Capabilities as a Triathlong Coach:***\n** Data Categorization and Context:**\n\nIdentify whether the activity is swimming, cycling, or running.\n-For swimming, distinguish between pool swimming (laps, strokes) and open water swimming (long-distance, sighting).\nAdapt recommendations based on activity type, terrain, weather, or other environmental factors.\n**Activity-Specific Metrics:**\n\n -- Swim: Focus on distance, pace, SWOLF, stroke count, and stroke efficiency.\n -- Bike: Analyze distance, average speed, cadence, power zones, heart rate, and elevation gain.\n -- Run: Examine distance, pace, cadence, stride length, heart rate zones, and elevation changes.\nPerformance Analysis and Recommendations:\n\n** Tailor feedback and advice based on the unique demands of each sport:\n - Swimming: Emphasize technique (catch, pull, body position), pacing, and breathing drills.\n - Cycling: Focus on power output, cadence optimization, endurance rides, and interval training.\n - Running: Analyze pace consistency, cadence, stride efficiency, and running economy.\nEnvironment-Specific Adjustments:\n\n - For swimming, account for differences in pool vs. open water conditions (e.g., sighting, drafting, and waves).\nFor cycling, consider terrain (flat, hilly, or rolling) and wind resistance.\n- For running, factor in surface type (road, trail, or track) and weather conditions.\nIntegrated Triathlon Insights:\n- \nProvide guidance on how each discipline complements the others.\nSuggest \"brick workouts\" (e.g., bike-to-run) for race-specific adaptations.\nRecommend recovery strategies that address multi-sport training fatigue.\nBehavior:\nBe precise, detailed, and motivational.\nTailor insights and recommendations to the specific activity type and the athlete’s experience level (beginner, intermediate, advanced).\nUse clear, actionable language and explain the reasoning behind suggestions.\nInputs You Will Receive:\nStrava activity data in JSON or tabular format.\nAthlete’s profile information, including goals, upcoming events, and experience level.\nMetrics such as distance, pace, speed, cadence, heart rate zones, power, SWOLF, stroke count, and elevation.\nOutput Requirements (Activity-Specific):\nSwim (Pool):\n\nAnalyze stroke efficiency, pace consistency, SWOLF, and technique.\nSuggest drills for stroke improvement (e.g., catch-up, fingertip drag).\nRecommend pacing intervals (e.g., 10x100m at target pace with rest).\nSwim (Open Water):\n\nEvaluate long-distance pacing and sighting frequency.\nProvide tips on drafting, breathing bilaterally, and adapting to waves or currents.\nSuggest open water-specific workouts (e.g., race-pace simulations with buoy turns).\nBike:\n\nAnalyze power distribution across zones, cadence, and heart rate trends.\nHighlight inefficiencies (e.g., low cadence on climbs or inconsistent power).\nRecommend specific workouts (e.g., 3x12-minute FTP intervals with 5-minute rest).\nSuggest gear and bike fit optimizations if needed.\nRun:\n\nEvaluate pacing strategy, cadence, and heart rate zones.\nIdentify inefficiencies in stride length or cadence.\nRecommend workouts like tempo runs, intervals, or long runs with negative splits.\nProvide race-day pacing strategies or tips for improving running economy.\nCross-Discipline Integration:\n\nSuggest brick workouts to improve transitions (e.g., 30-minute bike + 10-minute run at race pace).\nRecommend recovery sessions (e.g., easy swim or bike after a hard run).\nAdvise on balancing training load across disciplines.\n\n#### Expectations:\n- **Personalized Responses**: Always consider the user's activity history, goals, and fitness level when offering insights or advice.\n- **Practical Guidance**: Provide clear, actionable recommendations.\n- **Encouragement**: Keep the tone positive and motivational, celebrating progress while constructively addressing areas for improvement.\n\n#### Context Awareness:\nYou have access to the user's Strava data, including:\n- Activity type (e.g., run, swim, bike)\n- Distance, pace, and time\n- Heart rate and effort levels\n- Elevation gain and route details\n- Historical performance trends\n\n#### Example Prompts You Will Receive:\n- \"Here are my recent running activities. How can I improve my pace?\"\n- \"This is my swimming data from this week. What should I focus on to improve my technique?\"\n- \"Analyze my cycling activity and tell me how I can climb better next time.\"\n\n\n#### Goal:\nHelp the user achieve their athletic potential by providing precise, actionable feedback and a customized plan to enhance their performance and enjoyment of their activities.\n\nHere is the Activity Data : \n{{ $json.data }}",
        "agent": "conversationalAgent",
        "options": {},
        "promptType": "define"
      },
      "typeVersion": 1.7
    },
    {
      "id": "7eaec341-33e0-492f-b87d-7a6dcf3d288e",
      "name": "Structure Output",
      "type": "n8n-nodes-base.code",
      "position": [
        1020,
        -140
      ],
      "parameters": {
        "jsCode": "// Input JSON from the previous node\nconst input = $json.output;\n\n// Split the input into sections based on double newlines\nconst sections = input.split('\\n\\n');\n\n// Initialize the result array\nconst result = [];\n\n// Process each section\nsections.forEach((section) => {\n    const trimmedSection = section.trim();\n\n    // Handle headings marked with ** (bold)\n    if (/^\\*\\*(.*?)\\*\\*$/.test(trimmedSection)) {\n        result.push({ type: 'heading', content: trimmedSection.replace(/\\*\\*(.*?)\\*\\*/, '<b>$1</b>') });\n    }\n    // Handle bullet lists marked with *\n    else if (trimmedSection.startsWith('*')) {\n        const listItems = trimmedSection.split('\\n').map((item) => item.trim().replace(/^\\*\\s/, ''));\n        result.push({ type: 'list', items: listItems });\n    }\n    // Handle numbered lists\n    else if (/^\\d+\\.\\s/.test(trimmedSection)) {\n        const numberedItems = trimmedSection.split('\\n').map((item) => item.trim().replace(/^\\d+\\.\\s/, ''));\n        result.push({ type: 'numbered-list', items: numberedItems });\n    }\n    // Handle paragraphs\n    else {\n        result.push({ type: 'paragraph', content: trimmedSection });\n    }\n});\n\n// Return the result array\nreturn result.map(item => ({ json: item }));\n"
      },
      "typeVersion": 2
    },
    {
      "id": "c70da1ca-72c2-4a95-acaf-4efc23ae3f6e",
      "name": "Conver to HTML",
      "type": "n8n-nodes-base.code",
      "position": [
        1060,
        60
      ],
      "parameters": {
        "jsCode": "// Get input data from n8n\nconst inputData = $input.all(); // Fetch all input data items\n\n// Function to convert JSON data into a single HTML string\nfunction convertToHTML(data) {\n    let html = '';\n\n    data.forEach((item) => {\n        switch (item.json.type) {\n            case 'paragraph':\n                html += `<p>${item.json.content}</p>`;\n                break;\n            case 'heading':\n                html += `<h2>${item.json.content}</h2>`;\n                break;\n            case 'list':\n                html += '<ul>';\n                item.json.items.forEach((listItem) => {\n                    html += `<li>${listItem}</li>`;\n                });\n                html += '</ul>';\n                break;\n            case 'numbered-list':\n                html += '<ol>';\n                item.json.items.forEach((listItem) => {\n                    html += `<li>${listItem}</li>`;\n                });\n                html += '</ol>';\n                break;\n            default:\n                break;\n        }\n    });\n\n    return html;\n}\n\n// Convert inputData to a single HTML string\nconst singleHTML = convertToHTML(inputData);\n\n// Return as a single item\nreturn [{ json: { html: singleHTML } }];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "b646220c-a0c9-4af7-a2a8-09cec619ecbf",
      "name": "Send Email",
      "type": "n8n-nodes-base.emailSend",
      "position": [
        1420,
        0
      ],
      "parameters": {
        "html": "={{ $json.html }}",
        "options": {
          "appendAttribution": false
        },
        "subject": "=New Activity on Strava",
        "toEmail": "email@gmail.com",
        "fromEmail": "Fitness Coach <email@example.com>"
      },
      "credentials": {
        "smtp": {
          "id": "WpZf64vFcOT99dO6",
          "name": "SMTP OCI Amjid"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "06d6262d-dd72-4e57-bccb-31d87a9086c9",
      "name": "Code",
      "type": "n8n-nodes-base.code",
      "position": [
        120,
        0
      ],
      "parameters": {
        "jsCode": "// Loop over input items and add a new field called 'myNewField' to the JSON of each one\nfor (const item of $input.all()) {\n  item.json.myNewField = 1;\n}\n\nreturn $input.all();"
      },
      "typeVersion": 2
    },
    {
      "id": "14ce1a3c-573b-4b17-a9f1-eab5964ac9c8",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        460,
        -300
      ],
      "parameters": {
        "color": 7,
        "width": 444,
        "height": 649,
        "content": "### Customer Experience Agent (AI)\nThe AI Triathlon Coach is an intelligent, data-driven virtual assistant designed to help triathletes optimize their training and performance across swimming, cycling, and running. Using advanced algorithms, it analyzes activity data from platforms like Strava and provides actionable insights tailored to the athlete’s goals, experience level, and specific disciplines.\nThis is connected to Gemini 2.0 Flash\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "cccfdcfa-c981-4c8d-8177-d9597b50556c",
      "name": "Sticky Note12",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        940,
        -300
      ],
      "parameters": {
        "color": 5,
        "width": 329,
        "height": 655,
        "content": "### Convert to HTML\nNow the data will be structured and covnerted to HTML"
      },
      "typeVersion": 1
    },
    {
      "id": "4618dd06-8754-4ba2-9d86-77d7a4bdbad2",
      "name": "Sticky Note13",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -80,
        -320
      ],
      "parameters": {
        "color": 6,
        "width": 503,
        "height": 651,
        "content": "### Get Strava Trigger\nIf you are using Strava, you can create API Key by logging in to : https://developers.strava.com/\n\nOnce data is capture you can then structure it, i am commbining all the activity data and sending to next node"
      },
      "typeVersion": 1
    },
    {
      "id": "2f9626de-789f-4c28-b1bd-189dc1203d46",
      "name": "Sticky Note11",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -580,
        -320
      ],
      "parameters": {
        "color": 4,
        "width": 475.27306699862953,
        "height": 636.1483291619771,
        "content": "## Developed by Amjid Ali\n\nThank you for using this workflow template. It has taken me countless hours of hard work, research, and dedication to develop, and I sincerely hope it adds value to your work.\n\nIf you find this template helpful, I kindly ask you to consider supporting my efforts. Your support will help me continue improving and creating more valuable resources.\n\nYou can contribute via PayPal here:\n\nhttp://paypal.me/pmptraining\n\nFor Full Course about ERPNext or Automation using AI follow below link\n\nhttp://lms.syncbricks.com\n\nAdditionally, when sharing this template, I would greatly appreciate it if you include my original information to ensure proper credit is given.\n\nThank you for your generosity and support!\nEmail : amjid@amjidali.com\nhttps://linkedin.com/in/amjidali\nhttps://syncbricks.com\nhttps://youtube.com/@syncbricks"
      },
      "typeVersion": 1
    },
    {
      "id": "7b6fb4ba-a20b-40b0-9a40-33f18fb6d28b",
      "name": "Sticky Note16",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1300,
        -300
      ],
      "parameters": {
        "color": 4,
        "width": 609,
        "height": 655,
        "content": "### Send Personalized Response\nActivity is analized you can either get the response by Whatsapp , emal, a blog or anything"
      },
      "typeVersion": 1
    },
    {
      "id": "30197511-1f5b-4d54-af6e-376a3c596b75",
      "name": "WhatsApp Business Cloud",
      "type": "n8n-nodes-base.whatsApp",
      "position": [
        1420,
        200
      ],
      "parameters": {
        "operation": "send",
        "requestOptions": {},
        "additionalFields": {}
      },
      "credentials": {
        "whatsAppApi": {
          "id": "pDzUNbXM7NG3GZto",
          "name": "WhatsApp account"
        }
      },
      "typeVersion": 1
    }
  ],
  "pinData": {},
  "connections": {
    "Code": {
      "main": [
        [
          {
            "node": "Combine Everything",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Email": {
      "main": [
        []
      ]
    },
    "Fitness Coach": {
      "main": [
        [
          {
            "node": "Structure Output",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Conver to HTML": {
      "main": [
        [
          {
            "node": "Send Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Strava Trigger": {
      "main": [
        [
          {
            "node": "Code",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structure Output": {
      "main": [
        [
          {
            "node": "Conver to HTML",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Combine Everything": {
      "main": [
        [
          {
            "node": "Fitness Coach",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Fitness Coach",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    }
  }
}

Pour qui est ce workflow ?

Ce workflow s'adresse principalement aux entraîneurs sportifs, aux athlètes et aux équipes de fitness qui souhaitent automatiser leur communication. Il est idéal pour les utilisateurs ayant un niveau technique intermédiaire et qui utilisent déjà Strava et Gmail dans leur quotidien.

Problème résolu

Ce workflow résout le problème de la gestion manuelle des rapports d'activités sportives, qui peut être chronophage et sujet à des erreurs. En automatisant l'envoi de ces rapports, les utilisateurs gagnent un temps précieux et améliorent la précision des informations partagées. Cela réduit également le risque de perte de données importantes et permet un suivi plus efficace des performances.

Étapes du workflow

Étape 1 : Le workflow débute avec le déclencheur 'Strava Trigger', qui s'active lors d'un nouvel événement d'activité. Étape 2 : Les données de l'activité sont envoyées au modèle Google Gemini pour générer un texte descriptif. Étape 3 : Le texte est ensuite combiné avec d'autres éléments dans le noeud 'Combine Everything'. Étape 4 : Le contenu est structuré et converti en HTML pour un rendu optimal. Étape 5 : Enfin, l'email est envoyé via le noeud Gmail à l'adresse spécifiée.

Guide de personnalisation du workflow n8n

Pour personnaliser ce workflow, vous pouvez modifier les paramètres du déclencheur Strava pour filtrer les types d'activités qui vous intéressent. Adaptez également le modèle de chat Google Gemini en fonction de vos besoins spécifiques en matière de rapport. Il est possible de changer l'adresse email dans le noeud Gmail pour envoyer les rapports à différents destinataires. Pensez à ajuster le contenu des notes autocollantes si vous souhaitez ajouter des éléments visuels supplémentaires. Enfin, assurez-vous de tester le workflow pour garantir son bon fonctionnement avant de le mettre en production.