{
  "name": "Turn customer reviews into testimonial videos with Shotstack",
  "nodes": [
    {
      "parameters": {
        "content": "## How it works\nA customer fills in a short review form. The workflow turns the answers into a 12-second vertical testimonial video and files it in a Google Sheet.\n\n1. **Review form** is hosted by n8n. Share the link with customers.\n2. **Prepare fields** trims the quote, turns the rating into a number from 1 to 5 and joins role + company.\n3. **Shotstack: Render Template** fills your saved template's merge fields.\n4. **Shotstack: Get Render Status** waits until the render is done.\n5. **Shotstack: Get Asset by Render ID** returns the permanent CDN URL.\n6. **Google Sheets** appends a row: who said it, the quote, the rating and the video URL.\n7. **Thank the customer** shows a thank-you page with the video link.",
        "height": 440,
        "width": 420
      },
      "id": "a1b2c3d4-0001-4000-8000-000000000001",
      "name": "How it works",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -1180,
        -300
      ]
    },
    {
      "parameters": {
        "content": "## Setup (about 5 minutes)\n1. **Shotstack account**: [sign up free](https://shotstack.io/?utm_source=n8n&utm_medium=template&utm_campaign=customer-review-video) and copy your **production** API key.\n2. **Template**: add the customer testimonial template from the guide to your Shotstack account (POST it to `/edit/v1/templates`), or design your own in Shotstack Studio with merge fields `QUOTE`, `NAME`, `ROLE_COMPANY`, `RATING_NUM`, `HEADLINE`, `ACCENT`. Pick it in the **Render Template** node.\n3. **Shotstack credential**: in any Shotstack node, create a *Shotstack API* credential, paste the key, set Environment to **Production**.\n4. **Google Sheets**: create a sheet with the columns `submitted_at`, `name`, `role`, `company`, `rating`, `quote`, `video_url`. Connect your Google credential and pick the sheet.\n5. Activate the workflow and share the form URL shown on the **Review form** node.\n\nRenders use credits. To try the workflow without spending any, use a sandbox key and set Environment to **Sandbox**; those renders carry a watermark.",
        "height": 460,
        "width": 420,
        "color": 4
      },
      "id": "a1b2c3d4-0002-4000-8000-000000000002",
      "name": "Setup",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -1180,
        180
      ]
    },
    {
      "parameters": {
        "content": "## Customise\n- Swap the form for a Typeform, Tally, Trustpilot or Judge.me trigger and map the same five fields in **Prepare fields**.\n- Change the accent colour in the **Render Template** node (ACCENT), or edit the template itself; the merge field names stay the same.\n- Add an OpenAI or OpenRouter node before **Prepare fields** to write a short headline from the quote and pass it as `HEADLINE`.\n- Add a Slack or email node after the sheet to tell your team, or replace the sheet with Airtable, Notion or your CMS.",
        "height": 300,
        "width": 420,
        "color": 5
      },
      "id": "a1b2c3d4-0003-4000-8000-000000000003",
      "name": "Customise",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -1180,
        680
      ]
    },
    {
      "parameters": {
        "formTitle": "Share a quick review",
        "formDescription": "Two minutes. We turn your words into a short video to say thanks.",
        "formFields": {
          "values": [
            {
              "fieldLabel": "Your review",
              "fieldType": "textarea",
              "placeholder": "What changed for you since you started using the product?",
              "requiredField": true
            },
            {
              "fieldLabel": "Your name",
              "placeholder": "Priya Raman",
              "requiredField": true
            },
            {
              "fieldLabel": "Your role",
              "placeholder": "Head of Marketing"
            },
            {
              "fieldLabel": "Company",
              "placeholder": "Northwind Outdoors"
            },
            {
              "fieldLabel": "Rating out of 5",
              "fieldType": "number",
              "placeholder": "5",
              "requiredField": true
            }
          ]
        },
        "options": {
          "buttonLabel": "Send review"
        }
      },
      "id": "a1b2c3d4-0004-4000-8000-000000000004",
      "name": "Review form",
      "type": "n8n-nodes-base.formTrigger",
      "typeVersion": 2.5,
      "position": [
        -700,
        200
      ],
      "webhookId": "customer-review-video"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "f1",
              "name": "quote",
              "type": "string",
              "value": "={{ ($json['Your review'] || '').toString().trim().slice(0, 220) }}"
            },
            {
              "id": "f2",
              "name": "name",
              "type": "string",
              "value": "={{ ($json['Your name'] || '').toString().trim() }}"
            },
            {
              "id": "f3",
              "name": "role_company",
              "type": "string",
              "value": "={{ [$json['Your role'], $json['Company']].filter(Boolean).join(', ') }}"
            },
            {
              "id": "f4",
              "name": "rating_num",
              "type": "string",
              "value": "={{ String(Math.min(5, Math.max(1, Math.round(Number($json['Rating out of 5']) || 5)))) }}"
            },
            {
              "id": "f5",
              "name": "headline",
              "type": "string",
              "value": "What our customers say"
            }
          ]
        },
        "options": {}
      },
      "id": "a1b2c3d4-0005-4000-8000-000000000005",
      "name": "Prepare fields",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        -460,
        200
      ]
    },
    {
      "parameters": {
        "resource": "render",
        "operation": "postTemplateRender",
        "templateId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "mergeSource": "fields",
        "merge": {
          "mergeFields": [
            {
              "find": "QUOTE",
              "replace": "={{ $json.quote }}"
            },
            {
              "find": "NAME",
              "replace": "={{ $json.name }}"
            },
            {
              "find": "ROLE_COMPANY",
              "replace": "={{ $json.role_company }}"
            },
            {
              "find": "RATING_NUM",
              "replace": "={{ $json.rating_num }}"
            },
            {
              "find": "HEADLINE",
              "replace": "={{ $json.headline }}"
            },
            {
              "find": "ACCENT",
              "replace": "#22D3EE"
            }
          ]
        }
      },
      "id": "a1b2c3d4-0006-4000-8000-000000000006",
      "name": "Shotstack: Render Template",
      "type": "@shotstack/n8n-nodes-shotstack.shotstack",
      "typeVersion": 1,
      "position": [
        -220,
        200
      ]
    },
    {
      "parameters": {
        "resource": "render",
        "operation": "getRender",
        "renderId": "={{ $json.id }}",
        "waitForCompletion": true,
        "giveUpAfter": 5
      },
      "id": "a1b2c3d4-0007-4000-8000-000000000007",
      "name": "Shotstack: Get Render Status",
      "type": "@shotstack/n8n-nodes-shotstack.shotstack",
      "typeVersion": 1,
      "position": [
        20,
        200
      ]
    },
    {
      "parameters": {
        "resource": "asset",
        "operation": "getAssetByRenderId",
        "renderId": "={{ $json.id }}"
      },
      "id": "a1b2c3d4-0008-4000-8000-000000000008",
      "name": "Shotstack: Get Asset by Render ID",
      "type": "@shotstack/n8n-nodes-shotstack.shotstack",
      "typeVersion": 1,
      "position": [
        260,
        200
      ]
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "submitted_at": "={{ $now.toISO() }}",
            "name": "={{ $('Prepare fields').item.json.name }}",
            "role": "={{ $('Review form').item.json['Your role'] || '' }}",
            "company": "={{ $('Review form').item.json['Company'] || '' }}",
            "rating": "={{ $('Review form').item.json['Rating out of 5'] }}",
            "quote": "={{ $('Prepare fields').item.json.quote }}",
            "video_url": "={{ $json.url }}"
          },
          "matchingColumns": [],
          "schema": []
        },
        "options": {}
      },
      "id": "a1b2c3d4-0009-4000-8000-000000000009",
      "name": "File the video in Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        500,
        200
      ]
    },
    {
      "parameters": {
        "operation": "completion",
        "respondWith": "text",
        "completionTitle": "Thank you!",
        "completionMessage": "=Your review is now a short video. Watch it here: {{ $('Shotstack: Get Asset by Render ID').item.json.url }}",
        "options": {}
      },
      "id": "a1b2c3d4-0010-4000-8000-000000000010",
      "name": "Thank the customer",
      "type": "n8n-nodes-base.form",
      "typeVersion": 2.5,
      "position": [
        740,
        200
      ]
    }
  ],
  "connections": {
    "Review form": {
      "main": [
        [
          {
            "node": "Prepare fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare fields": {
      "main": [
        [
          {
            "node": "Shotstack: Render Template",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Shotstack: Render Template": {
      "main": [
        [
          {
            "node": "Shotstack: Get Render Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Shotstack: Get Render Status": {
      "main": [
        [
          {
            "node": "Shotstack: Get Asset by Render ID",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Shotstack: Get Asset by Render ID": {
      "main": [
        [
          {
            "node": "File the video in Google Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "File the video in Google Sheets": {
      "main": [
        [
          {
            "node": "Thank the customer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "pinData": {},
  "meta": {
    "templateCredsSetupCompleted": false
  }
}
