# Webhook campaigns

Webhook-triggered campaigns let you use your JSON data in Customer.io, without having to reshape it using Zapier or another product first. Where our traditional workflows trigger based on a person, a webhook trigger lets you start a campaign when you receive JSON data (in any shape) from a specific source.

## How it works[](#how-it-works)

Normally, you trigger campaigns when a person performs an event or meets some criteria you set. This type of campaign lets you use *webhooks* to trigger workflows when you receive data from an external source. This video helps explain how it works:

When you set up a webhook-triggered campaign, Customer.io generates a *Webhook URL*. You’ll provide this URL to the service or platform that you capture data from and set up rules determining when that service or platform will call your webhook, sending data to Customer.io. The data that your service or platform sends to Customer.io can take any JSON shape—arrays, objects, etc. As a part of your workflow, you’ll transform the incoming data to fit your needs.

You might use a webhook to capture data from an external service and convert it to:

*   An event that [triggers a campaign to send messages in Customer.io](/journeys/campaign-triggers/#event-trigger). This is the most common use case.
*   An [attributeA key-value pair that you associate with a person or an object—like a person’s name, the date they were created in your workspace, or a company’s billing date etc. Use attributes to target people and personalize messages.](/journeys/attributes/) update for a person.
*   Another service—using Customer.io as a bridge between data platforms, like what Zapier and Segment do!

### Reference customer attributes[](#reference-customer-attributes)

You cannot reference existing customer attributes in webhook-triggered campaigns because people aren’t the subject of the campaign: the webhook is. The campaign acts on the incoming webhook data, so there’s no person/customer to reference. Any attempt to reference customer data will return `""` (or `undefined` when using JavaScript) within a *Create/Update Person* action.

For example, the following Liquid is written to return the `customer.custom_attribute` value and append `trigger.custom_attribute`, or simply use the `trigger.custom_attribute` value if there is no value stored at `customer.custom_attribute`.

```fallback
{% if customer.custom_attribute == blank %}{{ trigger.custom_attribute }}
{% else %}
{{ customer.custom_attribute | append: trigger.custom_attribute }}
{% endif %}
```

However, within a webhook-triggered campaign, this Liquid will only return `trigger.custom_attribute`, regardless of the customer’s `custom_attribute` value.

You can use a *Create/Update Person* action within the webhook-triggered campaign to *set* attributes for people based on a match with the incoming webhook. You just won’t be able to *retrieve* the current attribute values.

 If any step in your data campaign needs to reference an existing customer attribute, [send an event from the data campaign](#create-event). Then use an [event-triggered campaign](/journeys/campaign-triggers/#event-trigger) to perform any logical evaluations based on the metadata passed in that event.

### Why can’t I send an email or message in my campaign?[](#why-cant-i-send-an-email-or-message-in-my-campaign)

In most campaigns, a person is the subject of the journey through your workflow. But in a webhook-triggered campaign, the incoming webhook is the subject of the campaign. We don’t know who (if anybody) your data is meant to represent. This means that you can’t send a message from a webhook-triggered campaign because there’s no person to send a message to.

*But* you can associate data from your webhook with a person in your workspace and trigger a secondary campaign that sends messages to a person—as long as there’s a value in your webhook that represents a person like an ID, email address, phone number, etc.

If your incoming webhook has this kind of data, you can use the *Send Event* action. This lets you transform your incoming webhook data into an [eventSomething that a person in your workspace did. Events can trigger campaigns, add people to segments, etc, and you can use properties from events to personalize messages.](/events/) associated with a person. This event can trigger downstream campaigns, so you can send messages to people based on your incoming webhook data.

 You can also update people

In a webhook campaign, you can use the [*Batch Update*](/journeys/batch-update/) action to update one or more people based on an identifying value in your incoming webhook—like all people associated with an account, or the person associated with a specific phone number.

## Create a webhook-triggered campaign[](#create-a-webhook-triggered-campaign)

As a part of campaign setup, you’ll receive a webhook URL that you need to provide to the external service that you want to capture data from. Before you begin, make sure that you have access to the service you want to capture data from, and that that service can send webhooks.

1.  Go to **Campaigns** and click **Create Campaign**.
    
2.  Click **Webhook**.
    
    [![the webhook campaign trigger exposes a webhook URL](https://docs.customer.io/images/data-campaign-trigger.png)](#8b0df8354512fb23ebede4589cbe764e-lightbox)
    
3.  Copy the **Webhook URL** and provide it to your external service. If possible, trigger the webhook; this sends representative data that you can use when setting up your campaign.
    
4.  Click **Save & Next**.
    
5.  Set up your workflow. From here you can:
    
    *   **[Create Events](#create-event)** to trigger another campaign or add people to segments.
    *   **[Create or Update People](#identify)** in your workspace.
    *   Send a **[Batch Update](#batch-update)** to update attributes or send events for multiple people.
    *   Use the **Send data** action to send a webhook. This forwards data to another service outside Customer.io:
        
        [![Set up your workflow actions to transform data](https://docs.customer.io/images/data-workflow-satismeter.png)](#0d6359e050c39d4b7c0b186744a719ab-lightbox)
        
6.  Click **Next** at the top right.
    
7.  Review your workflow, then click **Start Campaign** at the bottom of the page.
    

 You can send Slack notifications in a webhook-triggered campaign!

Because you trigger a webhook-based campaign with data that *isn’t* attached to a person in Customer.io, you can’t use most message types in this kind of campaign—you’d have nobody to send them to!

However, because Slack messages typically have a static destination—a channel or a specific DM—you can trigger a slack message. This provides a way to notify a group of people via Slack when this workflow is triggered.

### Send event[](#create-event)

The **[Send Event](/journeys/data-campaign-event-action/)** action lets you transform your incoming *Trigger data* to an event so you can [trigger messaging campaigns](/journeys/campaign-triggers/#event-trigger) or [add people to segments](/journeys/events/#event-segments). In general, the webhook that triggers your campaign should contain an identifierThe attributes you use to add, modify, and target people. Each unique identifier value represents an individual person in your workspace., like an email or ID, so you can create events for people in your workspace. (If your incoming webhook does *not* have an identifier for a person, you can still create an event, but you’ll have to set a static identifier and update the same person everytime this campaign is triggered.)

When you create an event, you must specify an *Event Name* (the `name` key) and *Event Attributes* (contained by the `data` object). Each of these fields can be one of four types:

*   **Static value**: A value that is the same in every event.
*   **Trigger attribute**: A property from your *Trigger data*. You can start typing to find a key in the incoming data or click the value in the *Trigger data*.
*   **[LiquidA syntax that supports variables, letting you personalize messages for your audience. For example, if you want to reference a person’s first name, you might use the variable `{{customer.first_name}}`.](/using-liquid)**: Use liquid to modify trigger attributes to fit your event—like reformatting a date value or appending a string to your event’s name.
*   **JavaScript**: Use [JavaScript](/journeys/js-in-actions/) to modify trigger attributes to fit your event—like reformatting a date value or appending a string to your event’s name. Use JavaScript over liquid if you want to modify incoming JSON.

**To create an event in your webhook-triggered campaign:**

1.  Drag **Send Event** into your workflow and click it.
2.  Set the *Event Name*. The event name helps you identify this action in your workflow; it’s not the `name` value for the event.
3.  Click **Add event** to set up your event.
4.  Under *Who do you want to update?*, select the **Workspace** containing the people you want to attach events to.
    
    [![Convert your incoming data to an event](https://docs.customer.io/images/create-event-json.png)](#a82e2c35250563a1fd1978259747e519-lightbox)
    
5.  Select the type of **Identifier** and set the identifier’s value for people in that workspace. You can identify someone from a trigger attribute, liquid, or JavaScript. Set a static value to always send events for the same person.
6.  Set the **Event Name**. This is the `name` value for the event that you’ll reference outside of this campaign in other campaign triggers, segments, etc.
7.  Add **Event Attributes**. These are values that appear in the `data` object of your event. You can use these properties to filter people into different campaigns or reference them in messages using [liquidA syntax that supports variables, letting you personalize messages for your audience. For example, if you want to reference a person’s first name, you might use the variable `{{customer.first_name}}`.](/using-liquid).
8.  Save your changes and click **Done**. Now you can finish building your webhook-triggered campaign.

### Create or update a person[](#identify)

If your incoming webhook contains an identifierThe attributes you use to add, modify, and target people. Each unique identifier value represents an individual person in your workspace.—like an email or ID—you can create or update a person as a part of your workflow. If the identifier matches a person in your workspace, this action updates that person; if the identifier does not match a person, this action creates a new person.

1.  Drag **Create or Update Person** into your workflow.
2.  Give the action a **Name** and click **Add Details**. You can also set *Action Conditions* if you want to limit when you create or update people based on an attribute in your incoming webhook.
    
    [![Add create or add person block to your workflow](https://docs.customer.io/images/campaign-webhook-create-update-person.png)](#5955fd6b1643b00bcb094d4164331d2e-lightbox)
    
3.  Select the workspace you want to add or update people in.
4.  Select the type of identifierThe attributes you use to add, modify, and target people. Each unique identifier value represents an individual person in your workspace. for the person you want to find or create then pick a value from your incoming webhook data.
5.  Click **Add attribute** and set attribute values for the new person.
    *   **Attribute** represents the name for the new attribute.
    *   **Value** lets you select where your value comes from and the value itself. For example, if you want to use an event property as a new attribute value, you’ll select *event attribute* and then the specific attribute in the event that you want to set as a person’s attribute.
    *   Keep in mind, [you cannot reference customer attributes in webhook-triggered campaigns](#reference-customer-attributes).
6.  Click **Save Changes** when you’re done, and finish your webhook-triggered campaign.

### Batch update[](#batch-update)

Other actions in a webhook-triggered campaign assume a one-to-one relationship between your data and a person. A [batch update](/journeys/batch-update/) lets you associate your incoming data with a group of up to 1000 people. For example, if multiple people can belong to an account and you trigger your webhook-based campaign when the account status changes, you can use a batch update to associate the new account status with all the people in your workspace belonging to that account.

The batch update action works much like a *Send event* or *Create or update person* action, except that you’ll set criteria determining the group of people you want to set attributes for, or send events to. See the [batch update page](/journeys/batch-update/) for help setting up a batch update.

[![send events to multiple people with a batch update](https://docs.customer.io/images/batch-update-event.png)](#87513950ffe9eb7e19668a0b84ba11a1-lightbox)

### Liquid variables[](#liquid-variables)

When you create an event or set a person’s attributes, you can manipulate values from your *Trigger data* with [liquidA syntax that supports variables, letting you personalize messages for your audience. For example, if you want to reference a person’s first name, you might use the variable `{{customer.first_name}}`.](/using-liquid). When you use liquid, you’ll reference incoming data in the `trigger` object. For example, you would access the `id` from the trigger data below using `{{trigger.identifiers.id}}`.

You can also use liquid to modify the trigger data. You might want to do this if you need to convert timestamps, append values, or access a specific set of values from an array. See the [liquid tag list](/journeys/liquid-tag-list/) for a list of ways you can transform data.

 When you reference an array or object, use `| to_json`

By default, liquid maps objects and arrays to strings (or an integer, where applicable). Use `| to_json` when you reference an object or array in your outgoing webhook to avoid errors and maintain the original shape of your trigger data!

Trigger Data

Outgoing Webhook (identify)

```json
{
"name": "purchase",
"identifiers": {
  "id": "abcd-1234",
  "email": "person@example.com"
},
"purchased_at": "Fri, 04 Feb 2022 23:49:39 GMT",
"total": 123.45,
"items": 2,
"tax": 10.45,
"purchase": [
  {
      "product": "shoes",
      "sku": 1234,
      "qty": 1,
      "price": 73.00
  }
  {
      "product": "socks",
      "sku": 5678,
      "qty": 4,
      "price": 40
  }
]
}
```

```json
{
  "email": "{{trigger.identifiers.email}}",
  "last_purchased_at": "{{trigger.purchased_at | date: %s}}",
  "last_purchased": "{{trigger.purchase | map product}}"
}
```

### Use JavaScript in your webhook-triggered campaign[](#use-javascript-in-your-webhook-triggered-campaign)

When you use the *Create Event* or *Create or Update Person* actions, you can also manipulate values from your *Trigger data* (or [snippetsA common value that you can reuse with Liquid in messages and other workflow actions—like your company address. You can store Liquid inside a snippet, making it easy to save and reuse advanced values and statements across your messages.](/snippets/)) with JavaScript rather than Liquid. Select *JavaScript* as the value type, and write `return` statements for your attribute or event data.

For example, if you wanted to access a person’s `id` using the example above, you would use `return triggers.identifiers.id;`.

See [our JavaScript quick reference guide](/journeys/js-in-actions/) for more examples to help you take advantage of JavaScript in your workflow.

 You can’t use Liquid inside JavaScript

When you use the JavaScript option, you must manipulate values with JavaScript. If you try to return a snippet value that contains Liquid, you’ll receive an error.

[![set event data with javascript](https://docs.customer.io/images/js-event-data.png)](#2c9b7b39b68dc89daba6669fb7a1e659-lightbox)