Functions

Endless customization at your fingertips with just a few lines of Javascript

Build custom integrations, enrich and transform data, and mask sensitive information with a simple webhook on Twilio Segment’s open, extensible platform - now even faster with AI.

Please provide your company email address.
Please enter a valid email address.
Please provide an individual corporate email address.
Please provide a valid full name.
Please provide your phone number.
That phone number is too short.
That phone number is too long.
Please provide a valid phone number.

For information about how Segment handles your personal data, please see our privacy policy.

Thank you, you're all set!

We'll get back to you shortly. For now, you can create your workspace by clicking below.

Thank you for submitting your request for a demo! Answer 4 more questions to help us pinpoint exactly what your team needs to get started with Segment.

Please provide a valid job title.
Please provide a company size.
Please provide the estimated web traffic.
Please provide a timeline.

For information about how Segment handles your personal data, please see our privacy policy.

Join the 25,000+ companies using the Segment platform

Unlock custom sources and destinations

Integrate each and every API

Collect and transform any stream of first-party customer data from webhooks into Segment events. Transform and map events collected by Segment to new destinations and internal services.

Illustration: Custom Sources
Illustration: Destinations

Extend Segment with custom capabilities

Enrich, transform, and mask data with code

Insert code to enrich data with context from profiles and third-party sources, filter events to ensure data quality, and even mask sensitive data to support compliance.

Orchestrate and optimize quickly with AI co-pilot

Save time writing, testing, and maintaining code with AI

Generate complete Functions in minutes from natural language prompts - without the hassle of manual coding. Plus, optimize existing Functions with AI recommendations for improvement.

Product Screenshot: Copilot
Product Screenshot: Copilot

Develop on Segment without the sweat

Serverless and effortless

Not only is Functions serverless, but it’s super easy to use with a crisp and clean code editor, testing with sample events, and reusable code from prebuilt templates and existing Functions, all in the same interface. Enhance team collaboration and experimentation with version control.

Quick and easy customization

Customizing your Segment implementation requires just a few lines of JavaScript, freeing up engineering time for productive tasks that drive business value and less time spent wrestling with data pipeline workarounds. Functions is serverless and Segment does all the heavy lifting so you don't have to worry about provisioning additional server space to run them.

Developer-friendly

Functions is built by developers, for developers. Segment supports testing, version control, and code reusability features to help you collaborate and experiment freely - as well as Functions Co-Pilot serving as your trusty AI guide to orchestrate and optimize code in a snap.

Enterprise-grade scalability

Not only do the biggest companies in the world trust Segment to process over a million API calls per second, but Functions also supports batching to help you stay within rate limits imposed by downstream providers.

Sample code to get you started

Try out these pre-built Functions templates on a free workspace today!

/**
* Please do not delete [used for Intellisense]
* @param {ServerRequest} request The incoming webhook request
* @param {Object.<string, any>} settings Custom settings
* @return void
*/
async function onRequest(request, settings) {
  const { event: body } = request.json();
  const {
    object_type,
    subscription_id,
    data: { id, created_by, updated_by },
    data,
    action
  } = body;
  const sourceCtx = () => ({ integration: { name: "Close [Custom]" } });
  
  const objectTypeCollectionMapping = new Map([
    ["opportunity", "opportunities"],
    ["lead", "leads"],
    ["contact", "contacts"],
    ["activity.note", "activity_notes"],
    ["activity.call", "activity_calls"],
    ["activity.email", "activity_emails"]
  ]);
  
  const collection = objectTypeCollectionMapping.get(object_type);
  if (!collection) return;
  
  let properties = {
    ...data,
    ...subscription_id
  };
  
  if (action === "deleted") properties = null;
  
  Segment.set({
    collection,
    id,
    properties,
    context: sourceCtx()
  });
  
  const eventName = [...object_type.split("."), action]
  .map(w => w[0].toUpperCase() + w.substr(1).toLowerCase())
  .join(" ");
  
  Segment.track({
    userId: updated_by || created_by,
    event: eventName,
    properties: {
      [`${object_type.replace(/\./g, "_")}_id`]: id,
      ...subscription_id
    },
    context: sourceCtx()
  });
}
/**
* Please do not delete [used for Intellisense]
* @param {ServerRequest} request The incoming webhook request
* @param {Object.<string, any>} settings Custom settings
* @return void
*/
async function onRequest(request, settings) {
  const {
    current,
    previous,
    meta: { object: objectType, id, action }
  } = request.json();
  
  const supportedObjects = ["deal", "organization", "note", "person"];
  if (!supportedObjects.some(type => type === objectType)) {
    console.log("unsupported webhook type");
    return;
  }
  
  const sourceContext = () => ({ integration: { name: "PipeDrive [Custom]" } });
  
  let properties;
  if (action === "deleted") {
    // overwrite all the pre-existing keys with empty values
    properties = _.mapValues(flatten(previous), _ => null);
  } else {
    properties = flatten(current);
  }
  
  // upsert
  Segment.set({
    collection: `${objectType}s`,
    id,
    properties,
    context: sourceContext()
  });
  
  const event = [objectType, action]
  .map(w => w[0].toUpperCase() + w.substr(1).toLowerCase())
  .join(" ");
  
  // send event
  Segment.track({
    event,
    userId: current.user_id,
    properties: {
      [`${objectType}_id`]: current.id,
      ...(action === "deleted" ? {} : properties)
    },
    context: sourceContext()
  });
}

