Promotions

In this example we take you through how you can use promotions to provide discounts to your customers.

What you’ll learn

  • What is a Connected Marketplacer integration
  • What are promotions
  • How promotions work in a Connected environment
  • GraphQL examples used to manipulate promotions

Connected Integrations

Before discussing the use of Promotions, it’s worthwhile learning about the different types of Marketplacer configuration (both current and deprecated), as these configurations impact how promotions work.


We will only be focused on “Connected Integrations” in this article, discussion on the other 2 types of pattern are provided for (historical) context only.


The different Marketplacer configuration types are outlined below:

Configuration TypeDescriptionCart & CheckoutStatus
Full StackInstances of Marketplacer that use a Marketplacer developed frontend and made use of Marketplacer cart and checkout functionality.MarketplacerDeprecated
HeadlessInstances of Marketplacer that use an Operator-developed frontend and made use of Marketplacer cart and checkout functionality via API.MarketplacerDeprecated
ConnectedInstances of Marketplacer that use an Operator-developed frontend as well as cart and checkout functionality.Operator suppliedActive

What are promotions?

Promotions can be created by either the Operator or Seller to enable the application of discounts on a customer order, however they work slightly differently depending on the Marketplacer configuration type:

Configuration TypeHow Promotions are applied
Full StackApplied automatically to the Marketplacer cart. Other than the existence of a valid, active promotion, no further action is required for promotions to be applied.
HeadlessApplied automatically to the Marketplacer cart. Other than the existence of a valid, active promotion, no further action is required for promotions to be applied.
ConnectedPromotions need to be explicitly applied to the order. The existence of a valid, active promotion does not mean it will be auto-applied to the order.

What about coupons?

To round out our conversation on the different types of Marketplacer configuration, and more specifically the types of discount that can be applied, it’s worth mentioning Coupons. Coupons, like Promotions, also provide the ability to apply discounts to an order but in a discretionary way. This is probably best expressed in the following table:

Configuration TypePromotionsCoupons
Full StackAuto applied to cartExplicitly applied to cart
HeadlessAuto applied to cartExplicitly applied to cart
ConnectedExplicitly applied to orderNot available

Promotions could be used to drive coupon-like behavior

The takeaway point here is that in a Connected configuration, the use of Promotions is at the discretion of the Marketplace Operator, and can be used to drive both auto applied and discretionary (coupon-like) discount behaviors.

How to use promotions in a Connected Environment

The following high-level journey describes how you would employ Promotions in a Connected configuration.

Connected Promotions Flow

In the remainder of this article we will follow the above journey and illustrate the Marketplacer specific touch points, noting that we will only be covering the API and not the UI.

1. Creating a promotion

To create a promotion via the API you can use the promotionUpsert mutation, this can be used by both Operators and Sellers:

mutation CreateAPromotion{
	promotionUpsert(
		input: {
			attributes: {
				name: "10% Off"
				description: "10% off the listed price"
				discountAmount: 10
				discountType: PERCENT
				# You can obtain Brand Ids via the "brands" query
				brandsExcludedIds: ["QnJhbmQtNA==", "QnJhbmQtMTk="]
				# You can obtain Taxon Ids via the "taxons" or "prototypes" queries
				categoriesIncludedIds: ["VGF4b24tNzg="]
			}
		}
	) {
		errors {
			field
			messages
		}
		promotion {
			id
			name
		}
	}
}

In the above example we have not included every possible configuration, refer to the promotionInput type for more information.


2. Ingest promotions

Having created promotions in Marketplacer, you would then need to ingest them into your domain, you can use the promotions query to do this:

query ReturnPromotions {
	promotions(status: "active") {
		nodes {
			id
			seller {
				id
				businessName
			}
			name
			teaser
			description
			startDate
			endDate
			minimumSpend
			maximumSpend
			suspended
			discountType
			discountAmount
			freeShipping
			costPercentageBorneByMarketplace
			loyaltyProgramLevels {
				nodes {
					name
				}
			}
			freeShippingDomesticOnly
			brandsIncluded {
				edges {
					node {
						name
					}
				}
			}
			brandsExcluded {
				edges {
					node {
						name
					}
				}
			}
			categoriesIncluded {
				edges {
					node {
						displayName
					}
				}
			}
			categoriesExcluded {
				edges {
					node {
						displayName
					}
				}
			}
			advertsIncluded {
				edges {
					node {
						description
					}
				}
			}
			advertsExcluded {
				edges {
					node {
						description
					}
				}
			}
			variantsIncluded {
				edges {
					node {
						sku
					}
				}
			}
			variantsExcluded {
				edges {
					node {
						sku
					}
				}
			}
			saleItemsExcluded
		}
	}
}

3. Render Promotions

This step would occur entirely in the Operator domain, outside of Marketplacer, it has been included for guidance purposes only.

You can use the data for promotions obtained in Step 2 to:

  • Display as site wide promotions on your products
  • Act as “coupons” that can be applied at your discretion

