Skip to content
Codeskop

Segments, export & webhooks

Group users by who they are and what they did, then take them to your own tools by user id.

Build a segment

In Analytics → Segments, choose New segment and combine conditions (all of them, or any):

OptionTypeDescription
Traitis, is not, contains, greater/less than, is setThe latest value from identify, e.g. plan is pro, or city is Nairobi.
Didevent or screen, within N dayse.g. added_to_cart at least once in the last 7 days. Can be filtered by a property.
Didn't doevent or screen, within N dayse.g. no order_completed in the last 7 days.

The count updates as you build it. Example: did added_to_cart in the last 7 days and didn't do order_completed in the last 7 days: your abandoned carts.

Use the members

Export

Export CSV downloads every member's user_id (or anonymous install id). Match them to people in your own database, CRM or messaging tool.

Webhook

  1. Add an HTTPS URL to the segment

    Owners and admins can add one when creating or editing a segment. It must be a public https:// address.

  2. Copy the signing secret

    It's shown once after saving. Use it to check that requests really come from Codeskop.

  3. Handle new members

    Every hour, Codeskop POSTs the users who newly match (the first run sends everyone who matches), up to 1,000 per request:

    POST body
    {  "type": "segment.entered",  "segment": { "id": "6f1c…", "name": "Added to cart, didn't buy" },  "project": { "id": "a2e9…", "name": "Shop" },  "environment": "production",  "users": [    { "user_id": "u_1042" },    { "anonymous_install_id": "3c0d…" }  ],  "sent_at": "2026-10-01T09:00:02Z"}

Verify the signature

verify.ts
import crypto from "node:crypto"; // header: Codeskop-Signature: t=1759309202,v1=5f2b…export function verify(rawBody: string, header: string, secret: string): boolean {  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));  const expected = crypto.createHmac("sha256", secret).update(`${parts.t}.${rawBody}`).digest("hex");  const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) < 300; // 5 minutes  const given = Buffer.from(parts.v1 ?? "");  return fresh && given.length === expected.length && crypto.timingSafeEqual(Buffer.from(expected), given);}
  • Respond with any 2xx. Other responses are shown as the segment's last status; the next run tries again.
  • Redirects aren't followed, and URLs that resolve to private networks are refused.

Messaging is on the roadmap

Sending WhatsApp, SMS and email to a segment directly from Codeskop is planned as a paid add-on for Growth and Scale. Until then, use the export or webhook with your own tools.

Next steps