AutomationFlowsWeb Scraping › Sync WooCommerce Product to JTL FFN API

Sync WooCommerce Product to JTL FFN API

Original n8n title: Manual Product Sync - Single Product

Manual Product Sync - Single Product. Uses wooCommerce, httpRequest. Event-driven trigger; 5 nodes.

Event trigger★★★★☆ complexity5 nodesWooCommerceHTTP Request
Web Scraping Trigger: Event Nodes: 5 Complexity: ★★★★☆ Added:

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "name": "Manual Product Sync - Single Product",
  "nodes": [
    {
      "parameters": {},
      "id": "manual-trigger",
      "name": "When clicking 'Test workflow'",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        250,
        300
      ]
    },
    {
      "parameters": {
        "resource": "product",
        "operation": "getAll",
        "returnAll": false,
        "limit": 10,
        "options": {
          "sku": "SKU12334"
        }
      },
      "id": "get-single-product",
      "name": "Get Product by SKU",
      "type": "n8n-nodes-base.wooCommerce",
      "typeVersion": 1,
      "position": [
        450,
        300
      ],
      "credentials": {
        "wooCommerceApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Transform WooCommerce product to JTL FFN CreateProductRequest format\nconst product = $input.first().json;\n\n// Helper function to safely get nested values\nfunction safeGet(obj, path, defaultValue) {\n  if (!obj) return defaultValue;\n  const keys = path.split('.');\n  let result = obj;\n  for (const key of keys) {\n    if (result && result[key] !== undefined) {\n      result = result[key];\n    } else {\n      return defaultValue;\n    }\n  }\n  return result !== undefined ? result : defaultValue;\n}\n\n// Build identifier object (at least one identifier required)\nconst identifier = {\n  ean: safeGet(product, 'sku', null), // Using SKU as EAN for now\n};\n\n// Build dimensions (convert from cm to meters for JTL FFN)\nconst dimensions = product.dimensions || {};\nconst length = dimensions.length ? parseFloat(dimensions.length) / 100 : 0;\nconst width = dimensions.width ? parseFloat(dimensions.width) / 100 : 0;\nconst height = dimensions.height ? parseFloat(dimensions.height) / 100 : 0;\n\n// Build attributes array (key/value pairs)\nconst attributes = [];\n\n// Add platform info\nattributes.push({\n  key: 'platform',\n  value: 'woocommerce'\n});\n\n// Add external product ID\nattributes.push({\n  key: 'externalProductId',\n  value: product.id ? product.id.toString() : ''\n});\n\n// Add product type\nif (product.type) {\n  attributes.push({\n    key: 'productType',\n    value: product.type\n  });\n}\n\n// Add categories\nif (product.categories && product.categories.length > 0) {\n  const categoryNames = product.categories.map(function(cat) {\n    return cat.name;\n  }).join(', ');\n  attributes.push({\n    key: 'categories',\n    value: categoryNames\n  });\n}\n\n// Build the JTL FFN product request\n// Note: Weight must be > 0, so use 0.1 kg as default if not specified\nconst weight = product.weight && parseFloat(product.weight) > 0 ? parseFloat(product.weight) : 0.1;\n\nconst jtlProduct = {\n  name: product.name || 'Unnamed Product',\n  merchantSku: product.sku || product.id.toString(),\n  identifier: identifier,\n  description: product.description || null,\n  attributes: attributes,\n  weight: weight,\n  length: length || 0.01,\n  width: width || 0.01,\n  height: height || 0.01\n};\n\nreturn [{ json: jtlProduct }];"
      },
      "id": "transform-product",
      "name": "Transform Product Data",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        650,
        300
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://ffn.api.jtl-software.com/api/v1/merchant/products",
        "authentication": "genericCredentialType",
        "genericAuthType": "oAuth2Api",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{$json}}",
        "options": {
          "timeout": 15000
        }
      },
      "id": "send-to-api",
      "name": "Send Product to JTL FFN API",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.1,
      "position": [
        850,
        300
      ],
      "credentials": {
        "oAuth2Api": {
          "name": "<your credential>"
        }
      },
      "onError": "continueErrorOutput"
    },
    {
      "parameters": {
        "content": "## Manual Product Sync\n\n**How to use:**\n1. Change the SKU in the 'Get Product by SKU' node\n2. Currently set to: SKU12334\n3. Click 'Execute workflow'\n4. Change to SKU238952 and run again\n\n**This will sync both products to JTL FFN**",
        "height": 300,
        "width": 350
      },
      "id": "sticky-note",
      "name": "Instructions",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        200,
        100
      ]
    }
  ],
  "connections": {
    "When clicking 'Test workflow'": {
      "main": [
        [
          {
            "node": "Get Single WooCommerce Product",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Single WooCommerce Product": {
      "main": [
        [
          {
            "node": "Transform Product Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Transform Product Data": {
      "main": [
        [
          {
            "node": "Send Product to JTL FFN API",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Manual Product Sync - Single Product. Uses wooCommerce, httpRequest. Event-driven trigger; 5 nodes.

Source: https://github.com/Simhateja17/no_limits_all/blob/ca2a0b144385d415c3b212cf68cad5d87f057f24/n8n-workflows/manual-product-sync.json — original creator credit. Request a take-down →

More Web Scraping workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Web Scraping

This workflow allows you to import any workflow from a file or another n8n instance and map the credentials easily. A multi-form setup guides you through the entire process At the beginning you have t

Execute Command, Read Write File, HTTP Request +3
Web Scraping

[n8n] Advanced URL Parsing and Shortening Workflow - Switchy.io Integration. Uses splitInBatches, stickyNote, httpRequest, html. Event-driven trigger; 56 nodes.

HTTP Request, GitHub, Stop And Error +1
Web Scraping

[](https://youtu.be/c7yCZhmMjtI)

HTTP Request, GitHub, Stop And Error +1
Web Scraping

This automation organizes your n8n workflows files into categorizes (Active, Template, Done, Archived) and uploads them directly to a categorized Google Drive folders. It is designed to help users man

Google Drive, HTTP Request, Time Saved
Web Scraping

Create Animated Stories using GPT-4o-mini, Midjourney, Kling and Creatomate API. Uses httpRequest. Event-driven trigger; 51 nodes.

HTTP Request