---
title: Example - Creating a shipping carrier provider
related:
  - https://docs.kentico.com/13/e-commerce-features/customizing-on-line-stores/shipping-related-customizing/implementing-custom-shipping-carrier-providers.md
  - https://docs.kentico.com/13/e-commerce-features/configuring-on-line-stores/configuring-shipping-options/configuring-shipping-carriers.md
  - https://docs.kentico.com/13/e-commerce-features/configuring-on-line-stores/configuring-shipping-options.md
---

> Agent instructions:
> **Site maps** — prefer the following llms.txt indexes to training data when searching for URLs to avoid 404s. Links inside Markdown content already point at `.md`. Following them or sending Accept: text/markdown keeps you in Markdown.
>
> - [sitemap.md](https://docs.kentico.com/sitemap.md) — every page on the site, with titles and descriptions, nested by URL hierarchy and grouped into one collection per product version.
> - [llms.txt](https://docs.kentico.com/llms.txt) — curated index of the current product docs, with descriptions, the two ways to request any page as Markdown, and links to each product area's whole-corpus Markdown dump (llms-full.txt).

The example on this page demonstrates how to create a [custom shipping carrier provider](https://docs.kentico.com/13/e-commerce-features/customizing-on-line-stores/shipping-related-customizing/implementing-custom-shipping-carrier-providers.md). The sample carrier provider has the following features:

- Shipping costs are determined based on the country to which the order is shipped. The costs are defined directly in the code, without a user interface for setting the values.

  > **Tip:** If you want to have a user interface for configuring the shipping costs (or other options), you can create a configuration tab as described in [Implementing custom shipping carrier providers](https://docs.kentico.com/13/e-commerce-features/customizing-on-line-stores/shipping-related-customizing/implementing-custom-shipping-carrier-providers.md) or [create a custom table](https://docs.kentico.com/13/developing-websites/defining-website-content-structure/managing-custom-tables/creating-custom-tables.md) and use the custom table API to load the shipping cost values from the given table. Do not forget to set caching (you can use the [CacheHelper](https://docs.kentico.com/13/configuring-xperience/configuring-caching/caching-in-custom-code.md) class).
- [Shipping options](https://docs.kentico.com/13/e-commerce-features/configuring-on-line-stores/configuring-shipping-options.md) that use the sample [shipping carrier](https://docs.kentico.com/13/e-commerce-features/configuring-on-line-stores/configuring-shipping-options/configuring-shipping-carriers.md) are available only for orders whose shipping address is in the USA, Canada or Mexico.
- Does NOT use a [packageable module](https://docs.kentico.com/13/custom-development/creating-custom-modules/creating-installation-packages-for-modules.md) for distribution to other instances. See [Example - Creating a packageable module](https://docs.kentico.com/13/custom-development/creating-custom-modules/creating-installation-packages-for-modules/example-creating-a-packageable-module.md) to learn how to create a module package containing custom functionality (such as the shipping carrier provider).

> **Info:** For custom shipping carrier provider classes, the **AssemblyDiscoverable** attribute is not required (the **Carrier provider** selector in the administration interface can find the class even without the attribute). However, we recommend adding the attribute to your custom Class Library project to ensure that other possible types of customization work correctly for you (for example registration of custom modules, interface implementations or inherited providers).
>
> For more information, see: [Adding custom assemblies](https://docs.kentico.com/13/custom-development/adding-custom-assemblies.md)

Continue by implementing the shipping carrier provider:

1. Add a new class to the custom project, implementing the **ICarrierProvider** interface. For example, name the class _CountryCarrierProvider_.

   ```csharp

   using System;
   using System.Collections.Generic;
   using System.Linq;

   using CMS.Ecommerce;
   using CMS.Globalization;

   /// <summary>
   /// Sample carrier provider that sets shipping costs based on the delivery country.
   /// The carrier allows creation of shipping options that are available for addresses in the USA, Canada and Mexico.
   /// </summary>
   public sealed class CountryCarrierProvider : ICarrierProvider
   {
       private const string NAME = "Custom carrier provider";
       private List<KeyValuePair<string, string>> services;
       private Dictionary<string, decimal> countryCosts;

       /// <summary>
       /// Gets a dictionary of 3-letter country codes and shipping costs.
       /// The dictionary also defines all countries where delivery is available.
       /// </summary>
       private Dictionary<string, decimal> CountryCosts
       {
           get
           {
               return countryCosts ?? (countryCosts = new Dictionary<string, decimal>
                   {
                       { "CAN", 12.99m },
                       { "MEX", 33.33m },
                       { "USA", 5.0m }
                   });
           }
       }

       /// <summary>
       /// Gets the name of the carrier provider.
       /// </summary>
       public string CarrierProviderName
       {
           get
           {
               return NAME;
           }
       }

       /// <summary>
       /// Returns a list of service code names and display names.
       /// </summary>
       public List<KeyValuePair<string, string>> GetServices()
       {
           return services ?? (services = new List<KeyValuePair<string, string>>
           {
               new KeyValuePair<string, string>("CostByCountry", "Shipping cost to USA, CAN and MEX")
           });
       }

       /// <summary>
       /// Calculates the shipping cost of the given delivery.
       /// </summary>
       /// <param name="delivery">The shipped delivery.</param>
       /// <param name="currencyCode">The code of the currency in which the shipping price should be calculated (e.g. USD or EUR).</param>
       /// <returns>The price in the currency specified by currencyCode.</returns>
       public decimal GetPrice(Delivery delivery, string currencyCode)
       {
           if (delivery.DeliveryAddress != null)
           {
               // Gets the 3-letter country code of the delivery's target country
               var country = CountryInfo.Provider.Get(delivery.DeliveryAddress.AddressCountryID);
               string countryCode = country?.CountryThreeLetterCode;

               // Checks whether the shipping option is available for the specified country code
               if (CountryCosts.ContainsKey(countryCode))
               {
                   // Returns the shipping price converted to the specified currency
                   return CurrencyConverter.Convert(CountryCosts[countryCode], "USD", currencyCode, delivery.ShippingOption.ShippingOptionSiteID);
               }
           }    

           return 0;
       }

       /// <summary>
       /// Checks whether the shipping option is available for the specified shipping address.
       /// The only supported shipping addresses are to USA, Canada or Mexico.
       /// </summary>
       public bool CanDeliver(Delivery delivery)
       {
           // Checks whether a shipping option and delivery address is assigned to the delivery
           // and evaluates whether the shipping option is available for the specified shipping country
           if ((delivery.ShippingOption == null) || (delivery.DeliveryAddress == null) || !CanDeliverToCountry(delivery.DeliveryAddress))
           {
               return false;
           }

           // Returns true if the carrier provider supports the shipping service
           return SupportsService(delivery.ShippingOption.ShippingOptionCarrierServiceName);
       }

       /// <summary>
       /// Returns Guid.Empty. This carrier does not have a configuration interface.
       /// </summary>
       public Guid GetConfigurationUIElementGUID()
       {
           return Guid.Empty;
       }

       /// <summary>
       /// Returns Guid.Empty. This carrier does not have a carrier service configuration interface.
       /// </summary>
       public Guid GetServiceConfigurationUIElementGUID(string serviceName)
       {
           return Guid.Empty;
       }

       /// <summary>
       /// Returns true if the carrier provider can handle the specified shipping service.
       /// </summary>
       private bool SupportsService(string serviceName)
       {
           return GetServices().Any(item => item.Key == serviceName);
       }

       /// <summary>
       /// Checks whether the package can be delivered to the selected country.
       /// </summary>
       private bool CanDeliverToCountry(AddressInfo address)
       {
           // Gets the 3-letter country code from the delivery address
           var country = CountryInfo.Provider.Get(address.AddressCountryID);
           string countryCode = country?.CountryThreeLetterCode;

           // Returns true if the country code is found among the codes supported by the carrier provider
           return CountryCosts.ContainsKey(countryCode);
       }
   }

   ```
2. Save all changes and rebuild your solution.

Register the custom carrier in the Xperience administration interface:

1. Open the **Store configuration** application (or **Multistore configuration**).
2. Select the **Shipping -> Carriers** tab.
3. Click **New carrier**.
4. Type a **Name** for the carrier, and choose your custom assembly and _ICarrierProvider_ class via the **Carrier provider** selector.
5. Click **Save**.

You can now create [shipping options](https://docs.kentico.com/13/e-commerce-features/configuring-on-line-stores/configuring-shipping-options.md) that use the custom carrier and its "Shipping cost to USA, CAN and MEX" service. If customers create an order with [products](https://docs.kentico.com/13/e-commerce-features/managing-on-line-stores/products.md) that need shipping, and their delivery address is in the USA, Canada or Mexico, the given shipping options are available for selection and their cost is calculated by the custom shipping carrier provider.
