{"id":30348004,"url":"https://github.com/remarcable/ghost-convertkit-integration","last_synced_at":"2025-09-15T18:47:57.208Z","repository":{"id":217361379,"uuid":"743685172","full_name":"remarcable/ghost-convertkit-integration","owner":"remarcable","description":"Serverless function to integrate Ghost with ConvertKit using their APIs and webhooks","archived":false,"fork":false,"pushed_at":"2024-01-18T13:19:19.000Z","size":135,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-01-18T16:44:01.960Z","etag":null,"topics":["convertkit","convertkit-api","ghost","ghost-api","ghost-blog","integration","serverless","synchronization"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/remarcable.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2024-01-15T19:07:05.000Z","updated_at":"2024-01-15T19:07:58.000Z","dependencies_parsed_at":"2024-01-18T15:11:12.037Z","dependency_job_id":null,"html_url":"https://github.com/remarcable/ghost-convertkit-integration","commit_stats":null,"previous_names":["remarcable/ghost-convertkit-integration"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/remarcable/ghost-convertkit-integration","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/remarcable%2Fghost-convertkit-integration","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/remarcable%2Fghost-convertkit-integration/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/remarcable%2Fghost-convertkit-integration/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/remarcable%2Fghost-convertkit-integration/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/remarcable","download_url":"https://codeload.github.com/remarcable/ghost-convertkit-integration/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/remarcable%2Fghost-convertkit-integration/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271029764,"owners_count":24687486,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-18T02:00:08.743Z","response_time":89,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["convertkit","convertkit-api","ghost","ghost-api","ghost-blog","integration","serverless","synchronization"],"created_at":"2025-08-18T17:30:18.877Z","updated_at":"2025-09-15T18:47:52.165Z","avatar_url":"https://github.com/remarcable.png","language":"JavaScript","readme":"# Ghost ConvertKit Integration\n\nThis [serverless](https://github.com/serverless/serverless) function integrates/connects Ghost and ConvertKit through their webhooks and APIs.\n\n## Motivation\n\nThe official \"integration\" for Ghost and ConverKit is a set of [Zaps](https://ghost.org/integrations/convertkit/#sync-ghost-members-to-convertkit). As they weren't complete enough for my use case and paying for Zapier was too expensive for my personal blog, I created this serverless function to connect the two. This integration (without quotes) is a much more robust integration and easy to customize.\n\n## Features\n\n- Sync confirmed subscribers between ConvertKit and Ghost\n- Subscribe confirmed Ghost members to ConvertKit sequence (without retriggering another confirmation email)\n- Sync unsubscribes between ConvertKit and Ghost\n- Sync tags between ConvertKit and Ghost\n- Sync resubscribes from ConvertKit to Ghost\n- Free deployment to AWS Lambda (compared to more than $20 with Zapier)\n- Easy registration of webhooks using custom scripts\n- Easy to extend and customize for other needs (create an issue and/or PR!)\n\n#### Missing Features\n\nThe following features are missing because it's not possible to delete members using the ConvertKit API or triggering a resubscribe using ConvertKit.\n\n- Sync resubscribes from Ghost to ConvertKit (other way round should work)\n- Sync deletions between Ghost and ConvertKit\n\n#### Under consideration:\n\n- Publish as a stand-alone integration so it is simple to use and install\n\n## Usage\n\nTo deploy or develop this integration, you need the following values and put them into `.env`:\n\n- `CONVERTKIT_API_SECRET`: ConvertKit [API Secret](https://app.convertkit.com/account_settings/advanced_settings)\n- `CONVERTKIT_SEQUENCE_ID`: ConvertKit Sequence ID (Open the [Sequence](https://app.convertkit.com/sequences) in the interface and note the last part in the URL, e.g. `1651234` in `https://app.convertkit.com/sequences/1651234`)\n- `GHOST_ADMIN_API_KEY` API key of a new custom integration. Go to `Settings \u003e Integrations` and click on \"Add custom integration\". Copy the Admin API key.\n- `GHOST_API_URL` Copy the API URL from your integration (should be the same as your Ghost blog, e.g. `https://www.example.com` without the trailing `/ghost`)\n\n### Local Development\n\n#### Installation\n\n```bash\nnpm install\ncp .env.sample .env # Fill in the values from above\nnpm start\n```\n\n#### Tunneling webhooks\n\nYou can use [ngrok](https://ngrok.com/docs/getting-started/) to locally test the webhooks. In another terminal window, run:\n\n```bash\nngrok http 3000\n```\n\nCopy the public URL for the next step of registering the webhooks. It should look like `https://abcd-ef-gh-i-jkl.ngrok-free.app`.\n\n#### Registering ConvertKit webhooks\n\nTo register the webhooks, run the following command:\n\n```bash\nnode src/scripts/registerConvertkitWebhooks.mjs\n```\n\nPaste the ngrok URL from the last step and provide a list of tags you want to sync. With ConvertKit, it is only possible to sync tags that were explicitly provided. When you are done, you should see something like the following:\n\n```\nThe following webhooks are currently registered:\n1001234 | subscriber_unsubscribe | https://abcd-ef-gh-i-jkl.ngrok-free.app/convertkit/subscriber.subscriber_unsubscribe/\n1001235 | subscriber_activate | https://abcd-ef-gh-i-jkl.ngrok-free.app/convertkit/subscriber.subscriber_activate/\n1001236 | tag_add | https://abcd-ef-gh-i-jkl.ngrok-free.app/convertkit/subscriber.tag_add/finished-yearly\n1001238 | tag_remove | https://abcd-ef-gh-i-jkl.ngrok-free.app/convertkit/subscriber.tag_remove/finished-yearly\n```\n\n#### Registering Ghost webhooks\n\nRepeat this step with the Ghost integration:\n\n```bash\nnode src/scripts/registerGhostWebhooks.mjs\n```\n\nVerify that it worked correctly by visiting the link to your integration that is printed on the console. You should see webhooks for the events `member.added`, `member.edited`, and `member.deleted`.\n\nAfter completing those steps, ConvertKit and Ghost are integrated through your locally running serverless function. For production use, follow the steps below to run it with AWS.\n\n### Deployment\n\nSetup your [AWS credentials](https://www.serverless.com/framework/docs/providers/aws/guide/credentials/) before deployment and follow the steps above. Then run the following command:\n\n```bash\n$ npm run deploy\n```\n\nAfter deploying, you should see an output similar to this:\n\n```\nDeploying aws-node-ghost-convertkit-integration to stage production (us-east-1)\n\n✔ Service deployed to stack aws-node-ghost-convertkit-integration-production (152s)\n\nendpoint: GET - https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/\nfunctions:\n  ghost-ck-integration: aws-node-ghost-convertkit-integration-production (1.9 kB)\n```\n\nIf you later change the code of the lambda, you can run `npm run redeploy` for faster deployment.\n\n#### Registering ConvertKit and Ghost webhooks\n\nRegister the deployment URL in Ghost and ConvertKit:\n\n```bash\nnode src/scripts/registerConvertkitWebhooks.mjs\n\n# and then afterwards\nnode src/scripts/registerGhostWebhooks.mjs\n```\n\n#### Unregistering local webhook endpoints\n\nIf you've set up the webhooks locally, remove them after registering the production endpoint using the following script:\n\n```bash\nnode src/scripts/unregisterConvertkitWebhooks.mjs\n```\n\nFor Ghost, it isn't possible to delete the old webhooks programmatically, so you need to visit your integration in `Ghost Settings \u003e Integrations \u003e Custom \u003e \u003cYour Integration\u003e` and remove them manually.\n\n## Done 🎉\n\nEnjoy your stress-free no-quotes integration between Ghost and ConvertKit.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fremarcable%2Fghost-convertkit-integration","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fremarcable%2Fghost-convertkit-integration","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fremarcable%2Fghost-convertkit-integration/lists"}