{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Automate Review Request via WhatsApp for Completed WooCommerce Order with Rapiwa",
  "nodes": [
    {
      "id": "4a8c635d-bd1c-45da-acea-ea28e8a691b0",
      "name": "If",
      "type": "n8n-nodes-base.if",
      "position": [
        64,
        880
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "3ab8725a-9268-45fd-b91c-0e055fe6fa7c",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.data.exists }}",
              "rightValue": "=\"true\""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "a88cec50-2e45-41b0-bcbb-01bcb92a7f79",
      "name": "Wait",
      "type": "n8n-nodes-base.wait",
      "position": [
        544,
        976
      ],
      "parameters": {},
      "typeVersion": 1.1
    },
    {
      "id": "2e326749-0efb-4968-9ee9-776a9a94ccf2",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -752,
        864
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "32af40bb-fee1-495a-9ff0-290837b24acd",
      "name": "Clean WhatsApp Number",
      "type": "n8n-nodes-base.code",
      "position": [
        -464,
        880
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\nconst updatedItems = items.map((item) => {\n  let rawNumber = item?.json[\"number\"];\n  rawNumber = rawNumber ? String(rawNumber) : \"\";\n  const cleanedNumber = rawNumber.replace(/\\D/g, \"\");\n  item.json[\"number\"] = cleanedNumber;\n  return item;\n});\nreturn updatedItems;"
      },
      "typeVersion": 2
    },
    {
      "id": "81018417-302a-49a8-a7c6-4d11be0de2b0",
      "name": "Order Completed check",
      "type": "n8n-nodes-base.code",
      "position": [
        -1008,
        864
      ],
      "parameters": {
        "jsCode": "return $input.all()\n  .filter(item => item.json && item.json.body && item.json.body.status === \"completed\")\n  .map(item => {\n    const body = item.json.body;\n\n    const customer = {\n      first_name: body.billing.first_name,\n      last_name: body.billing.last_name,\n      email: body.billing.email,\n      phone: body.billing.phone,\n      address: {\n        address_1: body.billing.address_1,\n        address_2: body.billing.address_2,\n        city: body.billing.city,\n        state: body.billing.state,\n        postcode: body.billing.postcode,\n        country: body.billing.country\n      }\n    };\n\n    const products = body.line_items.map(product => ({\n      status: body.status,\n      name: product.name,\n      size: product.meta_data?.find(meta => meta.key === \"size\")?.value,\n      product_id: product.product_id,\n      variation_id: product.variation_id,\n      quantity: product.quantity,\n      price: `${body.currency} ${product.price}`,\n      total: `${body.currency} ${product.total}`,\n      image: product.image?.src || null\n    }));\n\n    return {\n      json: {\n        data: {\n          customer,\n          products,\n          invoice_link: body.payment_url\n        }\n      }\n    };\n  });\n"
      },
      "typeVersion": 2
    },
    {
      "id": "2cb4272f-3315-4767-9f7c-626d4d9b62aa",
      "name": "Save State of Rows in Verified & Sent",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        528,
        752
      ],
      "parameters": {
        "columns": {
          "value": {
            "name": "={{ $('Clean WhatsApp Number').item.json.data.customer.first_name }} {{ $('Clean WhatsApp Number').item.json.data.customer.last_name }}",
            "email": "={{ $('Clean WhatsApp Number').item.json.data.customer.email }}",
            "number": "={{ $json.to }}",
            "status": "sent",
            "address1": "={{ $('Clean WhatsApp Number').item.json.data.customer.address.address_1 }}",
            "validity": "verified",
            "productId": "={{ $('Clean WhatsApp Number').item.json.data.products[0].product_id }}",
            "totalPrice": "={{ $('Clean WhatsApp Number').item.json.data.products[0].total }}",
            "invoiceLink": "={{ $('Clean WhatsApp Number').item.json.data.invoice_link }}",
            "productTitle": "={{ $('Clean WhatsApp Number').item.json.data.products[0].name }}",
            "delivery status": "={{ $('Clean WhatsApp Number').item.json.data.products[0].status }}"
          },
          "schema": [
            {
              "id": "name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "number",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "address1",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "address1",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "productTitle",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "productTitle",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "productId",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "productId",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "totalPrice",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "totalPrice",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "invoiceLink",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "invoiceLink",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "delivery status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "delivery status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "validity",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "validity",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "status",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1S3RtGt5tGk2sLLm9XQTI9C1C0bq2jx3TNuGQnXmQi_s/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1S3RtGt5tGk2sLLm9XQTI9C1C0bq2jx3TNuGQnXmQi_s",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1S3RtGt5tGk2sLLm9XQTI9C1C0bq2jx3TNuGQnXmQi_s/edit?usp=drivesdk",
          "cachedResultName": "WooCommerce - Send WhatsApp review request"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "8f9428de-1801-4c1f-8925-ff551f867e86",
      "name": "Save State of Rows in Unerified & Not sent",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        304,
        976
      ],
      "parameters": {
        "columns": {
          "value": {
            "name": "={{ $('Clean WhatsApp Number').item.json.data.customer.first_name }} {{ $('Clean WhatsApp Number').item.json.data.customer.last_name }}",
            "email": "={{ $('Clean WhatsApp Number').item.json.data.customer.email }}",
            "number": "={{ $json.data.number }}",
            "status": "not sent",
            "address1": "={{ $('Clean WhatsApp Number').item.json.data.customer.address.address_1 }}",
            "validity": "unverified",
            "productId": "={{ $('Clean WhatsApp Number').item.json.data.products[0].product_id }}",
            "totalPrice": "={{ $('Clean WhatsApp Number').item.json.data.products[0].total }}",
            "invoiceLink": "={{ $('Clean WhatsApp Number').item.json.data.invoice_link }}",
            "productTitle": "={{ $('Clean WhatsApp Number').item.json.data.products[0].name }}",
            "delivery status": "={{ $('Clean WhatsApp Number').item.json.data.products[0].status }}"
          },
          "schema": [
            {
              "id": "name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "number",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "address1",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "address1",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "productTitle",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "productTitle",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "productId",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "productId",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "totalPrice",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "totalPrice",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "invoiceLink",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "invoiceLink",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "delivery status",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "delivery status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "validity",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "validity",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "status",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1S3RtGt5tGk2sLLm9XQTI9C1C0bq2jx3TNuGQnXmQi_s/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1S3RtGt5tGk2sLLm9XQTI9C1C0bq2jx3TNuGQnXmQi_s",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1S3RtGt5tGk2sLLm9XQTI9C1C0bq2jx3TNuGQnXmQi_s/edit?usp=drivesdk",
          "cachedResultName": "WooCommerce - Send WhatsApp review request"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "9eca8980-0e80-4320-be26-3d0dbfa38b80",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2848,
        144
      ],
      "parameters": {
        "width": 1504,
        "height": 1456,
        "content": "# WhatsApp Review Request Automation for WooCommerce Orders Completed\n\n## Overview\nThis workflow listens for WooCommerce order events (example: `order.updated`) or an incoming WooCommerce Trigger, normalizes the order payload, and sends WhatsApp messages through the Rapiwa API for verified numbers. It:\n- Maps the incoming payload into `{ data: { customer, products, invoice_link } }`.\n- Processes items in batches (SplitInBatches) to control throughput and avoid rate limits.\n- Cleans phone numbers, verifies WhatsApp registration via Rapiwa, and sends templated messages to verified numbers.\n- Logs every attempt into Google Sheets (separate sheets for verified/sent and unverified/not sent).\n\n## Requirements\n- HTTP Bearer credential for Rapiwa (example name in flow: `Rapiwa Bearer Auth`).\n- WooCommerce API credential for the trigger (example: `WooCommerce (get customer)`)\n- Running n8n instance with nodes: WooCommerce Trigger, Code, SplitInBatches, HTTP Request, IF, Google Sheets, Wait.\n- Rapiwa account and a valid Bearer token.\n- Google account with Sheets access and OAuth2 credentials configured in n8n.\n- WooCommerce store (or any WooCommerce Trigger source) that provides `billing` and `line_items` in the payload.\n\n\n## Google Sheet Required Columns\nNote: the exported flow contains two Google Sheets append nodes and their mappings differ slightly. Create sheets with column names that match the node mappings exactly.\n**A Google Sheet formatted like this** \u27a4 [sample](https://docs.google.com/spreadsheets/d/1vxocktoY-y-PYBZNxmUDuQv02b5F8QKhbQ0yLHjwjBY/edit?usp=sharing)\n\n### In Workflow (Send Message Using Rapiwa)\n- `Send Message Using Rapiwa` (HTTP Request) \u2014 POST `https://app.rapiwa.com/api/send-message`. \nThe flow uses a templated message like:\n```\n  Hi *{first_name} {last_name}*,\n  Your order is currently: *{product.status}*\n  Your order has been successfully delivered!\n  We\u2019d love to hear your thoughts. Please take a moment to leave a review \u2014 your feedback helps us grow and improve!\n```\n\n## How to Use This Workflow\n1. Configure credentials in n8n\n   - Rapiwa: HTTP Bearer token \u2192 `Rapiwa Bearer Auth` credential.\n   - Google Sheets: OAuth2 credential \u2192 `Google Sheets`.\n   - WooCommerce Trigger: credential for the WooCommerce trigger (or use a Webhook node and configure WooCommerce webhooks).\n2. Create Google Sheets with the exact column names listed above and copy the spreadsheet ID and sheet gid into the two Google Sheets nodes.\n\n\n## Notes & Warnings\n- The `If` node in this export compares `{{$json.data.exists}}` to the string `\"true\"`. If Rapiwa sometimes returns booleans, normalize the value (e.g., `String($json.data.exists) === 'true'`) in a Code node before the IF.\n- Some Google Sheets mappings include keys like `delivery status` or trailing-space `status ` \u2014 ensure column names in the sheet exactly match the node mapping (trim trailing spaces).\n- Message templates reference `products[0]` \u2014 adapt if orders commonly contain multiple items.\n- Keep all API keys and tokens in n8n credentials; never hard-code secrets inside nodes.\n- Start tests with a very small batch to avoid accidental mass messaging and to respect Rapiwa rate limits.\n\n## Useful Links\n- **Dashboard:** [https://app.rapiwa.com](https://app.rapiwa.com/login)\n- **Official Website:** [https://rapiwa.com](https://rapiwa.com/)\n- **Documentation:** [https://docs.rapiwa.com](https://docs.rapiwa.com/)\n\n## Support & Help\n- **WhatsApp**: [Chat on WhatsApp](https://wa.me/8801322827799)\n- **Discord**: [SpaGreen Community](https://discord.gg/SsCChWEP)\n- **Facebook Group**: [SpaGreen Support](https://www.facebook.com/groups/spagreenbd)\n- **Website**: [https://spagreen.net](https://spagreen.net)\n- **Developer Portfolio**: [Codecanyon SpaGreen](https://codecanyon.net/user/spagreen/portfolio)\n "
      },
      "typeVersion": 1
    },
    {
      "id": "643d4ac7-f4bc-41ed-9c99-6187c780abdb",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1280,
        640
      ],
      "parameters": {
        "width": 448,
        "height": 560,
        "content": "## WooCommerce Trigger\n- Purpose: Receives incoming HTTP POST payloads from WooCommerce Trigger\n\n## Order Completed check (Code)\n- Purpose: Filter events and normalize payload into a compact `data` object."
      },
      "typeVersion": 1
    },
    {
      "id": "0bddd8a0-c5a9-45d8-ac3b-2a7f636244d3",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -608,
        640
      ],
      "parameters": {
        "width": 544,
        "height": 560,
        "content": "## Clean WhatsApp Number (Code)\n- Purpose: Ensure the `number` field exists and strip all non-digit characters.\n\n\n## Check valid whatsapp number Using Rapiwa (HTTP Request)\n- Purpose: Verify whether the phone number is registered on WhatsApp.\n- Authentication: RAPIWA Bearer (credential: `Rapiwa Bearer Auth`)"
      },
      "typeVersion": 1
    },
    {
      "id": "fc9e8191-cdbd-479d-aae2-c28bf6012920",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -32,
        208
      ],
      "parameters": {
        "width": 720,
        "height": 992,
        "content": "## If\n- Purpose: Branch the flow depending on Rapiwa verification.\n- True branch: send message (`Send Message Using Rapiwa`).\n- False branch: append to unverified sheet (`Save State of Rows in Unerified & Not sent`).\n\n\n## Send Message Using Rapiwa (HTTP Request)\n- Purpose: Send a templated WhatsApp message to the verified number.\n- Rapiwa:\n  - Method: POST\n  - Body parameters (selected):\n    - `number`: `={{ $json.data.number }}`\n    - `message_type`: `text`\n    - `message`: Hi, this is a text message.\n\n\n## Save State of Rows in Verified & Sent (Google Sheets)\n- **A Google Sheet formatted like this** \u27a4 [sample](https://docs.google.com/spreadsheets/d/1vxocktoY-y-PYBZNxmUDuQv02b5F8QKhbQ0yLHjwjBY/edit?usp=sharing)\n- Purpose: Append one row per successful send to the Google Sheet.\n\n\n## Save State of Rows in Unerified & Not sent (Google Sheets)\n- Purpose: Append a row when a number is not verified and message is not sent.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "c7ada026-0c4f-43f3-9409-174e6be7ae57",
      "name": "WooCommerce Trigger",
      "type": "n8n-nodes-base.wooCommerceTrigger",
      "position": [
        -1200,
        864
      ],
      "parameters": {
        "event": "order.updated"
      },
      "credentials": {
        "wooCommerceApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "6fa57d94-c9f3-4393-9bb0-7eaafda21dd6",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1280,
        352
      ],
      "parameters": {
        "color": 7,
        "width": 1216,
        "height": 272,
        "content": "# This Workflow Summary\n- Trigger: `WooCommerce Trigger` receives WooCommerce order events \n- Pre-filter & Map: `Order Completed check` (Code) filters for `status === 'completed'` and maps the payload into `{ data: { customer, products, invoice_link } }`.\n- Batch: `Loop Over Items` (SplitInBatches) iterates product items to avoid mass concurrent sends.\n- Normalize number: `Clean WhatsApp Number` (Code) strips non-digits and ensures `number` is a string.\n- Verify: `Check valid whatsapp number Using Rapiwa` (RAPIWA) calls `POST https://app.rapiwa.com/api/verify-whatsapp` with the number.\n- Branch: `If` node checks the verification response (`{{$json.data.exists}}` === `\"true\"`) and routes to send or log nodes.\n- Send: `Send Message Using Rapiwa` (HTTP Request) posts a templated text message to `POST https://app.rapiwa.com/api/send-message`.\n- Logging: `Save State of Rows in Verified & Sent` and `Save State of Rows in Unerified & Not sent` append rows to Google Sheets with mapped columns.\n- Throttle / loop: `Wait` delays and returns to `Loop Over Items`."
      },
      "typeVersion": 1
    },
    {
      "id": "0deb4de9-a50a-4bf4-928b-e241f93e5947",
      "name": "Rapiwa",
      "type": "n8n-nodes-rapiwa.rapiwa",
      "position": [
        -256,
        880
      ],
      "parameters": {
        "number": "={{ $json.data.customer.phone }}",
        "operation": "verifyWhatsAppNumber"
      },
      "credentials": {
        "rapiwaApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "ee69cc81-edc5-4fb8-9144-cb5d30a8fcc7",
      "name": "Rapiwa (send message)",
      "type": "n8n-nodes-rapiwa.rapiwa",
      "position": [
        288,
        752
      ],
      "parameters": {
        "number": "={{ $json.data.number }}",
        "messageType": "=Hi *{{ $('Clean WhatsApp Number').item.json.data.customer.first_name }} {{ $('Clean WhatsApp Number').item.json.data.customer.last_name }}*,\n\nYour order is currently: *{{ $('Clean WhatsApp Number').item.json.data.products[0].status }}*\n\nYour order has been successfully delivered!\n\nWe\u2019d love to hear your thoughts.\nPlease take a moment to leave a review \u2014 your feedback helps us grow and improve!\n\nThanks for shopping with *SpaGreen Creative*!  \nLet us know if you need anything."
      },
      "credentials": {
        "rapiwaApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "If": {
      "main": [
        [
          {
            "node": "Rapiwa (send message)",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Save State of Rows in Unerified & Not sent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Rapiwa": {
      "main": [
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [],
        [
          {
            "node": "Clean WhatsApp Number",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "WooCommerce Trigger": {
      "main": [
        [
          {
            "node": "Order Completed check",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Clean WhatsApp Number": {
      "main": [
        [
          {
            "node": "Rapiwa",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Order Completed check": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Rapiwa (send message)": {
      "main": [
        [
          {
            "node": "Save State of Rows in Verified & Sent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save State of Rows in Verified & Sent": {
      "main": [
        [
          {
            "node": "Wait",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save State of Rows in Unerified & Not sent": {
      "main": [
        [
          {
            "node": "Wait",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}