4. Apply Promotions at checkout

This step would occur entirely in the Operator domain, outside of Marketplacer, it has been included for guidance purposes only.

You would need to ensure that any relevant promotions that have been applied / selected are applied at your checkout step.

5. Place order in Marketplacer

A full overview of how you can create orders is covered in this article, (including the application of promotions).

Note: promotions are applied to order line items.

To apply a promotion to an order you need to:

  1. Provide the pre-discount value for the line item (in cents)
  2. Obtain the promotion id that you would like to apply
  3. Apply the (negative) promotion amount in cents to the line item
  4. Supply the amount (in cents) that you want to withhold from seller remittances
  5. Provide a description for the promotion (this will appear on customer invoices)

An example mutation is shown below.

mutation {
	orderCreate(
		input: {
			order: {
				firstName: "David"
				surname: "Tennant"
				phone: "972544939658"
				emailAddress: "drwho@email.com"
				address: {
					address: "1 Church Street"
					city: "Melbourne"
					country: { code: "AU" }
					postcode: "3000"
					state: { name: "Victoria" }
				}
			}
			lineItems: [
				{
					variantId: "VmFyaWFudC0xMDA0Nzk="
					quantity: 1
					cost: { amount: 27000 }
					postage: { amount: 0 }
					adjustments: [
						{
							adjustmentType: PROMOTION
							amountCents: -2700
							amountToWithholdFromSellerRemittanceCents: 0
							description: "10% off promotion"
							sourceId: "UHJvbW90aW9uLTI1"
						}
					]
				}
			]
		}
	) {
		order {
			id
			legacyId
			totalCents
			companyName
			invoices {
				nodes {
					id
					legacyId
					lineItems {
						id
					}
				}
			}
		}
		errors {
			field
			messages
		}
	}
}

Other points related to the application of promotions:

  • You need to calculate / supply the promotion discount to apply (amountCents for the promotion)
  • You can apply multiple, separate promotions to the same line item, an example of this is shown below for the lineItem definition for orderCreate (for brevity we have omitted the rest of the mutation call):
lineItems: [
  {
    variantId: "VmFyaWFudC0xMDAyMDY="
    quantity: 1
    cost: { amount: 20000 }
    postage: { amount: 0 }
    adjustments: [
      {
        adjustmentType: PROMOTION
        amountCents: -2000
        amountToWithholdFromSellerRemittanceCents: 0
        description: "10% off promotion"
        sourceId: "UHJvbW90aW9uLTE3OQ=="
      }
      {
        adjustmentType: PROMOTION
        amountCents: -1000
        amountToWithholdFromSellerRemittanceCents: 0
        description: "5% off coupon"
        sourceId: "UHJvbW90aW9uLTE4MA=="
      }
    ]
  }
]

6. Seller fulfills order

This step covers regular order fulfillment on the part of the Seller. If using the Seller API, the seller can understand the adjustments applied to line items by querying an invoice in the following way:

query GetMyOrders {
  node(id: "SW52b2ljZS0xMzU2Ng==") {
    ... on Invoice {
      legacyId
      id
      discountCents
      subtotalCents
      totalCents
      commissionAmountCents
      statusFlags
      adjustments {
        ...adjuistmentFrgament
      }
      lineItems {
        id
        legacyId
        quantity
        status
        adjustments {
          ...adjuistmentFrgament
        }
      }
    }
  }
}
fragment adjuistmentFrgament on Adjustment {
  id
  amountCents
  adjustmentType
  appliesTo
  description
  amountToWithholdFromSellerRemittanceCents
}

This would result in a response similar to the following:

{
  "data": {
    "node": {
      "legacyId": 13566,
      "id": "SW52b2ljZS0xMzU2Ng==",
      "discountCents": -3000,
      "subtotalCents": 20000,
      "totalCents": 17000,
      "commissionAmountCents": 1000,
      "statusFlags": [
        "PAID"
      ],
      "adjustments": [],    👈 Custom Fees would appear here     
      "lineItems": [
        {
          "id": "TGluZUl0ZW0tMzk1Ng==",
          "legacyId": 3956,
          "quantity": 1,
          "status": "ALLOCATED",
          "adjustments": [    👈 Promotions appear here 
            {
              "id": "QWRqdXN0bWVudC00Mzky",
              "amountCents": -2000,
              "adjustmentType": "PROMOTION",
              "appliesTo": "SUBTOTAL_DISCOUNT",
              "description": "10% off promotion",
              "amountToWithholdFromSellerRemittanceCents": 0
            },
            {
              "id": "QWRqdXN0bWVudC00Mzkz",
              "amountCents": -1000,
              "adjustmentType": "PROMOTION",
              "appliesTo": "SUBTOTAL_DISCOUNT",
              "description": "5% off coupon",
              "amountToWithholdFromSellerRemittanceCents": 0
            }
          ]
        }
      ]
    }
  }
}