function flatten(input) {
  const result = {};
  function recur(obj, prefix = "") {
    Object.entries(obj).forEach(([key, value]) => {
      if (_.isObject(value)) {
        recur(value, `${prefix}${key}_`);
      } else {
        result[`${prefix}${key}`] = value;
      }
    });
  }
  recur(input);
  return result;
}
exports.processEvents = async (event) => {
  const msg = event.payload.body
  const { first, last } = msg.Name.value
  const { email } = msg.Email.value
  const userId = msg.UniqueID
  const formId = msg.FormID
  const optin = msg.optin.value ? true : false
  
  // create Leads in SFDC or user profiles downstream
  const identify = {
    type: 'identify',
    userId,
    traits: {
      firstName: first,
      lastName: last,
      email,
      optin
    }
  }
  
  // send explicit track event for funnel analyses and audiencing downstream
  const track = {
    type: 'track',
    event: 'Form Submitted',
    userId,
    properties: { formId, email }
  }
  
  // Return an object with any combination of the following keys
  let returnValue = {
    events: [identify, track]
  }
  
  // Return the JavaScript object with a key of events, objects or both
  return(returnValue)
}
async function onRequest(request, settings) {
  let eventBody = request.json()
  
  if (eventBody.resource_type == 'order') {
    Segment.set({
      collection: eventBody.resource_type,
      id: eventBody.resource.id,
      properties: {
        createTime: eventBody.resource.create_time,
        updateTime: eventBody.resource.update_time,
        orderStatus: eventBody.event_type, // converts event_type as the status of the order
        revenue: eventBody.resource.amount.total,
        currency: eventBody.resource.amount.currency,
        transactionFeeValue: eventBody.resource.transaction_fee.value,
        transactionFeeCurrency: eventBody.resource.transaction_fee.currency,
        parentPayment: eventBody.resource.parent_payment,
        isFinalCapture: eventBody.resource.is_final_capture,
        state: eventBody.resource.state,
        webhookId: eventBody.id, // id of the incoming webhook
        source: 'Paypal'
      }
    })
  }
  
  if (eventBody.resource_type == 'plan') {
    Segment.set({
      collection: eventBody.resource_type,
      id: eventBody.resource.id,
      properties: {
        createTime: eventBody.resource.create_time,
        updateTime: eventBody.resource.update_time,
        status: eventBody.resource.status,
        tenureType: eventBody.resource.tenure_type,
        sequence: eventBody.resource.sequence,
        tier_mode: eventBody.resource.volume,
        webhookId: eventBody.id, // id of the incoming webhook
        source: 'Paypal'
      }
    })
  }
  
  if (eventBody.resource_type == 'checkout-order') {
    const props = {
      createTime: eventBody.resource.create_time,
      updateTime: eventBody.resource.update_time,
      revenue: eventBody.resource.gross_amount.value,
      currency: eventBody.resource.gross_amount.currency_code,
      status: eventBody.resource.status,
      webhookId: eventBody.id, // id of the incoming webhook
      source: 'Paypal'
    }
    
    Segment.set({
      collection: eventBody.resource_type,
      id: eventBody.resource.id,
      properties: props
    })
    
    Segment.track({
      event: 'Order Completed',
      userId: eventBody.resource.payer.payer_id,
      properties: props
    })
  }
}
async function onRequest(request, settings) {
  let eventBody = request.json()
  
  if (eventBody.type == "charge.succeeded" && eventBody.data.object.customer) {
    Segment.track({
      event: "Charge Succeeded",
      userId: eventBody.data.object.customer,
      properties: {
        createTime: eventBody.data.object.created,
        amount: eventBody.data.object.amount,
        paid: eventBody.data.object.paid,
        status: eventBody.data.object.status
      },
      context: {
        source: "Stripe"
      }
    })
  }
  
  if (eventBody.type == "customer.created") {
    Segment.track({
      event: "Customer Created",
      userId: eventBody.data.object.id,
      properties: {
        createTime: eventBody.data.object.created,
        account_balance: eventBody.data.object.account_balance,
        currency: eventBody.data.object.currency
      },
      context: {
        source: "stripe"
      }
    })
    
    Segment.identify({
      userId: eventBody.data.object.id,
      properties: {
        createTime: eventBody.data.object.created,
        account_balance: eventBody.data.object.account_balance,
        currency: eventBody.data.object.currency
      },
      context: {
        source: "Stripe"
      }
    })
  }
  
  if (eventBody.type == "customer.subscription.created") {
    Segment.track({
      event: "Subscription Created",
      userId: eventBody.data.object.customer,
      properties: {
        createTime: eventBody.data.object.created,
        plan_id: eventBody.data.object.plan.id,
        plan_name: eventBody.data.object.plan.name,
        plan_interval: eventBody.data.object.plan.interval,
        trial_start: eventBody.data.object.trial_start,
        trial_end: eventBody.data.object.trial_end
      },
      context: {
        source: "stripe"
      }
    })
  }
  
  if (eventBody.type == "customer.subscription.trial_will_end") {
    Segment.track({
      event: "Trial Ending Soon",
      userId: eventBody.data.object.customer,
      properties: {
        plan_id: eventBody.data.object.plan.id,
        plan_name: eventBody.data.object.plan.name,
        plan_interval: eventBody.data.object.plan.interval,
        trial_start: eventBody.data.object.trial_start,
        trial_end: eventBody.data.object.trial_end
      },
      context: {
        source: "stripe"
      }
    })
  }
async function onRequest(request, settings) {
  let eventBody = request.json();
  
  Segment.track({
    event: eventBody.event_type,
    userId: eventBody.resources.respondent_id,
    timestamp: eventBody.event_datetime,
    properties: {
      source: "SurveyMonkey",
      name: eventBody.name,
      objectType: eventBody.object_type,
      objectId: eventBody.object_id,
      filterId: eventBody.filter_id,
      eventId: eventBody.event_id,
      filterType: eventBody.filter_type,
      eventType: eventBody.event_type,
      subscriptionUrl: eventBody.subscription_url,
      href: eventBody.href,
      eventDateTime: eventBody.event_datetime,
      resources: {
        respondentId: eventBody.resources.respondent_id,
        recipientId: eventBody.resources.recipient_id,
        userId: eventBody.resources.user_id,
        collectorId: eventBody.resources.collector_id,
        surveyId: eventBody.resources.survey_id
      }
    }
  })
}
async function onRequest(request, settings) {
  let eventBody = request.json();
  const formResponse = eventBody.form_response;
  
  // Iterates through nested fields to build question answer pairs
  for (var i = 0; i < formResponse.definition.fields.length; i++) {
    buildQuestion(formResponse.definition.fields[i], formResponse.form_id)
    buildAnswer(formResponse.answers[i], formResponse.definition.fields[i].id)
  }
  
  if (eventBody.event_type == 'form_response') {
    Segment.set({
      collection: 'form_responses',
      id: formResponse.form_id,
      properties: {
        token: formResponse.token,
        submitTime: formResponse.submitted_at,
        landTime: formResponse.landed_at,
        formTitle: formResponse.definition.title
      }
    })
  }
}

// Helper Functions

function buildAnswerObj(fullAnswer) {
  if (fullAnswer["choices"] != undefined) {
    return fullAnswer["choices"]["labels"].join();
  } else if (fullAnswer["choice"] != undefined) {
    return fullAnswer["choice"]["label"];
  } else {
    return String(fullAnswer[fullAnswer.type])
  }
}

function buildQuestion(formFields, id) {
  Segment.set({
    collection: 'form_questions',
    id: id,
    properties: {
      responseId: id,
      title: formFields.title,
      type: formFields.type,
      ref: formFields.ref,
      allowMultipleSelections: formFields.allow_multiple_selections,
      allowOtherChoices: formFields.allow_other_choices
    }
  })
}

function buildAnswer(answerFields, questionId) {
  Segment.set({
    collection: 'form_answers',
    id: answerFields.field.id,
    properties: {
      questionId: questionId,
      type: answerFields.type,
      answer: buildAnswerObj(answerFields)
    }
  })
}

Getting started is easy

Start connecting your data with Segment.