Skip to main content

Attribute B2B orders

This guide describes how to use the purchasingEntity field on the Order object to correctly attribute orders to the buyer, whether it's an individual customer (D2C) or a company (B2B). The purchasingEntity field returns a union type that resolves to one of two types:

  • Customer (D2C): An individual customer placed the order.
  • PurchasingCompany (B2B): A company placed the order through a company contact. The PurchasingCompany object includes the company, contact, and company location associated with the order.

The customer field always returns the individual who placed the order, which for B2B orders is the company contact, not the purchasing company itself. On shops that process B2B orders alongside D2C orders, apps that rely solely on Order.customer will attribute B2B orders to the company contact rather than the company, which can cause incorrect reporting, broken analytics, and misattributed order data.


Anchor to Comparing D2C and B2B order dataComparing D2C and B2B order data

The following examples show how the same fields return different data depending on the order type:

Individual (D2C) order

{
"id": 1,
"totalAmount": 45,
"customer": { "id": 100 },
"purchasingEntity": {
"__typename": "Customer",
"Customer": { "id": 100 }
}
}

B2B order

{
"id": 3,
"totalAmount": 1000,
"customer": { "id": 102 },
"purchasingEntity": {
"__typename": "PurchasingCompany",
"PurchasingCompany": {
"companyLocation": { "id": 456 },
"companyContact": {
"id": 800,
"customer": { "id": 102 }
}
}
}
}

The B2B order still has a customer (the individual contact who placed it), but purchasingEntity correctly identifies the purchasing company and its location.


Anchor to Before and after: fixing order attributionBefore and after: fixing order attribution

The following examples show how a typical order attribution integration can misattribute B2B orders, and how to fix it using purchasingEntity.

Anchor to Incorrect implementationIncorrect implementation

The following integration reads Order.customer, which misattributes B2B orders to the individual contact:

def misattributing_integration_pattern
recent_shopify_orders.each do |order|
customer_id = order.dig(:customer, :id)
account = "AR/Individual/#{customer_id}"
accounting_system_send(account, order[:totalAmount])
end
end

This produces wrong results for B2B orders:

account=AR/Individual/100 debit=45 (correct, D2C)
account=AR/Individual/101 debit=23 (correct, D2C)
account=AR/Individual/102 debit=1000 (WRONG, B2B order misattributed to individual)
account=AR/Individual/103 debit=4500 (WRONG, B2B order misattributed to individual)

Anchor to Correct implementationCorrect implementation

The following integration reads Order.purchasingEntity and branches on __typename to correctly route both order types:

def correct_integration_pattern
recent_shopify_orders.each do |order|
case order.dig(:purchasingEntity, :__typename)
when "Customer"
customer_id = order.dig(:purchasingEntity, :Customer, :id)
account = "AR/Individual/#{customer_id}"
when "PurchasingCompany"
business_id = order.dig(:purchasingEntity,
:PurchasingCompany, :companyLocation, :id)
account = "AR/Business/#{business_id}"
end
accounting_system_send(account, order[:totalAmount])
end
end

This correctly routes both order types:

account=AR/Individual/100 debit=45 (correct, D2C)
account=AR/Individual/101 debit=23 (correct, D2C)
account=AR/Business/456 debit=1000 (correct, B2B routed to company location)
account=AR/Business/456 debit=4500 (correct, B2B routed to company location)

The following queries show how to retrieve buyer attribution data for both single orders and bulk operations using the GraphQL Admin API.

Anchor to Query buyer attribution for a single orderQuery buyer attribution for a single order

The following order query (OrderBuyerAttribution) uses inline fragments to return the appropriate fields for both D2C and B2B orders. For a D2C order, purchasingEntity resolves to Customer and returns the individual buyer's details. For a B2B order, it resolves to PurchasingCompany and returns the company, the contact who placed the order, and the company location associated with it:

POST https://{shop}.myshopify.com/api/{api_version}/graphql.json

GraphQL query

query OrderBuyerAttribution($orderId: ID!) {
order(id: $orderId) {
id
name
purchasingEntity {
... on Customer {
id
displayName
email
}
... on PurchasingCompany {
company {
id
name
}
contact {
id
customer {
displayName
email
}
}
location {
id
name
}
}
}
}
}

JSON response

{
"data": {
"order": {
"id": "gid://shopify/Order/3",
"name": "#1003",
"purchasingEntity": {
"company": {
"id": "gid://shopify/Company/1",
"name": "Acme Corp"
},
"contact": {
"id": "gid://shopify/CompanyContact/1",
"customer": {
"displayName": "Jane Smith",
"email": "jane@acme.com"
}
},
"location": {
"id": "gid://shopify/CompanyLocation/1",
"name": "Acme Corp HQ"
}
}
}
}
}

Anchor to Check the order type with ,[object Object]Check the order type with __typename

The __typename field returns "Customer" for D2C orders and "PurchasingCompany" for B2B orders. Use this to branch your app logic:

query OrderType($orderId: ID!) {
order(id: $orderId) {
id
name
purchasingEntity {
__typename
... on Customer {
id
displayName
}
... on PurchasingCompany {
company {
id
name
}
}
}
}
}

The following JavaScript snippet shows how to handle the __typename from the query response:

const entity = order.purchasingEntity;

if (entity.__typename === "PurchasingCompany") {
// B2B order: attribute to the company
const companyName = entity.company.name;
} else if (entity.__typename === "Customer") {
// D2C order: attribute to the individual customer
const customerName = entity.displayName;
}

Anchor to Bulk query for orders with buyer attributionBulk query for orders with buyer attribution

The following orders query fetches multiple orders with correct buyer attribution across both order types:

POST https://{shop}.myshopify.com/api/{api_version}/graphql.json

GraphQL query

{
orders(first: 50, query: "status:open") {
nodes {
id
name
createdAt
purchasingEntity {
__typename
... on Customer {
id
displayName
email
}
... on PurchasingCompany {
company {
id
name
}
contact {
customer {
displayName
email
}
}
location {
name
}
}
}
}
}
}

JSON response

{
"data": {
"orders": {
"nodes": [
{
"id": "gid://shopify/Order/1",
"name": "#1001",
"createdAt": "2024-01-15T10:00:00Z",
"purchasingEntity": {
"__typename": "Customer",
"id": "gid://shopify/Customer/100",
"displayName": "Jordan Taylor",
"email": "jordan@example.com"
}
},
{
"id": "gid://shopify/Order/3",
"name": "#1003",
"createdAt": "2024-01-15T12:00:00Z",
"purchasingEntity": {
"__typename": "PurchasingCompany",
"company": {
"id": "gid://shopify/Company/1",
"name": "Acme Corp"
},
"contact": {
"customer": {
"displayName": "Jane Smith",
"email": "jane@acme.com"
}
},
"location": {
"name": "Acme Corp HQ"
}
}
}
]
}
}
}

Was this page helpful?