Mergetober part 2: my plan was wrong twice, and a free trial caught it before the code did
Description and use
The connector now reliably syncs all Customer.io messages, correctly handles translations, avoids duplicate processing, and gracefully skips incomplete steps, enabling cognee to answer queries about marketing content.
Problem
Implementing a Customer.io connector for cognee required a correct sync strategy, but initial assumptions about translations, deduplication, and change detection were wrong, leading to data inconsistencies.
Outcome
The connector now reliably syncs all Customer.io messages, correctly handles translations, avoids duplicate processing, and gracefully skips incomplete steps, enabling cognee to answer queries about marketing content.
Workflow
- 1. Sign up for a free Customer.io trial and create test messages in English, French, and a newsletter.
- 2. Write a script to snapshot API responses and diff them to detect unexpected changes.
- 3. Identify translation handling: each language is a separate action with its own id and a multi_language_branch_action_id.
- 4. Discover deduplicate_id is a branch prefix, not a message id, and that updating one language updates all languages’ timestamps.
- 5. Test campaign updated timestamp as sync cursor; find it only changes on structural edits.
- 6. Switch design to a full snapshot: list all messages each run, use replace, hash message fields, and abort on listing failures.
- 7. Handle half‑finished SMS steps by falling back to per‑message fetch on 5xx and skipping only the failing item.
- 8. Strip HTML body to plain text, remove head, style, script, and unsubscribe footer.
- 9. Write 36 unit tests with a mocked API and run live against the trial to validate behavior.
- 10. Deploy connector via cognee’s remember API with an App API key.
Evidence
I signed up for a free Customer.io trial and built a small test automation: one email in Default, English and French, plus a newsletter.
My plan assumed one message comes back once per language. In reality, each language is its own action with its own id, linked by a multi_language_branch_action_id.
My plan said deduplicate_id "looks like id + timestamp" and proposed using it to detect changes.
The connector became a full snapshot, like cognee's Notion connector: Every run lists everything, with replace.
I wrote a throwaway script that: saved every API response as raw JSON (snapshot NAME), printed what appeared, disappeared or changed between two snapshots (diff A B).
- Record date: 2026-10-15T00:42:15.841Z