{
  "id": "0MxmpAAh0NhjkYW2",
  "name": "Turn Shopify orders into personalized upsell photos with Dreem.ai",
  "tags": [],
  "nodes": [
    {
      "id": "a5eff233-84b0-40a7-b299-753851c9a63a",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        0,
        0
      ],
      "parameters": {
        "width": 480,
        "height": 864,
        "content": "## Turn Shopify orders into personalized upsell photos with Dreem.ai\n\n### How it works\n\nThis workflow starts when a new Shopify order is placed, retrieves the purchased item, and pulls the store catalog. It selects the newest arrival as an upsell pairing, sends the purchased item and selected product to Dreem.ai to generate a personalized paired-look image, then waits for the render result. Once checked, it posts either the completed pairing or a timeout notification to Slack.\n\n### Setup steps\n\n- Connect and authorize the Shopify trigger and Shopify nodes with the correct store credentials and permissions to read orders, products, and catalog data.\n- Configure the Dreem.ai node with the required API credentials and generation settings for the paired-look render.\n- Set the Slack credentials, target channel, and message templates for both successful delivery and timeout alerts.\n- Review the custom code in \u201cPick Newest Arrival\u201d to ensure it matches the catalog fields and sorting logic used by the Shopify store.\n\n### Customization\n\nAdjust the product-selection logic to recommend items by category, inventory, margin, or customer history instead of simply choosing the newest arrival. The wait duration, completion condition, Dreem.ai prompt/settings, and Slack message content can also be tuned."
      },
      "typeVersion": 1
    },
    {
      "id": "2872aebd-5bb6-4524-aa7a-4de7cf62d5ac",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        560,
        192
      ],
      "parameters": {
        "color": 7,
        "width": 640,
        "height": 336,
        "content": "## Capture Shopify order\n\nStarts from a new Shopify order and gathers the purchased product plus catalog data needed for the upsell recommendation. These nodes form the left-side Shopify intake cluster."
      },
      "typeVersion": 1
    },
    {
      "id": "414cd85b-422c-4399-bcbf-e06b87849e3d",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1232,
        160
      ],
      "parameters": {
        "color": 7,
        "width": 400,
        "height": 368,
        "content": "## Select and generate look\n\nChooses the newest catalog arrival and sends it with the purchased item to Dreem.ai to create a personalized paired-look image. This is the central recommendation and image-generation cluster."
      },
      "typeVersion": 1
    },
    {
      "id": "cce70909-4302-4249-931b-05ecbd4092b4",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1664,
        160
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 368,
        "content": "## Wait and check render\n\nPauses for Dreem.ai rendering and evaluates whether the generated image is complete before routing to the appropriate outcome. These nodes sit together as the render-status decision cluster."
      },
      "typeVersion": 1
    },
    {
      "id": "a283bc74-74a9-43e8-b0b8-d3abe797e9c7",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2112,
        0
      ],
      "parameters": {
        "color": 7,
        "height": 672,
        "content": "## Notify Slack outcome\n\nSends the final Slack notification, either delivering the completed paired-look image or reporting that the render timed out. The two Slack endpoints form the right-side output cluster."
      },
      "typeVersion": 1
    },
    {
      "id": "9b947bdf-8018-4325-8e6a-6dd9629205d7",
      "name": "When New Order Placed",
      "type": "n8n-nodes-base.shopifyTrigger",
      "position": [
        608,
        368
      ],
      "parameters": {
        "topic": "orders/create",
        "authentication": "accessToken"
      },
      "typeVersion": 1
    },
    {
      "id": "71be3c2b-066d-4437-a5c1-173c1cd0d401",
      "name": "Retrieve Purchased Item Details",
      "type": "n8n-nodes-base.shopify",
      "position": [
        832,
        368
      ],
      "parameters": {
        "resource": "product",
        "operation": "get",
        "productId": "={{ $json.line_items[0].product_id }}",
        "authentication": "accessToken",
        "additionalFields": {}
      },
      "typeVersion": 1
    },
    {
      "id": "7586cb38-2320-4fc9-83ae-e165c38facef",
      "name": "Fetch Product Catalog",
      "type": "n8n-nodes-base.shopify",
      "position": [
        1056,
        368
      ],
      "parameters": {
        "resource": "product",
        "operation": "getAll",
        "returnAll": true,
        "authentication": "accessToken",
        "additionalFields": {}
      },
      "executeOnce": true,
      "typeVersion": 1
    },
    {
      "id": "9b4ece18-0247-464e-af08-cd23dcc19453",
      "name": "Select Latest Product",
      "type": "n8n-nodes-base.code",
      "position": [
        1280,
        368
      ],
      "parameters": {
        "jsCode": "const purchased = $('Retrieve Purchased Item Details').first().json;\nconst order = $('When New Order Placed').first().json;\nconst arrival = $('Fetch Product Catalog').all()\n  .map(i => i.json)\n  .filter(p => p.id !== purchased.id && (p.images || []).length > 0)\n  .sort((a, b) => new Date(b.created_at) - new Date(a.created_at))[0];\nif (!arrival) return [];\nreturn [{ json: {\n  customerEmail: order.email || 'unknown',\n  purchasedTitle: purchased.title,\n  purchasedImage: (purchased.images || [])[0]?.src,\n  arrivalTitle: arrival.title,\n  arrivalImage: arrival.images[0].src\n} }];"
      },
      "typeVersion": 2
    },
    {
      "id": "47e26788-517b-4c9a-968a-34288371fce9",
      "name": "Await Image Rendering",
      "type": "n8n-nodes-base.wait",
      "position": [
        1712,
        368
      ],
      "parameters": {
        "resume": "webhook",
        "options": {},
        "httpMethod": "POST",
        "resumeUnit": "minutes",
        "resumeAmount": 20,
        "limitWaitTime": true
      },
      "typeVersion": 1.1
    },
    {
      "id": "fb599a71-90d8-4bb5-8482-d364361f5e8c",
      "name": "Check Render Completion",
      "type": "n8n-nodes-base.if",
      "position": [
        1936,
        368
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.body?.status ?? $json.status }}",
              "rightValue": "completed"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "0d968f7c-d410-44ec-93c0-0286057629a0",
      "name": "Send Pairing to Slack",
      "type": "n8n-nodes-base.slack",
      "position": [
        2160,
        272
      ],
      "parameters": {
        "text": "=:dress: *Your Closet pairing* for {{ $('Select Latest Product').item.json.customerEmail }}\nOwns: {{ $('Select Latest Product').item.json.purchasedTitle }} \u00b7 New arrival: {{ $('Select Latest Product').item.json.arrivalTitle }}\nStyled together: {{ $('Await Image Rendering').item.json.body.outputs[0].files[0].url }}\nDrop it in the post-purchase email.",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "typeVersion": 2.5
    },
    {
      "id": "3401fd64-0273-41da-bc01-72f937f5d8ef",
      "name": "Notify Render Timeout",
      "type": "n8n-nodes-base.slack",
      "position": [
        2160,
        512
      ],
      "parameters": {
        "text": "Your Closet pairing render timed out (or the paired-look request was rejected).",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "typeVersion": 2.5
    },
    {
      "id": "c53e0df7-a24c-4f0e-a990-75af6259572c",
      "name": "Generate Upsell Image with Dreem",
      "type": "n8n-nodes-dreem.dreem",
      "position": [
        1488,
        368
      ],
      "parameters": {
        "talentId": "b2c80190-4a00-4718-9d3f-c531472d5984",
        "shotCodes": [
          "model_front_women"
        ],
        "callbackUrl": "={{ $execution.resumeUrl }}",
        "outputFormat": "jpeg",
        "frontImageUrl": "={{ $json.arrivalImage }}",
        "authentication": "apiKey",
        "stylingImageUrls": {
          "imageValues": [
            {
              "url": "={{ $json.purchasedImage }}"
            }
          ]
        },
        "outputAspectRatio": 5
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "executionOrder": "v1"
  },
  "versionId": "25ebec0a-a65e-46f5-a804-8ed01ba58074",
  "nodeGroups": [],
  "connections": {
    "Await Image Rendering": {
      "main": [
        [
          {
            "node": "Check Render Completion",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Product Catalog": {
      "main": [
        [
          {
            "node": "Select Latest Product",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Select Latest Product": {
      "main": [
        [
          {
            "node": "Generate Upsell Image with Dreem",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When New Order Placed": {
      "main": [
        [
          {
            "node": "Retrieve Purchased Item Details",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Render Completion": {
      "main": [
        [
          {
            "node": "Send Pairing to Slack",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Notify Render Timeout",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Retrieve Purchased Item Details": {
      "main": [
        [
          {
            "node": "Fetch Product Catalog",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Upsell Image with Dreem": {
      "main": [
        [
          {
            "node": "Await Image Rendering",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}