{
  "name": "Turn customer reviews into Videotok UGC ads",
  "nodes": [
    {
      "parameters": {
        "content": "## Turn customer reviews into Videotok UGC ads\n\n### How it works\n\n1. Initiates the workflow manually for processing customer reviews.\n2. Sets up the review details including text, product name, and image URL.\n3. Sends the review data to OpenAI for generating a User-Generated Content (UGC) script.\n4. Prepares and posts the generated UGC script to Videotok for ad generation.\n5. Waits for the processing to complete, then fetches the status and final data.\n\n### Setup steps\n\n- [ ] Configure OpenAI API credentials in the 'Post to OpenAI for UGC Script' node\n- [ ] Configure Videotok API credentials in 'Post to Videotok API' and 'Fetch UGC Generation Status' nodes\n\n### Customization\n\nYou can change the waiting time in the 'Wait 90 Seconds' node or modify the data being set in 'Set Review Source Data'.",
        "width": 480,
        "height": 720
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [-1232, 0],
      "id": "67e818bd-fdd2-4ec9-acd1-13feb9aa0f3a",
      "name": "Sticky Note"
    },
    {
      "parameters": {
        "content": "## Initiate and set review\n\nManually starts the workflow and provides the review data for processing. Sends data to OpenAI to generate a UGC script based on customer reviews.",
        "width": 736,
        "height": 304,
        "color": 7
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [-672, 0],
      "id": "e55d1b7a-600a-4ec0-a787-b8725b5a02e9",
      "name": "Sticky Note1"
    },
    {
      "parameters": {
        "content": "## Prepare and post to Videotok\n\nBuilds the payload with the UGC script and posts it to Videotok for video generation.",
        "width": 480,
        "height": 304,
        "color": 7
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [160, 0],
      "id": "b155741d-de70-4200-a969-d6c61c5537c2",
      "name": "Sticky Note2"
    },
    {
      "parameters": {
        "content": "## Wait and fetch status\n\nPauses execution to allow for processing time and then retrieves the status of the video generation.",
        "width": 704,
        "height": 304,
        "color": 7
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [720, 0],
      "id": "5a12a004-c1d2-4e56-9410-a17795608330",
      "name": "Sticky Note3"
    },
    {
      "parameters": {},
      "id": "manual",
      "name": "When Review Starts",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [-624, 128]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "review",
              "name": "review_text",
              "type": "string",
              "value": "I bought this before a work trip and my skin looked better in three days. It is the first serum I actually finished."
            },
            {
              "id": "product",
              "name": "product_name",
              "type": "string",
              "value": "Vitamin C serum"
            },
            {
              "id": "image",
              "name": "product_image_url",
              "type": "string",
              "value": "https://example.com/product.png"
            }
          ]
        }
      },
      "id": "review-source",
      "name": "Prepare Review Data",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [-352, 128]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.openai.com/v1/responses",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=Bearer {{$vars.OPENAI_API_KEY}}"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\"model\":\"gpt-4.1-mini\",\"input\":\"Convert this customer review into compliant UGC ad JSON. Include title, hook, script, generation_prompt, caption. Preserve truthful customer language and avoid unsupported claims. Input: \" + JSON.stringify($json)}"
      },
      "id": "openai-ugc",
      "name": "Send to OpenAI for Script",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [-80, 128]
    },
    {
      "parameters": {
        "jsCode": "const review = $('Prepare Review Data').first().json;\nconst raw = $input.first().json.output_text || '{}';\nlet brief;\ntry { brief = JSON.parse(raw); } catch { brief = { title: 'UGC testimonial ad', hook: raw.slice(0, 120), script: raw, generation_prompt: raw, caption: raw.slice(0, 220) }; }\nreturn [{ json: { ...brief, product_image_url: review.product_image_url, idempotency_key: `review-ugc-${$execution.id}` } }];"
      },
      "id": "prepare",
      "name": "Create UGC Payload",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [208, 128]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://videotok.app/api/v1/generations",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=Bearer {{$vars.VIDEOTOK_API_KEY}}"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "Idempotency-Key",
              "value": "={{$json.idempotency_key}}"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\"type\":\"ugc_ad\",\"template_slug\":\"ugc-product-video\",\"prompt\":$json.generation_prompt,\"aspect_ratio\":\"9:16\",\"duration\":8,\"quality_tier\":\"high\",\"avatar_id\":$vars.VIDEOTOK_AVATAR_ID,\"brand_kit_id\":$vars.VIDEOTOK_BRAND_KIT_ID,\"reference_image_urls\":[$json.product_image_url],\"idempotency_key\":$json.idempotency_key}"
      },
      "id": "generate",
      "name": "Send to Videotok for Generation",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [496, 128]
    },
    {
      "parameters": {
        "amount": 90,
        "unit": "seconds"
      },
      "id": "wait",
      "name": "Wait 90 Seconds",
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1.1,
      "position": [768, 128]
    },
    {
      "parameters": {
        "url": "=https://videotok.app/api/v1/generations/{{$json.id || $json.generation_id}}",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=Bearer {{$vars.VIDEOTOK_API_KEY}}"
            }
          ]
        }
      },
      "id": "poll",
      "name": "Check UGC Generation Status",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [1024, 128]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "approval",
              "name": "approval_note",
              "type": "string",
              "value": "={{'Review claim compliance before publishing. Caption: ' + $('Create UGC Payload').first().json.caption}}"
            },
            {
              "id": "url",
              "name": "videotok_url",
              "type": "string",
              "value": "={{$json.url}}"
            }
          ]
        }
      },
      "id": "approval",
      "name": "Prepare Approval Data",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [1280, 128]
    }
  ],
  "connections": {
    "When Review Starts": {
      "main": [
        [
          {
            "node": "Prepare Review Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Review Data": {
      "main": [
        [
          {
            "node": "Send to OpenAI for Script",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send to OpenAI for Script": {
      "main": [
        [
          {
            "node": "Create UGC Payload",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create UGC Payload": {
      "main": [
        [
          {
            "node": "Send to Videotok for Generation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send to Videotok for Generation": {
      "main": [
        [
          {
            "node": "Wait 90 Seconds",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 90 Seconds": {
      "main": [
        [
          {
            "node": "Check UGC Generation Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check UGC Generation Status": {
      "main": [
        [
          {
            "node": "Prepare Approval Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "tags": ["videotok", "openai", "ugc", "reviews"],
  "active": false,
  "versionId": "videotok-review-to-ugc-ads-1"
}
