Meetup参加者登録と抽選アプリ
中級
これはMiscellaneous分野の自動化ワークフローで、12個のノードを含みます。主にSet, Code, Form, Webhook, Postgresなどのノードを使用。 PostgreSQLデータベースに基づくMeetup登録システムとインタラクティブな抽選ツール
前提条件
- •HTTP Webhookエンドポイント(n8nが自動生成)
- •PostgreSQLデータベース接続情報
カテゴリー
ワークフロープレビュー
ノード接続関係を可視化、ズームとパンをサポート
ワークフローをエクスポート
以下のJSON設定をn8nにインポートして、このワークフローを使用できます
{
"id": "B1Tn4E0X4IfTUiHw",
"meta": {
"instanceId": "43905f7eef4dcd9dab6e186fbccfa78b0e88a07b5e6c19ebd17391441f834f49",
"templateCredsSetupCompleted": true
},
"name": "Meetup Participant Registration & Giveaway App",
"tags": [],
"nodes": [
{
"id": "76bd011c-3ace-4094-8fa0-bac818192d9a",
"name": "サンクス画面",
"type": "n8n-nodes-base.form",
"position": [
620,
600
],
"webhookId": "b33ea633-f82b-4e16-b71f-5075fae13cdc",
"parameters": {
"options": {
"customCss": ":root {\n\t--font-family: 'Inter', sans-serif;\n\t--font-weight-normal: 400;\n\t--font-weight-bold: 700;\n\t--font-size-body: 14px;\n\t--font-size-label: 16px;\n\t--font-size-header: 24px;\n\t--font-size-input: 16px;\n\t--font-size-error: 12px;\n\n\t/* Purple Themed Colors */\n\t--color-background: #f5f3ff; /* soft lavender */\n\t--color-card-bg: #ffffff;\n\t--color-card-border: #e0d7f8;\n\t--color-card-shadow: rgba(103, 80, 164, 0.12);\n\t--color-header: #3c1e74;\n\t--color-label: #4c1d95;\n\t--color-input-text: #1f1b2e;\n\t--color-input-border: #c4b5fd;\n\t--color-focus-border: #7c3aed;\n\t--color-submit-btn-bg: #7c3aed;\n\t--color-submit-btn-bg-hover: #6d28d9;\n\t--color-submit-btn-text: #ffffff;\n\t--color-error: #dc2626;\n\t--color-required: #dc2626;\n\t--color-test-notice-text: #7e22ce;\n\t--color-test-notice-bg: #f3e8ff;\n\t--color-test-notice-border: #e9d5ff;\n\n\t--border-radius-card: 12px;\n\t--border-radius-input: 8px;\n\t--submit-btn-height: 52px;\n\n\t--padding-card: 32px;\n\t--padding-form-input: 14px;\n\t--box-shadow-card: 0 8px 24px rgba(103, 80, 164, 0.15);\n}\n\n/* Body Background */\nbody {\n\tbackground-color: var(--color-background);\n\tfont-family: var(--font-family);\n\tmargin: 0;\n\tpadding: 0;\n\tcolor: var(--color-input-text);\n}\n\n/* Form Container Card */\n.card {\n\tmax-width: 480px;\n\tmargin: 40px auto;\n\tbackground-color: var(--color-card-bg);\n\tborder-radius: var(--border-radius-card);\n\tbox-shadow: var(--box-shadow-card);\n\tpadding: var(--padding-card);\n\tborder: 1px solid var(--color-card-border);\n}\n\n/* Header */\n.card h1 {\n\tfont-size: var(--font-size-header);\n\tfont-weight: var(--font-weight-bold);\n\tcolor: var(--color-header);\n\tmargin-bottom: 24px;\n\ttext-align: center;\n}\n\n/* Test Notice */\n.test-notice {\n\tbackground-color: var(--color-test-notice-bg);\n\tcolor: var(--color-test-notice-text);\n\tborder: 1px solid var(--color-test-notice-border);\n\tborder-radius: 6px;\n\tpadding: 12px 16px;\n\tfont-size: 14px;\n\tmargin-bottom: 24px;\n}\n\n/* Label */\nlabel {\n\tdisplay: block;\n\tfont-size: var(--font-size-label);\n\tfont-weight: var(--font-weight-bold);\n\tcolor: var(--color-label);\n\tmargin-bottom: 8px;\n}\n\n/* Input Field */\ninput[type=\"text\"], input[type=\"email\"] {\n\twidth: 100%;\n\tpadding: var(--padding-form-input);\n\tborder: 1px solid var(--color-input-border);\n\tborder-radius: var(--border-radius-input);\n\tfont-size: var(--font-size-input);\n\tcolor: var(--color-input-text);\n\tbox-sizing: border-box;\n\ttransition: border-color 0.2s ease;\n}\n\ninput[type=\"text\"]:focus, input[type=\"email\"]:focus {\n\tborder-color: var(--color-focus-border);\n\toutline: none;\n}\n\n/* Error Message */\n.error {\n\tcolor: var(--color-error);\n\tfont-size: var(--font-size-error);\n\tmargin-top: 6px;\n}\n\n/* Submit Button */\nbutton[type=\"submit\"] {\n\twidth: 100%;\n\theight: var(--submit-btn-height);\n\tbackground-color: var(--color-submit-btn-bg);\n\tcolor: var(--color-submit-btn-text);\n\tfont-weight: var(--font-weight-bold);\n\tfont-size: 16px;\n\tborder: none;\n\tborder-radius: 10px;\n\tcursor: pointer;\n\ttransition: background-color 0.2s ease;\n}\n\nbutton[type=\"submit\"]:hover {\n\tbackground-color: var(--color-submit-btn-bg-hover);\n}\n\n/* Required Asterisk */\nlabel .required {\n\tcolor: var(--color-required);\n\tmargin-left: 4px;\n}\n"
},
"operation": "completion",
"completionTitle": "Glad You're Here!",
"completionMessage": "Thank you for being part of our meetup. Don’t miss the giveaway at the end of the session!"
},
"typeVersion": 1
},
{
"id": "dc0a7158-2b27-4a83-8fc0-e826ce425b7f",
"name": "参加者リストのフォーマット",
"type": "n8n-nodes-base.code",
"position": [
420,
1140
],
"parameters": {
"jsCode": "// Loop over input items and add a new field called 'myNewField' to the JSON of each one\nvar list = $input.all();\n\nfunction base64Encode(originalString) {\n // Create a Buffer from the string\n const buffer = Buffer.from(originalString, 'utf8');\n // Convert the Buffer to a Base64 string\n const encodedString = buffer.toString('base64');\n return encodedString;\n}\nfunction redactWhatsapp(number) {\n if (!number || number.length < 7) return number; // too short to redact safely\n const start = number.slice(0, 4);\n const end = number.slice(-4);\n return `${start}****${end}`;\n}\nvar newList = list.map((row)=> {\n var data = row.json\n var name = data.nama_lengkap\n var whatsapp = redactWhatsapp(data.whatsapp)\n var label = name + ' (' +whatsapp+')'\n return label;\n})\n\nreturn {names: newList}"
},
"typeVersion": 2
},
{
"id": "7fba3d0f-8c7b-4f19-8954-9b8ab7a6d95b",
"name": "フォームからデータベースへのマッピング",
"type": "n8n-nodes-base.set",
"position": [
180,
600
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "8d91a9a0-84fa-47c6-a8b9-31b21bb25ab0",
"name": "nama_lengkap",
"type": "string",
"value": "={{ $json['Nama Lengkap'] }}"
},
{
"id": "3459b5c2-0c65-4684-a7f7-bcdb2aece4d5",
"name": "discord_username",
"type": "string",
"value": "={{ $json['Discord Username (yang join di discord channel)'] }}"
},
{
"id": "59ac4d04-3dee-4ccb-bd08-351f5529bd6b",
"name": "domisili_kota",
"type": "string",
"value": "={{ $json['Domisili (Kota)'] }}"
},
{
"id": "c0ac2b89-4d7b-4e79-87de-c7f58efcba1f",
"name": "bio",
"type": "string",
"value": "={{ $json['Bio (pekerjaan, specialty, dsb)'] }}"
},
{
"id": "7460a976-89e9-4d9c-8680-74ac823a6aca",
"name": "email",
"type": "string",
"value": "={{ $json.Email }}"
},
{
"id": "9018f12d-2aaf-4e9c-941c-9db53da5e83c",
"name": "whatsapp",
"type": "string",
"value": "={{ $json.Whatsapp }}"
},
{
"id": "483859a7-add4-46e5-a39d-d9199c86e59b",
"name": "threads_username",
"type": "string",
"value": "={{ $json['Threads Username'] }}"
},
{
"id": "9717df91-b9f1-4098-8eb3-6c97dfede3d7",
"name": "instagram_username",
"type": "string",
"value": "={{ $json['Instagram Username'] }}"
},
{
"id": "0d2fb350-61ec-4822-8dc5-c3ab9a20ce1c",
"name": "created_at",
"type": "string",
"value": "={{ $json.submittedAt }}"
},
{
"id": "32b9a3fa-0ef7-4a84-9adb-df25d112d4af",
"name": "event",
"type": "string",
"value": "={{ $json.Event }}"
},
{
"id": "8e2be506-a19b-4c0d-97c4-1fa73fe1546e",
"name": "id",
"type": "string",
"value": "={{ $json.Event }}--{{ $json.Whatsapp }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "6d66e53e-147c-42a8-a742-349901287c96",
"name": "全参加者の取得",
"type": "n8n-nodes-base.postgres",
"position": [
200,
1140
],
"parameters": {
"table": {
"__rl": true,
"mode": "list",
"value": "n8n_meetup_participants",
"cachedResultName": "n8n_meetup_participants"
},
"where": {
"values": [
{
"value": "Meetup #2",
"column": "event"
}
]
},
"schema": {
"__rl": true,
"mode": "list",
"value": "public"
},
"options": {},
"operation": "select",
"returnAll": true
},
"credentials": {
"postgres": {
"id": "irlIPHqjhjs13ldK",
"name": "Neon N8N Community Indonesia"
}
},
"typeVersion": 2.6
},
{
"id": "8478dcf5-7e9c-471e-b7db-d7b601f4fd58",
"name": "Giveaway App",
"type": "n8n-nodes-base.webhook",
"position": [
-20,
1140
],
"webhookId": "6706b347-20f6-41cc-a17c-7afb747d4f24",
"parameters": {
"path": "giveaway",
"options": {},
"responseMode": "responseNode"
},
"typeVersion": 2
},
{
"id": "0df6e338-46ee-42fc-b2b8-4986e167f271",
"name": "Giveaway Appへの応答",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
620,
1140
],
"parameters": {
"options": {},
"respondWith": "text",
"responseBody": "=<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"/>\n <title>n8n Meetup Name Picker</title>\n <style>\n body {\n font-family: 'Inter', sans-serif;\n background-color: #f5f3ff;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n min-height: 100vh;\n justify-content: center;\n }\n\n .container {\n background-color: #ffffff;\n border-radius: 12px;\n padding: 32px;\n max-width: 500px;\n width: 100%;\n box-shadow: 0 8px 24px rgba(103, 80, 164, 0.15);\n text-align: center;\n }\n\n h1 {\n color: #4c1d95;\n margin-bottom: 24px;\n }\n\n textarea {\n width: 100%;\n height: 150px;\n border: 1px solid #c4b5fd;\n border-radius: 8px;\n padding: 12px 20px 12px 16px;\n font-family: 'Inter', sans-serif;\n box-sizing: border-box;\n font-size: 14px;\n margin-bottom: 16px;\n resize: none;\n }\n\n input[type=\"number\"] {\n width: 60px;\n padding: 8px;\n margin: 8px 0;\n border-radius: 6px;\n border: 1px solid #c4b5fd;\n text-align: center;\n }\n\n button {\n background-color: #7c3aed;\n color: white;\n border: none;\n padding: 12px 24px;\n border-radius: 8px;\n font-size: 16px;\n cursor: pointer;\n margin-top: 12px;\n }\n\n button:hover {\n background-color: #6d28d9;\n }\n\n .results {\n margin-top: 24px;\n font-size: 18px;\n color: #1f1b2e;\n }\n\n .results li {\n margin: 4px 0;\n }\n </style>\n</head>\n<body>\n <div class=\"container\">\n <h1>🎉 Giveaway <br/> N8N ID Meetup #2</h1>\n <div id=\"formSection\">\n <p>Paste the list of attendee names below (one per line):</p>\n <textarea id=\"nameInput\" placeholder=\"e.g. John Doe Jane Smith Andi Prasetyo\"></textarea>\n <p>Select how many names to pick:</p>\n <input type=\"number\" id=\"countInput\" value=\"5\" min=\"1\" />\n <br />\n <button onclick=\"pickNames()\">Pick Random Name(s)</button>\n </div>\n <div id=\"rollingSection\" style=\"display:none; margin-top:32px; text-align:center;\">\n <div id=\"rollingNames\" style=\"font-size:2rem; color:#7c3aed; min-height:2.5em; font-weight:bold;\"></div>\n <div id=\"rollingCount\" style=\"margin-top:8px; color:#6d28d9;\"></div>\n <button id=\"backButton\" style=\"display:none; margin-top:24px; background:#e0e7ff; color:#4c1d95; border:none; padding:10px 24px; border-radius:8px; font-size:15px; cursor:pointer;\" onclick=\"backToInput()\">Back to Input</button>\n </div>\n </div>\n\n <script src=\"https://cdn.jsdelivr.net/npm/canvas-confetti@1.6.0/dist/confetti.browser.min.js\"></script>\n\n <script>\n // Daftar nama peserta (bisa diubah sesuai kebutuhan)\n const predefinedNames = {{ JSON.stringify($json.names) }}\n\n // Isi textarea dengan daftar nama saat halaman dimuat\n window.onload = function() {\n document.getElementById('nameInput').value = predefinedNames.join('\\n');\n };\n\n function pickNames() {\n const input = document.getElementById('nameInput').value.trim();\n const count = parseInt(document.getElementById('countInput').value);\n const resultsList = document.getElementById('resultsList');\n const formSection = document.getElementById('formSection');\n const rollingSection = document.getElementById('rollingSection');\n const rollingNames = document.getElementById('rollingNames');\n const rollingCount = document.getElementById('rollingCount');\n\n if (!input) {\n alert('Please enter at least one name.');\n return;\n }\n\n const names = input.split('\\n').map(name => name.trim()).filter(name => name !== '');\n\n if (count > names.length) {\n alert('Not enough names to pick from.');\n return;\n }\n\n // Sembunyikan form, tampilkan rolling\n formSection.style.display = 'none';\n rollingSection.style.display = 'block';\n\n // Rolling animation\n let rollingInterval;\n let rollingDuration = 2000; // ms\n let rollingSpeed = 60; // ms\n let rollingNamesArr = [];\n let rollingStep = 0;\n\n if (count === 1) {\n // Rolling satu nama\n rollingInterval = setInterval(() => {\n const randomName = names[Math.floor(Math.random() * names.length)];\n rollingNames.textContent = randomName;\n }, rollingSpeed);\n } else {\n // Rolling beberapa nama sekaligus\n rollingInterval = setInterval(() => {\n rollingNamesArr = [];\n let tempNames = [...names];\n for (let i = 0; i < count; i++) {\n if (tempNames.length === 0) break;\n const idx = Math.floor(Math.random() * tempNames.length);\n rollingNamesArr.push(tempNames[idx]);\n tempNames.splice(idx, 1);\n }\n rollingNames.innerHTML = rollingNamesArr.map(n => `<div>${n}</div>`).join('');\n }, rollingSpeed);\n }\n rollingCount.textContent = 'Picking winner...';\n\n setTimeout(() => {\n clearInterval(rollingInterval);\n // Pilih pemenang sebenarnya\n const shuffled = names.sort(() => 0.5 - Math.random());\n const selected = shuffled.slice(0, count);\n rollingNames.innerHTML = selected.map(n => `<div style=\\\"color:#22c55e;\\\">${n}</div>`).join('');\n rollingCount.textContent = 'Winner' + (count > 1 ? 's' : '') + ' 🎉';\n\n // Tampilkan confetti\n confetti({\n particleCount: 120,\n spread: 90,\n origin: { y: 0.6 }\n });\n\n document.getElementById('backButton').style.display = 'inline-block';\n }, rollingDuration);\n }\n\n function backToInput() {\n document.getElementById('formSection').style.display = 'block';\n document.getElementById('rollingSection').style.display = 'none';\n document.getElementById('backButton').style.display = 'none';\n document.getElementById('resultsList').innerHTML = '';\n document.getElementById('rollingNames').textContent = '';\n document.getElementById('rollingCount').textContent = '';\n }\n </script>\n</body>\n</html>\n"
},
"typeVersion": 1.4
},
{
"id": "99f96a32-d847-43f7-8740-cff828d7b314",
"name": "付箋",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1500,
420
],
"parameters": {
"width": 660,
"height": 520,
"content": "# 🎉 n8n Workflow: Meetup Participant Registration & Giveaway App\n\nThis n8n workflow is designed to handle both the participant registration process and the random selection of giveaway winners via a frontend integration.\n\n## ✅ Use Case Summary\n\n- Efficiently collects and stores attendee information\n- Securely exposes a simplified participant list to the frontend\n- Prepares giveaway-ready data with privacy protection\n- Perfect for community events or randomized prize draws\n\n"
},
"typeVersion": 1
},
{
"id": "cf039ad9-01ee-4484-ae3d-d0225227da32",
"name": "参加者フォーム",
"type": "n8n-nodes-base.formTrigger",
"position": [
-40,
600
],
"webhookId": "48c80b3d-22a0-4add-9d7f-384bff7791b1",
"parameters": {
"options": {
"path": "giveaway",
"customCss": ":root {\n\t--font-family: 'Inter', sans-serif;\n\t--font-weight-normal: 400;\n\t--font-weight-bold: 700;\n\t--font-size-body: 14px;\n\t--font-size-label: 16px;\n\t--font-size-header: 24px;\n\t--font-size-input: 16px;\n\t--font-size-error: 12px;\n\n\t/* Purple Themed Colors */\n\t--color-background: #f5f3ff; /* soft lavender */\n\t--color-card-bg: #ffffff;\n\t--color-card-border: #e0d7f8;\n\t--color-card-shadow: rgba(103, 80, 164, 0.12);\n\t--color-header: #3c1e74;\n\t--color-label: #4c1d95;\n\t--color-input-text: #1f1b2e;\n\t--color-input-border: #c4b5fd;\n\t--color-focus-border: #7c3aed;\n\t--color-submit-btn-bg: #7c3aed;\n\t--color-submit-btn-bg-hover: #6d28d9;\n\t--color-submit-btn-text: #ffffff;\n\t--color-error: #dc2626;\n\t--color-required: #dc2626;\n\t--color-test-notice-text: #7e22ce;\n\t--color-test-notice-bg: #f3e8ff;\n\t--color-test-notice-border: #e9d5ff;\n\n\t--border-radius-card: 12px;\n\t--border-radius-input: 8px;\n\t--submit-btn-height: 52px;\n\n\t--padding-card: 32px;\n\t--padding-form-input: 14px;\n\t--box-shadow-card: 0 8px 24px rgba(103, 80, 164, 0.15);\n}\n\n/* Body Background */\nbody {\n\tbackground-color: var(--color-background);\n\tfont-family: var(--font-family);\n\tmargin: 0;\n\tpadding: 0;\n\tcolor: var(--color-input-text);\n}\n\n/* Form Container Card */\n.card {\n\tmax-width: 480px;\n\tmargin: 40px auto;\n\tbackground-color: var(--color-card-bg);\n\tborder-radius: var(--border-radius-card);\n\tbox-shadow: var(--box-shadow-card);\n\tpadding: var(--padding-card);\n\tborder: 1px solid var(--color-card-border);\n}\n\n/* Header */\n.card h1 {\n\tfont-size: var(--font-size-header);\n\tfont-weight: var(--font-weight-bold);\n\tcolor: var(--color-header);\n\tmargin-bottom: 24px;\n\ttext-align: center;\n}\n\n/* Test Notice */\n.test-notice {\n\tbackground-color: var(--color-test-notice-bg);\n\tcolor: var(--color-test-notice-text);\n\tborder: 1px solid var(--color-test-notice-border);\n\tborder-radius: 6px;\n\tpadding: 12px 16px;\n\tfont-size: 14px;\n\tmargin-bottom: 24px;\n}\n\n/* Label */\nlabel {\n\tdisplay: block;\n\tfont-size: var(--font-size-label);\n\tfont-weight: var(--font-weight-bold);\n\tcolor: var(--color-label);\n\tmargin-bottom: 8px;\n}\n\n/* Input Field */\ninput[type=\"text\"], input[type=\"email\"] {\n\twidth: 100%;\n\tpadding: var(--padding-form-input);\n\tborder: 1px solid var(--color-input-border);\n\tborder-radius: var(--border-radius-input);\n\tfont-size: var(--font-size-input);\n\tcolor: var(--color-input-text);\n\tbox-sizing: border-box;\n\ttransition: border-color 0.2s ease;\n}\n\ninput[type=\"text\"]:focus, input[type=\"email\"]:focus {\n\tborder-color: var(--color-focus-border);\n\toutline: none;\n}\n\n/* Error Message */\n.error {\n\tcolor: var(--color-error);\n\tfont-size: var(--font-size-error);\n\tmargin-top: 6px;\n}\n\n/* Submit Button */\nbutton[type=\"submit\"] {\n\twidth: 100%;\n\theight: var(--submit-btn-height);\n\tbackground-color: var(--color-submit-btn-bg);\n\tcolor: var(--color-submit-btn-text);\n\tfont-weight: var(--font-weight-bold);\n\tfont-size: 16px;\n\tborder: none;\n\tborder-radius: 10px;\n\tcursor: pointer;\n\ttransition: background-color 0.2s ease;\n}\n\nbutton[type=\"submit\"]:hover {\n\tbackground-color: var(--color-submit-btn-bg-hover);\n}\n\n/* Required Asterisk */\nlabel .required {\n\tcolor: var(--color-required);\n\tmargin-left: 4px;\n}\n",
"ignoreBots": true,
"buttonLabel": "Submit",
"appendAttribution": false
},
"formTitle": "n8n Indonesia Community Meetup #2",
"formFields": {
"values": [
{
"fieldName": "Event",
"fieldType": "hiddenField",
"fieldValue": "=Meetup #2"
},
{
"fieldLabel": "Nama Lengkap",
"requiredField": true
},
{
"fieldLabel": "Domisili (Kota)",
"requiredField": true
},
{
"fieldType": "textarea",
"fieldLabel": "Bio (pekerjaan, specialty, dsb)",
"requiredField": true
},
{
"fieldLabel": "Whatsapp",
"requiredField": true
},
{
"fieldLabel": "Discord Username (yang join di discord channel)"
},
{
"fieldLabel": "Threads Username"
},
{
"fieldLabel": "Instagram Username"
},
{
"fieldType": "email",
"fieldLabel": "Email"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "d1387478-3489-4d10-b2a0-910eda73469c",
"name": "参加者をデータベースに保存",
"type": "n8n-nodes-base.postgres",
"position": [
400,
600
],
"parameters": {
"table": {
"__rl": true,
"mode": "list",
"value": "n8n_meetup_participants",
"cachedResultName": "n8n_meetup_participants"
},
"schema": {
"__rl": true,
"mode": "list",
"value": "public"
},
"columns": {
"value": {},
"schema": [
{
"id": "id",
"type": "string",
"display": true,
"removed": false,
"required": true,
"displayName": "id",
"defaultMatch": true,
"canBeUsedToMatch": true
},
{
"id": "nama_lengkap",
"type": "string",
"display": true,
"required": true,
"displayName": "nama_lengkap",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "discord_username",
"type": "string",
"display": true,
"required": false,
"displayName": "discord_username",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "domisili_kota",
"type": "string",
"display": true,
"required": false,
"displayName": "domisili_kota",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "bio",
"type": "string",
"display": true,
"required": false,
"displayName": "bio",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "email",
"type": "string",
"display": true,
"required": false,
"displayName": "email",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "whatsapp",
"type": "string",
"display": true,
"required": false,
"displayName": "whatsapp",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "threads_username",
"type": "string",
"display": true,
"required": false,
"displayName": "threads_username",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "instagram_username",
"type": "string",
"display": true,
"required": false,
"displayName": "instagram_username",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "created_at",
"type": "dateTime",
"display": true,
"required": false,
"displayName": "created_at",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "event",
"type": "string",
"display": true,
"required": false,
"displayName": "event",
"defaultMatch": false,
"canBeUsedToMatch": false
}
],
"mappingMode": "autoMapInputData",
"matchingColumns": [
"id"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "upsert"
},
"credentials": {
"postgres": {
"id": "irlIPHqjhjs13ldK",
"name": "Neon N8N Community Indonesia"
}
},
"typeVersion": 2.6
},
{
"id": "7222a521-913f-4326-84c3-8b84e1d07735",
"name": "付箋1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-800,
420
],
"parameters": {
"color": 6,
"width": 1660,
"height": 520,
"content": "\n## 📋 Participant Registration Flow\n\nThis part of the workflow handles user submissions from a registration form.\n\n### 🔄 Steps:\n1. **📝 Participant Form**\n - Triggered when a participant submits the form.\n - Collects fields like `nama_lengkap`, `email`, `whatsapp`, `discord_username`, etc.\n\n2. **🛠️ Mapping Form to Database**\n - Manual mapping node that prepares form data for the database.\n - Can include trimming, validation, and formatting.\n\n3. **💾 Save Participant to Database**\n - Uses an *upsert* operation to insert or update records in PostgreSQL.\n - Avoids duplicate entries based on `id`.\n\n4. **✅ Thank You Screen**\n - Displays a confirmation or success message to the participant after submission.\n"
},
"typeVersion": 1
},
{
"id": "0562529e-7a41-4a25-a949-87fed3007814",
"name": "付箋2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-800,
980
],
"parameters": {
"color": 5,
"width": 1660,
"height": 480,
"content": "## 🎁 Giveaway App\n\nThis section serve frontend app to display and select random winners.\n\n### 🔄 Steps:\n1. **🌐 Webhook GET (Giveaway App)**\n - Exposes a public endpoint that delivers a ready-to-use HTML app.\n - Can be opened in a browser or projected during the event.\n\n2. **📥 Fetch Participants**\n - Executes a SQL query to retrieve all participant records from the database.\n\n3. **🧮 Format Participant Data**\n - Redacts personal details (e.g., masks WhatsApp numbers).\n - Encodes the `id` using Base64 for privacy and uniqueness.\n\n4. **📤 Render Giveaway App**\n - Returns an HTML-based Single Page Application with the participant list included.\n - Allows the host to click a button to pick random winners live."
},
"typeVersion": 1
},
{
"id": "f166d098-c4c9-470f-9bb2-afbf7e9df119",
"name": "付箋3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1500,
980
],
"parameters": {
"width": 660,
"height": 480,
"content": "# Preview\n"
},
"typeVersion": 1
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "5e3676e8-9daa-402d-bdba-994aad9b7596",
"connections": {
"8478dcf5-7e9c-471e-b7db-d7b601f4fd58": {
"main": [
[
{
"node": "6d66e53e-147c-42a8-a742-349901287c96",
"type": "main",
"index": 0
}
]
]
},
"cf039ad9-01ee-4484-ae3d-d0225227da32": {
"main": [
[
{
"node": "7fba3d0f-8c7b-4f19-8954-9b8ab7a6d95b",
"type": "main",
"index": 0
}
]
]
},
"6d66e53e-147c-42a8-a742-349901287c96": {
"main": [
[
{
"node": "dc0a7158-2b27-4a83-8fc0-e826ce425b7f",
"type": "main",
"index": 0
}
]
]
},
"dc0a7158-2b27-4a83-8fc0-e826ce425b7f": {
"main": [
[
{
"node": "0df6e338-46ee-42fc-b2b8-4986e167f271",
"type": "main",
"index": 0
}
]
]
},
"7fba3d0f-8c7b-4f19-8954-9b8ab7a6d95b": {
"main": [
[
{
"node": "d1387478-3489-4d10-b2a0-910eda73469c",
"type": "main",
"index": 0
}
]
]
},
"d1387478-3489-4d10-b2a0-910eda73469c": {
"main": [
[
{
"node": "76bd011c-3ace-4094-8fa0-bac818192d9a",
"type": "main",
"index": 0
}
]
]
}
}
}よくある質問
このワークフローの使い方は?
上記のJSON設定コードをコピーし、n8nインスタンスで新しいワークフローを作成して「JSONからインポート」を選択、設定を貼り付けて認証情報を必要に応じて変更してください。
このワークフローはどんな場面に適していますか?
中級 - その他
有料ですか?
このワークフローは完全無料です。ただし、ワークフローで使用するサードパーティサービス(OpenAI APIなど)は別途料金が発生する場合があります。
関連ワークフロー
Microsoft Teams会議分析をGPT-4.1、Outlook、Mem.aiを使用して自動化
GPT-4.1、Outlook、Mem.aiを使ってMicrosoft Teams会議の分析を自動化する
If
Set
Code
+
If
Set
Code
61 ノードWayne Simpson
人事
競合他社コンテンツギャップ分析ツール:構題マッピングの自動化
Gemini AI、Apify、Google Sheetsを使用して競合企業のコンテンツギャップを分析
If
Set
Code
+
If
Set
Code
30 ノードMychel Garzon
その他
自動化されたプレゼンテーション予約システム
Outlook カレンダーと Zoom を統合した自動化によるプレゼンテーション予約システム
If
Set
Code
+
If
Set
Code
21 ノードAureusR
その他
Groq AIとGhostGeniusを使ってLinkedInプロフィールと求人情報を比較
Groq AI と GhostGenius を使って LinkedIn プロフィールと職位説明のマッチ度を比較する
If
Set
Code
+
If
Set
Code
17 ノードStephan Koning
その他
完全予約システム
Google Calendar、勤務時間、REST API を使った完全な予約システム
If
Set
Code
+
If
Set
Code
41 ノードSean Lon
その他
AIエージェント - 短縮URLジェネレーター
GPT-4.1 およびデータストアによる短縮 URL の生成と管理
Set
Code
Html
+
Set
Code
Html
18 ノードNghia Nguyen
その他
ワークフロー情報
難易度
中級
ノード数12
カテゴリー1
ノードタイプ8
作成者
Ficky
@fickyTurning Tech & AI into Real Business Results I’ve been in software development for over 15 years, helping businesses solve real problems with smart and practical solutions. These days, I focus on automation using tools like n8n, along with custom software and AI. I enjoy making tech work for people in a way that’s clear, useful, and effective.
外部リンク
n8n.ioで表示 →
このワークフローを共有