とりあえず仮でできたかも。
{
"name": "Amazon API直接連携 - 日次売上集計",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 6 * * *"
}
]
}
},
"id": "schedule-trigger",
"name": "毎朝6時実行",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.2,
"position": [250, 400]
},
{
"parameters": {
"jsCode": "// 前日の日付を計算\nconst yesterday = new Date();\nyesterday.setDate(yesterday.getDate() - 1);\n\n// YYYY-MM-DD形式にフォーマット\nconst year = yesterday.getFullYear();\nconst month = String(yesterday.getMonth() 1).padStart(2, '0');\nconst day = String(yesterday.getDate()).padStart(2, '0');\nconst dateStr = `${year}-${month}-${day}`;\n\n// ISO 8601形式(Amazon API用)\nconst startOfDay = new Date(yesterday.setHours(0, 0, 0, 0));\nconst endOfDay = new Date(yesterday.setHours(23, 59, 59, 999));\n\nreturn {\n json: {\n date: dateStr,\n startDate: dateStr,\n endDate: dateStr,\n startDateTime: startOfDay.toISOString(),\n endDateTime: endOfDay.toISOString()\n }\n};"
},
"id": "code-date",
"name": "前日の日付を計算",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [450, 400]
},
{
"parameters": {
"url": "
sellingpartnerapi-fe.amazon.…",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "amazonSpApi",
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "MarketplaceIds",
"value": "A1VC38T7YXB528"
},
{
"name": "CreatedAfter",
"value": "={{
$json.startDateTime }}"
},
{
"name": "CreatedBefore",
"value": "={{
$json.endDateTime }}"
},
{
"name": "OrderStatuses",
"value": "Shipped,Unshipped"
}
]
},
"options": {}
},
"id": "http-orders",
"name": "注文データ取得",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [650, 300],
"notes": "Amazon SP-APIから注文情報を取得"
},
{
"parameters": {
"url": "
advertising-api.amazon.com/v…",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "amazonAdvertisingApi",
"method": "POST",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Amazon-Advertising-API-Scope",
"value": "YOUR_PROFILE_ID"
}
]
},
"sendBody": true,
"contentType": "json",
"jsonBody": "={\n \"reportDate\": \"{{
$json.startDate }}\",\n \"metrics\": \"cost,impressions,clicks,sales\"\n}",
"options": {}
},
"id": "http-ad-report-request",
"name": "広告レポート要求",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [650, 500],
"notes": "Amazon Advertising APIにレポート生成を要求"
},
{
"parameters": {
"amount": 30,
"unit": "seconds"
},
"id": "wait",
"name": "レポート生成待機",
"type": "n8n-nodes-base.wait",
"typeVersion": 1.1,
"position": [850, 500],
"webhookId": "wait-webhook-id"
},
{
"parameters": {
"url": "=
advertising-api.amazon.com/v…{{
$json.reportId }}",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "amazonAdvertisingApi",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Amazon-Advertising-API-Scope",
"value": "YOUR_PROFILE_ID"
}
]
},
"options": {}
},
"id": "http-ad-report-download",
"name": "広告レポート取得",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [1050, 500],
"notes": "生成された広告レポートをダウンロード"
},
{
"parameters": {
"jsCode": "// 注文データから売上と注文商品を集計\nconst ordersData =
$input.first().json;\nconst adData =
$input.last().json;\n\n// 売上合計と商品別集計の初期化\nlet totalSales = 0;\nconst productSales = {};\n\nif (ordersData.payload && ordersData.payload.Orders) {\n for (const order of ordersData.payload.Orders) {\n // 各注文の合計金額を加算\n if (order.OrderTotal && order.OrderTotal.Amount) {\n totalSales = parseFloat(order.OrderTotal.Amount);\n }\n \n // 注文商品の詳細を取得する必要がある(次のステップで実装)\n // ここでは注文IDをリストに保存\n if (!$node[\"Order IDs\"].json.orderIds) {\n
$node[\"Order IDs\"].json.orderIds = [];\n }\n
$node[\"Order IDs\"].json.orderIds.push(order.AmazonOrderId);\n }\n}\n\n// 広告費の集計\nlet totalAdCost = 0;\nif (adData && Array.isArray(adData)) {\n for (const campaign of adData) {\n if (campaign.cost) {\n totalAdCost = parseFloat(campaign.cost);\n }\n }\n}\n\nreturn {\n json: {\n totalSales: totalSales,\n totalAdCost: totalAdCost,\n orderCount: ordersData.payload?.Orders?.length || 0\n }\n};"
},
"id": "code-aggregate-initial",
"name": "初期集計",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [1250, 400]
},
{
"parameters": {
"batchSize": 50,
"options": {}
},
"id": "split-in-batches",
"name": "注文IDをバッチ分割",
"type": "n8n-nodes-base.splitInBatches",
"typeVersion": 3,
"position": [1450, 300]
},
{
"parameters": {
"url": "=
sellingpartnerapi-fe.amazon.…{{
$json.orderId }}/orderItems",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "amazonSpApi",
"options": {}
},
"id": "http-order-items",
"name": "注文商品詳細取得",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [1650, 300],
"notes": "各注文の商品明細を取得"
},
{
"parameters": {
"jsCode": "// 商品別の売上を集計\nconst items = [];\n\nfor (const input of
$input.all()) {\n if (input.json.payload && input.json.payload.OrderItems) {\n for (const item of input.json.payload.OrderItems) {\n items.push({\n json: {\n asin: item.ASIN,\n sku: item.SellerSKU,\n title: item.Title,\n quantity: item.QuantityOrdered,\n itemPrice: parseFloat(item.ItemPrice?.Amount || 0),\n itemTax: parseFloat(item.ItemTax?.Amount || 0)\n }\n });\n }\n }\n}\n\nreturn items;"
},
"id": "code-parse-items",
"name": "商品データ解析",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [1850, 300]
},
{
"parameters": {
"operation": "aggregateItems",
"fieldsToAggregate": {
"fieldToAggregate": [
{
"fieldToAggregate": "quantity",
"aggregation": "sum"
},
{
"fieldToAggregate": "itemPrice",
"aggregation": "sum"
}
]
},
"options": {
"groupByFields": "asin"
}
},
"id": "aggregate",
"name": "ASIN別に集計",
"type": "n8n-nodes-base.aggregate",
"typeVersion": 1,
"position": [2050, 300]
},
{
"parameters": {
"operation": "read",
"documentId": {
"mode": "id",
"value": "YOUR_COST_SPREADSHEET_ID"
},
"sheetName": {
"mode": "name",
"value": "原価マスタ"
},
"options": {
"range": "A:D"
}
},
"id": "google-sheets-cost",
"name": "原価データ取得",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.7,
"position": [2050, 500],
"credentials": {
"googleSheetsOAuth2Api": {
"id": "YOUR_GOOGLE_CREDENTIALS_ID",
"name": "Google Sheets account"
}
},
"notes": "ASIN, 仕入れ価格, 物流価格のマスタデータ"
},
{
"parameters": {
"jsCode": "// 売上データと原価データを結合して粗利益を計算\nconst salesData =
$input.first().json;\nconst costData =
$input.last().json;\nconst adCost = $('初期集計').first().json.totalAdCost;\nconst date = $('前日の日付を計算').first().json.date;\n\n// 原価マスタをASINでマッピング\nconst costMap = {};\nif (Array.isArray(costData)) {\n for (const row of costData) {\n if (row.ASIN) {\n costMap[row.ASIN] = {\n purchasePrice: parseFloat(row['仕入れ価格'] || 0),\n logisticsPrice: parseFloat(row['物流価格'] || 0)\n };\n }\n }\n}\n\n// 全体サマリーの計算\nlet totalSales = 0;\nlet totalCost = 0;\nlet totalLogistics = 0;\nconst productResults = [];\n\n// 商品別の計算\nfor (const input of
$input.all()) {\n const asin = input.json.asin;\n const quantity = input.json.quantity || 0;\n const sales = input.json.itemPrice || 0;\n \n const cost = costMap[asin] || { purchasePrice: 0, logisticsPrice: 0 };\n const productCost = cost.purchasePrice * quantity;\n const productLogistics = cost.logisticsPrice * quantity;\n const productTotal = productCost productLogistics;\n const grossProfit = sales - productTotal;\n const profitMargin = sales > 0 ? (grossProfit / sales * 100) : 0;\n \n totalSales = sales;\n totalCost = productCost;\n totalLogistics = productLogistics;\n \n productResults.push({\n date: date,\n type: '親ASIN',\n asin: asin,\n productName: input.json.title || '-',\n quantity: quantity,\n sales: sales,\n purchaseCost: productCost,\n logisticsCost: productLogistics,\n totalCost: productTotal,\n grossProfit: grossProfit,\n adCost: 0, // ASINごとの広告費は別途配分が必要\n profitMargin: profitMargin.toFixed(2)\n });\n}\n\n// 全体サマリー\nconst totalCosts = totalCost totalLogistics;\nconst totalGrossProfit = totalSales - totalCosts;\nconst netProfit = totalGrossProfit - adCost;\nconst profitMargin = totalSales > 0 ? (netProfit / totalSales * 100) : 0;\n\nconst overallResult = {\n date: date,\n type: '全体',\n asin: '-',\n productName: '-',\n quantity: productResults.reduce((sum, p) => sum p.quantity, 0),\n sales: totalSales,\n purchaseCost: totalCost,\n logisticsCost: totalLogistics,\n totalCost: totalCosts,\n grossProfit: totalGrossProfit,\n adCost: adCost,\n netProfit: netProfit,\n profitMargin: profitMargin.toFixed(2)\n};\n\n// 全体と商品別を結合\nconst allResults = [overallResult, ...productResults];\n\nreturn
allResults.map(row => ({ json: row }));"
},
"id": "code-calculate-profit",
"name": "粗利益計算",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [2250, 400]
},
{
"parameters": {
"operation": "append",
"documentId": {
"mode": "id",
"value": "YOUR_RESULT_SPREADSHEET_ID"
},
"sheetName": {
"mode": "name",
"value": "売上データ"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"date": "={{
$json.date }}",
"type": "={{
$json.type }}",
"asin": "={{
$json.asin }}",
"productName": "={{
$json.productName }}",
"quantity": "={{
$json.quantity }}",
"sales": "={{
$json.sales }}",
"purchaseCost": "={{
$json.purchaseCost }}",
"logisticsCost": "={{
$json.logisticsCost }}",
"totalCost": "={{
$json.totalCost }}",
"grossProfit": "={{
$json.grossProfit }}",
"adCost": "={{
$json.adCost }}",
"profitMargin": "={{
$json.profitMargin }}"
}
},
"options": {}
},
"id": "google-sheets-output",
"name": "結果をSheetsに追加",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.7,
"position": [2450, 400],
"credentials": {
"googleSheetsOAuth2Api": {
"id": "YOUR_GOOGLE_CREDENTIALS_ID",
"name": "Google Sheets account"
}
}
}
],
"connections": {
"毎朝6時実行": {
"main": [
[
{
"node": "前日の日付を計算",
"type": "main",
"index": 0
}
]
]
},
"前日の日付を計算": {
"main": [
[
{
"node": "注文データ取得",
"type": "main",
"index": 0
},
{
"node": "広告レポート要求",
"type": "main",
"index": 0
}
]
]
},
"注文データ取得": {
"main": [
[
{
"node": "初期集計",
"type": "main",
"index": 0
}
]
]
},
"広告レポート要求": {
"main": [
[
{
"node": "レポート生成待機",
"type": "main",
"index": 0
}
]
]
},
"レポート生成待機": {
"main": [
[
{
"node": "広告レポート取得",
"type": "main",
"index": 0
}
]
]
},
"広告レポート取得": {
"main": [
[
{
"node": "初期集計",
"type": "main",
"index": 0
}
]
]
},
"初期集計": {
"main": [
[
{
"node": "注文IDをバッチ分割",
"type": "main",
"index": 0
}
]
]
},
"注文IDをバッチ分割": {
"main": [
[
{
"node": "注文商品詳細取得",
"type": "main",
"index": 0
}
]
]
},
"注文商品詳細取得": {
"main": [
[
{
"node": "商品データ解析",
"type": "main",
"index": 0
}
]
]
},
"商品データ解析": {
"main": [
[
{
"node": "ASIN別に集計",
"type": "main",
"index": 0
}
]
]
},
"ASIN別に集計": {
"main": [
[
{
"node": "粗利益計算",
"type": "main",
"index": 0
}
]
]
},
"原価データ取得": {
"main": [
[
{
"node": "粗利益計算",
"type": "main",
"index": 0
}
]
]
},
"粗利益計算": {
"main": [
[
{
"node": "結果をSheetsに追加",
"type": "main",
"index": 0
}
]
]
}
},
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"staticData": null,
"tags": [],
"triggerCount": 1,
"updatedAt": "2025-11-10T00:00:00.000Z",
"versionId": "1"
}