---
title: "B2B company triggers, step by step"
description: "Step-by-step Shopify Flow tutorials for B2B: company and company location updates, tax exemption changes and company contact changes."
canonical: "https://docs.workflow-trigger-extensions.app/b2b-company-trigger-tutorials"
---

# B2B company triggers, step by step

Five triggers for stores on Shopify's B2B features: companies, their locations, their contacts and the tax exemptions of a location.

**On this page:** [Company Update](#company-update), [Company Location Update](#company-location-update), [Company Location Tax Exemptions Changed](#company-location-tax-exemptions-changed), [Company Contact Updated](#company-contact-updated), [Customer Removed from Company](#customer-removed-from-company)

> [!TIP]
> **New to Shopify Flow?**
> Every example follows the same five moves: pick the trigger, add a condition, add an action, turn the workflow on, check Event History. [Your first workflow, step by step](https://docs.workflow-trigger-extensions.app/first-workflow-tutorial.md) shows each of them with screenshots.

![Shopify Flow's trigger picker inside Workflow Trigger Extensions, searched for Compan](https://cdn-dev.eu.codecreationlabs.cloud/crm-tool/uploads/SjJ78gKLnLlocopCui3Cs62dJbGZ7F1n/5f798fe8ee355dc5.png)
*Where you find them: in Shopify Flow choose Select a trigger, open Workflow Trigger Extensions and search for "Compan".*

## Company Update

Fires when a company record is updated: name, note, external ID.

| | |
| --- | --- |
| **Fires from** | Shopify webhook |
| **Permission** | **Company & Company Location Data Access (B2B)** |
| **Switched on** | Turning on a Flow workflow that uses it switches it on. Its own switch is on the app's **Triggers** page |

**Use it for**

- Sync companies to an ERP keyed on `externalId`.

### What Company Update sends to your workflow

| Variable in Flow | Type | What it holds |
| --- | --- | --- |
| `company` | Object | The company that was updated |
| `company.id` | ID |  |
| `company.name` | Text |  |
| `company.note` | Text |  |
| `company.externalId` | Text |  |
| `company.customerSince` | Text |  |
| `company.createdAt` | Text |  |
| `company.updatedAt` | Text |  |
| `eventId` | Text | The id of this event. Search for it in the app's Event History to see exactly what was sent. |

### Example: Sync a company to the ERP

1. Pick **Company Update** as the trigger.
2. Add a **Condition**: `company.externalId` **Not empty and exists**.
3. Add **Send HTTP request** with `{{company.externalId}}`, `{{company.name}}` and `{{company.note}}`.
4. Turn the workflow on.

## Company Location Update

Fires when a company location is updated: name, phone, locale, note, external ID.

| | |
| --- | --- |
| **Fires from** | Shopify webhook |
| **Permission** | **Company & Company Location Data Access (B2B)** |
| **Switched on** | Turning on a Flow workflow that uses it switches it on. Its own switch is on the app's **Triggers** page |

**Use it for**

- Keep ship-to records of an ERP current.

### What Company Location Update sends to your workflow

| Variable in Flow | Type | What it holds |
| --- | --- | --- |
| `companyLocation` | Object | The company location that was updated |
| `companyLocation.id` | ID |  |
| `companyLocation.name` | Text |  |
| `companyLocation.note` | Text |  |
| `companyLocation.externalId` | Text |  |
| `companyLocation.locale` | Text |  |
| `companyLocation.phone` | Text |  |
| `companyLocation.currency` | Text |  |
| `companyLocation.createdAt` | Text |  |
| `companyLocation.updatedAt` | Text |  |
| `eventId` | Text | The id of this event. Search for it in the app's Event History to see exactly what was sent. |

### Example: Sync a ship-to location

1. Pick **Company Location Update** as the trigger.
2. Add **Send HTTP request** with `{{companyLocation.externalId}}`, `{{companyLocation.name}}` and `{{companyLocation.currency}}`.
3. Turn the workflow on.

## Company Location Tax Exemptions Changed

Fires when the tax exemptions, the tax registration ID or the tax-exempt flag of a company location change. `changes.added` and `changes.removed` are lists of exemptions, each with a `code` and a readable `label`.

| | |
| --- | --- |
| **Fires from** | Checked on a schedule, because Shopify sends no webhook for it |
| **Permission** | **Company & Company Location Data Access (B2B)** |
| **Switched on** | Turning on a Flow workflow that uses it switches it on. Its own switch is on the app's **Triggers** page |

**Use it for**

- Have finance verify every new exemption before the next order.
- Keep a tax engine in step.

### What Company Location Tax Exemptions Changed sends to your workflow

| Variable in Flow | Type | What it holds |
| --- | --- | --- |
| `companyLocation` | Object | The company location whose tax exemptions changed |
| `companyLocation.id` | ID |  |
| `companyLocation.name` | Text |  |
| `changes` | Object | The added / removed / current tax exemptions (each a code + label), plus the tax registration ID and tax-exempt flag |
| `changes.added` | List of objects | Tax exemptions added in this change. |
| `changes.added (each).code` | Text | The Shopify tax exemption enum value (e.g. CA_BC_RESELLER_EXEMPTION, EU_REVERSE_CHARGE_EXEMPTION_RULE). |
| `changes.added (each).label` | Text | A human-readable label derived from the code (e.g. "CA BC Reseller Exemption"). |
| `changes.removed` | List of objects | Tax exemptions removed in this change. |
| `changes.removed (each).code` | Text | The Shopify tax exemption enum value (e.g. CA_BC_RESELLER_EXEMPTION, EU_REVERSE_CHARGE_EXEMPTION_RULE). |
| `changes.removed (each).label` | Text | A human-readable label derived from the code (e.g. "CA BC Reseller Exemption"). |
| `changes.current` | List of objects | All tax exemptions currently on the company location (after this change). |
| `changes.current (each).code` | Text | The Shopify tax exemption enum value (e.g. CA_BC_RESELLER_EXEMPTION, EU_REVERSE_CHARGE_EXEMPTION_RULE). |
| `changes.current (each).label` | Text | A human-readable label derived from the code (e.g. "CA BC Reseller Exemption"). |
| `changes.taxRegistrationId` | Text | The company location's tax registration ID (empty if not set). |
| `changes.taxExempt` | True / false | Whether the company location is fully tax exempt. |
| `eventId` | Text | The id of this event. Search for it in the app's Event History to see exactly what was sent. |

### Example: Send new tax exemptions to finance

1. Pick **Company Location Tax Exemptions Changed** as the trigger.
2. Add a **Condition**: `changes.added` **Not empty and exists**.
3. Add **Send internal email** with `{{companyLocation.name}}` and a Liquid `for` loop over `changes.added` that prints each exemption's `label` and `code`.
4. Turn the workflow on.

> [!NOTE]
> **Good to know**
> Shopify sends no webhook for this, so it is a polling trigger with a short delay.

## Company Contact Updated

Fires when a company contact is updated: job title, locale, main-contact flag.

| | |
| --- | --- |
| **Fires from** | Shopify webhook |
| **Permission** | **Company & Company Location Data Access (B2B)** + **Customer Data Access** |
| **Switched on** | Turning on a Flow workflow that uses it switches it on. Its own switch is on the app's **Triggers** page |

**Use it for**

- Tell the account manager when the main contact of a company changes.

### What Company Contact Updated sends to your workflow

| Variable in Flow | Type | What it holds |
| --- | --- | --- |
| `customer` | Customer (Shopify) | The customer whose company contact was updated. A full Shopify customer, so all of its fields and Flow's own customer actions are available. |
| `company` | Object | The company the contact belongs to (id, name, external ID, note) |
| `company.id` | ID |  |
| `company.name` | Text |  |
| `company.externalId` | Text |  |
| `company.note` | Text |  |
| `companyContact` | Object | The updated contact (id, job title, locale, whether they are the main contact) |
| `companyContact.id` | ID |  |
| `companyContact.title` | Text |  |
| `companyContact.locale` | Text |  |
| `companyContact.isMainContact` | True / false |  |
| `eventId` | Text | The id of this event. Search for it in the app's Event History to see exactly what was sent. |

### Example: Notify on a new main contact

1. Pick **Company Contact Updated** as the trigger.
2. Add a **Condition**: `companyContact.isMainContact` **Equal to** `true`.
3. Add **Send internal email** with `{{company.name}}` and `{{customer.displayName}}`.
4. Turn the workflow on.

> [!NOTE]
> **Good to know**
> Needs **Customer Data Access** as well, because the contact arrives as a customer reference.

## Customer Removed from Company

Fires when a customer is removed as a contact of a company.

| | |
| --- | --- |
| **Fires from** | Shopify webhook |
| **Permission** | **Company & Company Location Data Access (B2B)** + **Customer Data Access** |
| **Switched on** | Turning on a Flow workflow that uses it switches it on. Its own switch is on the app's **Triggers** page |

**Use it for**

- Remove B2B tags, price list access or portal logins of someone who left a company.

### What Customer Removed from Company sends to your workflow

| Variable in Flow | Type | What it holds |
| --- | --- | --- |
| `customer` | Customer (Shopify) | The customer who was removed from the company. A full Shopify customer, so all of its fields and Flow's own customer actions are available. |
| `company` | Object | The company the customer was removed from (id, name, external ID, note) |
| `company.id` | ID |  |
| `company.name` | Text |  |
| `company.externalId` | Text |  |
| `company.note` | Text |  |
| `companyContact` | Object | The removed contact (id, job title, locale, whether they were the main contact) |
| `companyContact.id` | ID |  |
| `companyContact.title` | Text |  |
| `companyContact.locale` | Text |  |
| `companyContact.isMainContact` | True / false |  |
| `eventId` | Text | The id of this event. Search for it in the app's Event History to see exactly what was sent. |

### Example: Remove the wholesale tag from a removed contact

1. Pick **Customer Removed from Company** as the trigger.
2. Add **Remove customer tags** with `wholesale`.
3. Add **Send internal email** to the account manager of `{{company.name}}`.
4. Turn the workflow on.

## Next steps

Company access depends on **Customer Data Access**: without it Shopify returns no companies at all. Grant Customer access first, then Company access. For B2B buyers visiting the storefront see [Storefront triggers, step by step](https://docs.workflow-trigger-extensions.app/storefront-trigger-tutorials.md).

- [Complete trigger reference](https://docs.workflow-trigger-extensions.app/trigger-reference.md) - every trigger on one page.
- [Choosing the right trigger](https://docs.workflow-trigger-extensions.app/choosing-the-right-trigger.md) - which one fits your case.
- [Custom triggers](https://docs.workflow-trigger-extensions.app/custom-triggers.md) - when no built-in trigger fits, write your own.
- [Event history and troubleshooting](https://docs.workflow-trigger-extensions.app/event-history-and-troubleshooting.md) - see what fired and what it carried.
- [Trigger events on a record's admin page](https://docs.workflow-trigger-extensions.app/admin-blocks.md) - the latest events of one record, on its own page in the Shopify admin.
