{
  "nodes": [
    {
      "id": "7b0ca6c0-c156-4031-8b05-30da71580472",
      "name": "Sticky Note - Configuration",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        544,
        -96
      ],
      "parameters": {
        "color": 7,
        "width": 1084,
        "height": 632,
        "content": "## \ud83d\udccb Configure Sync Settings\n\nBefore starting, make sure to populate the following nodes with your credentials:\n\u27a1\ufe0f  MailerLite (update/create subscriber)\n\u27a1\ufe0f  Ghost (add/delete webhook)\n\u27a1\ufe0f  n8n (get/update current workflow)\n\nUse this form to configure your sync settings:\n\u2705 Set your Ghost API URL\n\u2705 Set the webhook URL (copy from Webhook node below)\n\u2705 Enable/disable member addition sync\n\u2705 Enable/disable member deletion sync\n\nThe workflow will automatically create webhooks in Ghost and remember your settings. You may need to refresh the page to get the current sync status displayed in the form."
      },
      "typeVersion": 1
    },
    {
      "id": "95b10da8-329e-4dfc-8130-5a274aedd13d",
      "name": "Sticky Note - Webhook Management",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1648,
        -96
      ],
      "parameters": {
        "color": 7,
        "width": 914,
        "height": 636,
        "content": "## \ud83d\udd17 Webhook Management\n\nThis section automatically manages Ghost webhooks based on your form settings:\n\nWhen **enabled**: Creates webhook in Ghost \u2192 Stores webhook ID in data table\nWhen **disabled**: Retrieves webhook ID \u2192 Deletes webhook from Ghost \u2192 Removes from data table\n\nWebhook IDs are stored so they can be properly removed later when unsyncing."
      },
      "typeVersion": 1
    },
    {
      "id": "66e51880-d110-4afc-9ef8-5bcaf63f10b6",
      "name": "Sticky Note - Sync Listener",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        544,
        576
      ],
      "parameters": {
        "color": 7,
        "width": 1084,
        "height": 612,
        "content": "## \ud83c\udfaf Webhook Listener to Sync in Real-Time\n\nThis webhook receives events from Ghost when members are added or deleted.\n\n**Member Added** \u2192 Creates subscriber in MailerLite\n**Member Deleted** \u2192 Unsubscribes from MailerLite\n\nEnsure this webhook URL is added to your Ghost configuration form above."
      },
      "typeVersion": 1
    },
    {
      "id": "8763a85c-77a7-46d2-93f3-23e42917b4d5",
      "name": "Sticky Note - State Persistence",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2592,
        -96
      ],
      "parameters": {
        "color": 7,
        "width": 612,
        "height": 644,
        "content": "## \ud83d\udcbe Keep Track of Current Sync Status\n\nAfter webhook changes, the workflow updates itself to remember your configuration:\n\n1\ufe0f\u20e3 Fetches current workflow\n2\ufe0f\u20e3 Updates form default values with your settings and current sync status\n3\ufe0f\u20e3 Saves the updated workflow\n\nThis makes sure the latest status of your syncs is displayed in the Sync Settings Form.  You may need to refresh your browser page if you want to see the settings update immediately after changes are made."
      },
      "typeVersion": 1
    },
    {
      "id": "0ab70058-853c-4ddd-b3c7-242d231302aa",
      "name": "Create ghost_webhooks table",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        1072,
        368
      ],
      "parameters": {
        "columns": {
          "column": [
            {
              "name": "webhook_id"
            },
            {
              "name": "event"
            }
          ]
        },
        "options": {},
        "resource": "table",
        "operation": "create",
        "tableName": "ghost_webhooks"
      },
      "typeVersion": 1.1
    },
    {
      "id": "aa87b500-55b0-4e35-ae94-978ed7c2349a",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        768,
        800
      ],
      "parameters": {
        "path": "ghost-mailerlite",
        "options": {},
        "httpMethod": "POST"
      },
      "typeVersion": 2.1
    },
    {
      "id": "55e28835-aedc-4bdd-b062-63e1001ebfe6",
      "name": "Sync Settings Form",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        592,
        256
      ],
      "parameters": {
        "options": {
          "buttonLabel": "Update Sync"
        },
        "formTitle": "Sync Settings Form",
        "formFields": {
          "values": [
            {
              "fieldLabel": "Ghost API URL"
            },
            {
              "fieldLabel": "Webhook URL"
            },
            {
              "fieldType": "radio",
              "fieldLabel": "Ghost Member Added > Added to Mailerlite",
              "defaultValue": "Disabled",
              "fieldOptions": {
                "values": [
                  {
                    "option": "Enabled"
                  },
                  {
                    "option": "Disabled"
                  }
                ]
              }
            },
            {
              "fieldType": "radio",
              "fieldLabel": "Ghost Member Removed > Removed from Mailerlite",
              "defaultValue": "Disabled",
              "fieldOptions": {
                "values": [
                  {
                    "option": "Enabled"
                  },
                  {
                    "option": "Disabled"
                  }
                ]
              }
            }
          ]
        }
      },
      "typeVersion": 2.5
    },
    {
      "id": "c2d2e2c7-b263-41b4-8ba4-5b330a41739b",
      "name": "List data tables",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        752,
        256
      ],
      "parameters": {
        "options": {},
        "resource": "table"
      },
      "typeVersion": 1.1,
      "alwaysOutputData": true
    },
    {
      "id": "d1e366f5-a757-4fb8-bfe7-ab63f131ac7c",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "position": [
        1200,
        256
      ],
      "parameters": {},
      "typeVersion": 3.2
    },
    {
      "id": "25c7087b-9aa2-4044-a2a5-95a8e98aaf50",
      "name": "Split Out",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        1488,
        256
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "webhooks"
      },
      "typeVersion": 1
    },
    {
      "id": "3cb3c30b-6ead-40cc-9ef0-adc1f92273d8",
      "name": "Check if member deleted",
      "type": "n8n-nodes-base.if",
      "position": [
        992,
        800
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "2e0a021f-b4b4-4a71-813b-cc99f6ab6847",
              "operator": {
                "type": "object",
                "operation": "empty",
                "singleValue": true
              },
              "leftValue": "={{ $json.body.member.current }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "cc4eb62e-e2bd-483c-88c4-c1f9409a9837",
      "name": "Update a subscriber",
      "type": "n8n-nodes-base.mailerLite",
      "position": [
        1216,
        704
      ],
      "parameters": {
        "operation": "update",
        "subscriberId": "={{ $json.body.member.previous.email }}",
        "additionalFields": {
          "status": "unsubscribed"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "ceb33f96-1095-4145-8e53-86f7354e97a0",
      "name": "Create a subscriber",
      "type": "n8n-nodes-base.mailerLite",
      "position": [
        1216,
        896
      ],
      "parameters": {
        "email": "={{ $('Webhook').item.json.body.member.current.email }}",
        "additionalFields": {}
      },
      "typeVersion": 2
    },
    {
      "id": "bf2dc904-e74b-41c7-9ea3-e5c8ea6171c4",
      "name": "Get webhook ID to delete",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        1904,
        320
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "event",
              "keyValue": "={{ $json.type }}"
            }
          ]
        },
        "operation": "get",
        "dataTableId": {
          "__rl": true,
          "mode": "name",
          "value": "ghost_webhooks"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "37f73744-fcb0-4407-bbbb-1aaf8f7aa171",
      "name": "Delete webhook in Ghost",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2128,
        320
      ],
      "parameters": {
        "url": "={{ $('Sync Settings Form').item.json['Ghost API URL'] }}/ghost/api/v2/admin/webhooks/{{ $json.webhook_id }}",
        "method": "DELETE",
        "options": {},
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "ghostAdminApi"
      },
      "typeVersion": 4.4
    },
    {
      "id": "d863ba71-9101-414a-948f-78bb101164a7",
      "name": "Add webhook in Ghost",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1904,
        176
      ],
      "parameters": {
        "url": "={{ $('Sync Settings Form').item.json['Ghost API URL'] }}/ghost/api/v2/admin/webhooks",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n    \"webhooks\": [{\n            \"event\": \"{{ $('Split Out').item.json.type }}\",\n            \"target_url\": \"{{ $('Sync Settings Form').item.json['Webhook URL'] }}\"\n    }]\n}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "ghostAdminApi"
      },
      "typeVersion": 4.4
    },
    {
      "id": "174371ed-2bfb-4e78-8f8e-871a2e075298",
      "name": "Store Ghost webhook ID",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        2128,
        176
      ],
      "parameters": {
        "columns": {
          "value": {
            "event": "={{ $json.webhooks[0].event }}",
            "webhook_id": "={{ $json.webhooks[0].id }}"
          },
          "schema": [
            {
              "id": "webhook_id",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "webhook_id",
              "defaultMatch": false
            },
            {
              "id": "event",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "event",
              "defaultMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {
          "optimizeBulk": false
        },
        "dataTableId": {
          "__rl": true,
          "mode": "name",
          "value": "ghost_webhooks"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "4f04a59a-8236-4cf3-8eda-ba23a51a268c",
      "name": "Forget Ghost webhook ID",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        2368,
        320
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "event",
              "keyValue": "={{ $('Split Out').item.json.type }}"
            }
          ]
        },
        "options": {},
        "operation": "deleteRows",
        "dataTableId": {
          "__rl": true,
          "mode": "name",
          "value": "ghost_webhooks"
        }
      },
      "typeVersion": 1.1,
      "alwaysOutputData": true
    },
    {
      "id": "a6fc18ff-276b-4ea7-b3f5-11a7c4fa62fa",
      "name": "Update default form values to remember webhook status",
      "type": "n8n-nodes-base.code",
      "position": [
        2832,
        240
      ],
      "parameters": {
        "jsCode": "// Loop over input items and add a new field called 'myNewField' to the JSON of each one\nfor (const item of $input.all()) {\n  item.json.settings = {executionOrder: $input.first().json.settings.executionOrder};\n  for (const nodeKey in item.json.nodes) {\n    const node = item.json.nodes[nodeKey];\n    console.log(node)\n    if (node.name === \"Sync Settings Form\" && node.parameters?.formFields?.values) {\n      for (const val of node.parameters.formFields.values) {\n        switch(val.fieldLabel) {\n          case \"Ghost API URL\":\n            val.defaultValue = $('Sync Settings Form').first().json['Ghost API URL'];\n            break;\n          case \"Webhook URL\":\n            val.defaultValue = $('Sync Settings Form').first().json['Webhook URL'];\n            break;\n          case \"Ghost Member Added > Added to Mailerlite\":\n            val.defaultValue = $('Sync Settings Form').first().json['Ghost Member Added > Added to Mailerlite'];\n            break;\n          case \"Ghost Member Removed > Removed from Mailerlite\":\n            val.defaultValue = $('Sync Settings Form').first().json['Ghost Member Removed > Removed from Mailerlite'];\n            break;\n        }\n      }\n    }\n  }\n}\n\nreturn $input.all();"
      },
      "typeVersion": 2
    },
    {
      "id": "4fbf0f71-25b4-4d25-9a84-f64cafc06270",
      "name": "Get current workflow",
      "type": "n8n-nodes-base.n8n",
      "position": [
        2656,
        240
      ],
      "parameters": {
        "operation": "get",
        "workflowId": {
          "__rl": true,
          "mode": "id",
          "value": "={{$workflow.id}}"
        },
        "requestOptions": {}
      },
      "executeOnce": true,
      "typeVersion": 1
    },
    {
      "id": "20316cd7-df3d-4641-9d82-920deef000a4",
      "name": "Update current workflow with sync status",
      "type": "n8n-nodes-base.n8n",
      "position": [
        3024,
        240
      ],
      "parameters": {
        "operation": "update",
        "workflowId": {
          "__rl": true,
          "mode": "id",
          "value": "={{$workflow.id}}"
        },
        "requestOptions": {},
        "workflowObject": "={{ $json.toJsonString() }}"
      },
      "typeVersion": 1
    },
    {
      "id": "01b26057-8667-4c26-98bf-01dda6ccbf6d",
      "name": "Check if ghost_webhooks table exists",
      "type": "n8n-nodes-base.if",
      "position": [
        912,
        256
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "31a00cad-b6b4-4318-87d7-72e6fc7f4464",
              "operator": {
                "type": "object",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json }}",
              "rightValue": ""
            }
          ]
        }
      },
      "executeOnce": true,
      "typeVersion": 2.3
    },
    {
      "id": "ed2f1b35-df02-45c8-a878-5332cc19cb91",
      "name": "If sync enabled",
      "type": "n8n-nodes-base.if",
      "position": [
        1680,
        256
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "ac8b774b-4e4e-4f31-977f-1e1d6e654826",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.action }}",
              "rightValue": "enabled"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "5093cb47-9c5f-470e-86c5-7c39ad0d0307",
      "name": "Identity syncs to be enabled/disabled",
      "type": "n8n-nodes-base.code",
      "position": [
        1344,
        256
      ],
      "parameters": {
        "jsCode": "// Loop over input items and add a new field called 'myNewField' to the JSON of each one\nfor (const item of $input.all()) {\n  item.json.webhooks = [];\n  if ($('Sync Settings Form').first().json['Ghost Member Added > Added to Mailerlite'] === 'Enabled') {\n    item.json.webhooks.push({type: 'member.added', action: 'enabled'});\n  }\n  else {\n    item.json.webhooks.push({type: 'member.added', action: 'disabled'});\n  }\n  if ($('Sync Settings Form').first().json['Ghost Member Removed > Removed from Mailerlite'] === 'Enabled') {\n    item.json.webhooks.push({type: 'member.deleted', action: 'enabled'});\n  }\n  else {\n    item.json.webhooks.push({type: 'member.deleted', action: 'disabled'});\n  }\n}\n\nreturn $input.all();"
      },
      "typeVersion": 2
    },
    {
      "id": "0199ef3d-c57c-442d-867f-6224fca7b447",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        544,
        -256
      ],
      "parameters": {
        "width": 928,
        "height": 144,
        "content": "## Sync Ghost Members with MailerLite Subscribers in Real-Time\nThis n8n workflow automatically syncs your Ghost CMS members with MailerLite subscribers in real-time using webhooks. When members join or leave your Ghost site, they're automatically added or unsubscribed from MailerLite with no manual exports, imports, or CSV files required. A simple configuration form lets you enable or disable sync settings for member additions and deletions independently."
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Merge": {
      "main": [
        [
          {
            "node": "Identity syncs to be enabled/disabled",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook": {
      "main": [
        [
          {
            "node": "Check if member deleted",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Out": {
      "main": [
        [
          {
            "node": "If sync enabled",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If sync enabled": {
      "main": [
        [
          {
            "node": "Add webhook in Ghost",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Get webhook ID to delete",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "List data tables": {
      "main": [
        [
          {
            "node": "Check if ghost_webhooks table exists",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sync Settings Form": {
      "main": [
        [
          {
            "node": "List data tables",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Add webhook in Ghost": {
      "main": [
        [
          {
            "node": "Store Ghost webhook ID",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get current workflow": {
      "main": [
        [
          {
            "node": "Update default form values to remember webhook status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Store Ghost webhook ID": {
      "main": [
        [
          {
            "node": "Get current workflow",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check if member deleted": {
      "main": [
        [
          {
            "node": "Update a subscriber",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Create a subscriber",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Delete webhook in Ghost": {
      "main": [
        [
          {
            "node": "Forget Ghost webhook ID",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Forget Ghost webhook ID": {
      "main": [
        [
          {
            "node": "Get current workflow",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get webhook ID to delete": {
      "main": [
        [
          {
            "node": "Delete webhook in Ghost",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create ghost_webhooks table": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Check if ghost_webhooks table exists": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Create ghost_webhooks table",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Identity syncs to be enabled/disabled": {
      "main": [
        [
          {
            "node": "Split Out",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update default form values to remember webhook status": {
      "main": [
        [
          {
            "node": "Update current workflow with sync status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}