Velocity in Workflows

In workflows, Velocity goes beyond message personalization — you can use it to transform data, write values to contact fields, and route contacts through different paths based on field values, event parameters, or external data.

This article covers practical use cases. Depending on the scenario, the expressions shown here are used in the Update contact fields, Branch, or Webhook block settings.

Use Case 1: Global Holdout Group from the Last Digit of Contact ID

  • Goal: split contacts into stable test and control groups for all campaigns.
  • Start: event-based workflow or regular workflow for a segment
  • Where: Workflow → Update contact fields block
  • Save: the last digit of contactId into the additional field controlDigit
  • Expression:
$contactId.toString().substring($mathTool.sub($contactId.toString().length(),1))

How to use later:

  • Control group 10% — put only contacts with controlDigit equal to 0 into the control group. Out of all possible digits (0–9), you take one → approximately 10% of the audience.
  • Test group 90% — send campaigns to everyone except the control group. Contacts with controlDigit from 1 to 9approximately 90% of the audience.
  • Control group 20% — put contacts with controlDigit equal to 0 or 1 into the control group. Two digits out of ten → approximately 20% of the audience.

How this looks in practice:

In the Branch block or a segment condition, check the saved field controlDigit and route contacts into Control and Test paths based on the last digit.

Use Case 2: Save a Value from AddFavoritesItem into a Contact Field

  • Goal: save the ID of the last favorited product from an event into a contact field (e.g., lastWishlistItemId) for reuse.
  • Start: event-based workflow (AddFavoritesItem)
  • Where: Workflow → Update contact fields block
  • Save: product ID into additional field lastWishlistItemId

If the value comes from an object in the lastProductAdded parameter:

$lastProductAdded.externalItemId

Event fragment:

"lastProductAdded": {
  "externalItemId": 87420539,
  "name": "Awesome item",
  "cost": "1000"
}

If the value comes from an array in the productsFullData parameter:

$productsFullData[0].externalItemId

Event fragment:

"productsFullData": [
  {
    "externalItemId": 2697928574,
    "name": "Awesome item",
    "cost": "1000"
  }
]

How to use later:

  • Personalize messages — insert the saved ID into recommendation emails or push notifications (e.g., a reminder about a wishlisted item).
  • Segmentation — build segments based on the last added product or category.
  • Branching — route contacts through different paths depending on which product was added to the wishlist.

How this looks in practice:

  1. A contact adds a product to their wishlist → Yespo receives the AddFavoritesItem event.
  2. The workflow starts and moves to the Update contact fields block.
  3. Yespo writes the event value into the field lastWishlistItemId (using $lastProductAdded.externalItemId or $productsFullData[0].externalItemId).
  4. Any future workflow, segment, or message can read lastWishlistItemId from the contact profile and use it for branching or personalization.

Use Case 3: Webhook for Data Enrichment or Transfer

  • Goal:
    • GET: request data from an external system (e.g., stock availability, personal discount, recommended product) and optionally save the returned values in Yespo.
    • POST: transfer selected event or contact data to an external system (for logging, CRM updates, analytics pipelines, triggering external processes).
  • Start: event-based workflow (AddFavoritesItem) or regular workflow for a segment
  • Where: Workflow → Webhook block (+ Update contact fields block if you want to save GET results)
  • Save:
    • GET: optional — save values returned by the endpoint into additional fields (e.g., couponCode, stockStatus, recommendedItemId).
    • POST: depends on your use case.

GET — pass data in the URL, receive a response:

https://api.example.com/favorites?contactId=$contactId&itemId=$lastProductAdded.externalItemId

Or if the value comes from an array:

https://api.example.com/favorites?contactId=$contactId&itemId=$productsFullData[0].externalItemId

POST — pass data in the request body:

{
  "externalCustomerId": "$externalCustomerId",
  "externalItemId": "$lastProductAdded.externalItemId"
}

Or if the value comes from an array:

{
  "contactId": "$contactId",
  "externalCustomerId": "$externalCustomerId",
  "event": "AddFavoritesItem",
  "externalItemId": "$productsFullData[0].externalItemId"
}

How to use later:

  • After GET: personalize messages using saved values, branch workflows based on returned attributes, segment audiences using enriched fields.
  • After POST: build external reporting and attribution, sync data with a CRM, trigger external actions (coupon generation, stock check, etc.).

How this looks in practice:

  1. AddFavoritesItem triggers the workflow.
  2. The workflow reaches the Webhook block.
  3. One of two patterns occurs:
    • GET: Yespo calls the URL → the external system returns data (e.g., { "couponCode": "WISH10", "stockStatus": "available" }).
    • POST: Yespo sends a JSON payload → the external system stores or processes the data.
  4. For GET, the workflow can then move to Update contact fields to save response values into the contact profile.
  5. Future workflows and messages use the saved fields (GET) or rely on external processing (POST).

Use Case 4: Branch by Subscription Period

  • Goal: check the subscription period in a payment event and send the corresponding email.
  • Start: event-based workflow (InvoiceCommon)
  • Where: Workflow → Branch block → Email block
  • Save: optional — save the subscription period to a contact field if you want to reuse it later in segments, workflows, or messages.

In this example, subscription details are passed in the items parameter where products are stored inside items.array. To access the subscription period of the first item, use:

$items.array[0].subscriptionPeriod

Event fragment:

{
  "eventTypeKey": "InvoiceCommon",
  "params": {
    "items": {
      "array": [
        {
          "subscriptionPeriod": "90"
        }
      ]
    }
  }
}

How to use in the Branch block

Based on the value of $items.array[0].subscriptionPeriod, route contacts to the correct email path:

  • 30 → send the 30-day subscription email
  • 90 → send the 90-day subscription email
  • other or empty value → use a fallback branch

How to use later

  • Send different payment confirmation or onboarding emails depending on the purchased subscription term.
  • Keep communication aligned with the actual subscription period from the payment event.
  • Optionally save the value to a contact field to reuse it outside this event-triggered workflow.

How this looks in practice

  1. A payment triggers the InvoiceCommon event.
  2. The workflow starts.
  3. The Branch block checks the value of $items.array[0].subscriptionPeriod.
  4. The contact is routed to the corresponding email branch based on the value.
  5. Each branch sends the appropriate email for that subscription term.

Next Steps