Setting Up Logistics for AlterCPA and CPAmoe

Setting Up Logistics for AlterCPA and CPAmoe

Xoxo, everyone — it’s Reznik, and today we’re going to whip up some killer logistics for AlterCPA or CPAmoe. Well, actually, you’re the one who’ll be whipping it up, and how killer it turns out is on you too. I’ll just toss in a couple of solid tips.

The AlterCPA platform lets you track parcel delivery for your COD traffic and keep an eye on the buyout rate automatically. As of this writing, the built-in delivery types don’t give you a whole lot of room to maneuver in logistics. And when it comes to setting up delivery schemes designed to outsmart courier and postal services — it flat-out doesn’t support that, and never will. So our way out is to expand logistics capabilities ourselves, in other words, to pull off some “schemosis”.

Schemosis (from “scheme” + “-osis,” like a diagnosis) – a manager’s irresistible urge to cut costs through crafty workarounds of normal operations and assorted ways of conning carriers. It’s usually a degenerate form of “schematics” or “a scheme” – the smart, perfectly legal practice of borrowing the best parts of different competing solutions within the same field.

For this, we’re going to need a quality programmer, at least one unit of them. The rest of this guide is meant to be studied strictly paired with a competent web-service developer. Without a good programmer, nothing described below is happening. No way.

This guide works whether you’re setting up your own logistics service alongside full-featured AlterCPA, or hooking up logistics for CPAmoe, the free CRM for COD CPA business. The differences between the two are minimal, and we’ll call them out separately where they come up.

Solution Architecture

Our bare-minimum plan is to build some kind of web service that absolutely has to handle the following tasks:

  1. Export orders ready to ship, from your network on AlterCPA or your CPAmoe account.
  2. Create shipment records with the carrier based on that data, and add the matching marks to the order on the AlterCPA / CPAmoe side.
  3. Pull the current shipment status from the carrier and assemble it into a consistent history of the parcel’s delivery status changes.
  4. Return the parcel’s delivery status history on request from AlterCPA / CPAmoe, in the strict format used by the standard delivery type.

Let’s call our creation the “logistics service”. Further down, we’ll look at a few more useful things this service can do, but first, let’s nail down these four mandatory points.

Exporting Orders for Delivery

The AlterCPA platform’s advertiser API makes it fairly convenient to export orders that need delivery. Let’s say we’ll export every order in the “Shipping” status under the “Standard” delivery service, which is exactly what that integration is meant for. You can also export orders from “Packing” if your logistics service is running fulfillment.

UPD: a couple of years later, a new way to send leads showed up, described in the article “Creating a Simple Delivery Service” – it doesn’t need any extra APIs, everything runs through webhooks.

The “List orders” API function from the advertiser section will help here – it’s documented for your network, for example at: ui.cpa.moe/help/api.en.php#orderlist. At first glance, it’s a horrifyingly clunky interface, since it won’t let you export just the parcels that don’t need delivery. And that’s exactly how it would be, if AlterCPA didn’t have its own undocumented function for this very case.

We call the function with the following GET parameters:

  • trackon set to 0 exports every order that doesn’t have a tracking code yet.
  • delivery set to 1 picks every order using the “Standard” delivery type.
  • status set to 7 narrows the selection down to the “Shipping” status; use 6 for “Packing”.
  • You can also add stage with an extended status ID, or stagename with its string code, to export parcels at a specific stage.

For CPAmoe, for instance, the URL will look something like this:

https://api.cpa.moe/comp/list.json?id=x-x&trackon=0&delivery=1&status=6

What you get back is a list of orders ready to ship. It’s best to study the exact field set in the API docs – it includes all the recipient’s details and the full list of items in the order.

Sending Orders to the Carrier

The orders we’ve exported now actually need to be sent. To do that, either right away or after some processing, we hand the orders off to the carrier’s interface.

We won’t get into the actual process of handing orders off to whichever carrier you’re using – that whole problem rests entirely on the mighty shoulders of your programmer. There’s only one thing we care about here: once the order’s added to the carrier, we get back some kind of tracking code.

We need to attach that tracking code to the order in AlterCPA and turn tracking on for it. The order-editing API function will help here, for example: ui.cpa.moe/help/api.en.php#orderedit

We need to pass it the following fields:

  • oid with the order’s ID on the AlterCPA side
  • trackon set to 1 to turn on delivery tracking
  • track with our parcel’s tracking code

For CPAmoe, the URL will look like this:

https://api.cpa.moe/comp/edit.json?id=x-x&oid=123&trackon=1&track=AB123456

It’s best to make this request right after you export the order from AlterCPA and send it off to the carrier. Otherwise, the order will just get exported again on the next pull from the previous step.

If you’re not sending orders right away, use some intermediate tracking code of your own, one that maps unambiguously to the order in your logistics service’s database. You’ll use it to check on the parcel’s status later on.

Exporting Delivery Statuses

Exporting statuses, just like adding orders to the carrier, is once again on your programmer’s plate. Usually, this task isn’t especially hard. But sometimes the urge to track down whoever built that parcel-tracking API and give them a nice, firm handshake – right around the neck – goes a little too far.

There are a few recommendations for exporting statuses that’ll make your integration a lot smoother:

  • Always store the entire delivery status history, not just the latest one, so it can be exported to AlterCPA without any trouble.
  • Record the time each status appeared. If the carrier’s own statuses don’t come with a timestamp, use the time you first saw that status show up during a check.
  • If you can, export the ZIP code and the city where each status in the parcel’s movement history occurred. That can come in handy later for manual delivery analysis.
  • If needed, save the text comments attached to statuses in the movement history too – they can be useful. Carriers often use these comments to flag a rescheduled delivery, issues reaching the customer, and other details that matter to your call center.

You can either export this data automatically and store it in your logistics service’s database, or generate the export on request from AlterCPA, as described below.

Providing AlterCPA with the Parcel’s Delivery History

Twice a day, AlterCPA can request a parcel’s delivery history. To set up the export, go to the delivery services settings for the company in question, activate the “Standard” delivery service, and enter the URL of your logistics service’s API function – the one that returns the delivery history – in the URL field, in the format described below.

When you set the check URL, add the {code} macro and it’ll get replaced with the parcel’s tracking code, the one you added back in step two of the algorithm. If you don’t include the {code} macro in the address, the tracking code gets tacked onto the end of the URL instead.

At that URL, your logistics service needs to return the status history as JSON in the form of a simple array of objects, each one corresponding to a status. Every status needs to be sorted by time, oldest to newest. Sticking to the exact structure below is mandatory.

A status object can contain the following fields:

  • status – required field with the delivery status string, list below
  • time – required field with the time the status occurred, as a UNIX timestamp
  • country – the country’s ISO code
  • zip – postal or ZIP code
  • city – city or locality
  • comment – a free-form comment on the status

The status field can hold one of the following values:

  1. wait – the parcel is waiting to be shipped.
  2. transfer – the parcel is on its way, moves the order to the “Delivery” status.
  3. problem – something went wrong with delivery, the advertiser needs to step in.
  4. delivered – the parcel reached its destination, moves the order to the “Delivered” status.
  5. paid – the parcel was successfully bought out, moves the order to the “Paid” status.
  6. return – the parcel was returned or written off, moves the order to the “Returned” status.
  7. comment – a free-form comment that doesn’t change the parcel’s state.

A sample function response might look like this:

[
   {
      "status":"delivered",
      "time":1234567890,
      "zip":"AB1234",
      "city":"Neverland"
   },
   {
      "status":"paid",
      "time":1234567891,
      "comment":"Awesome!"
   }
]

UPD: the new article “Creating a Simple Delivery Service” goes into more detail on exporting statuses, and it’s got a sample file too.

Printing Documents

In the AlterCPA interface, an operator can request a document package for a parcel. To turn this on, the “Standard” delivery service needs the URL field set to your logistics service’s API function that returns a link to the document package file, in the format described below.

When you set the export URL, add the {code} macro and it’ll be replaced with the parcel’s tracking code, the one you added in step two of the algorithm. If the {code} macro isn’t in the address, the tracking code gets added to the end of the URL.

At that URL, your logistics service should return a JSON response with two fields: status and url. The status field should be ok if the document package was put together successfully, and error if something went wrong. The url field should hold the link to the document package that gets shown to the user.

An example of a successful response might look like this:

{
    "status": "ok",
    "url": "https://altercpa.one/docs/abcdef123456.zip"
}

UPD: the new article “Creating a Simple Delivery Service” covers preparing documents in more detail, with a sample file too.

The Simplest Way to Implement This

Your logistics service can boil down to two logical functions, or even just two files, doing the following:

  1. Export parcels from the system per step 1, and ship them right away, marking them up per step 2.
  2. Receive requests from the system as described in step 4, quietly making the step-3 request in the background and returning the result formatted per step 4.

This simple little mechanism is all it takes to run your own delivery service, one that doesn’t exist yet in AlterCPA or CPAmoe. And by the time you’re reading this article, the one you need almost certainly still isn’t there – otherwise, why would you even be reading this!

Multiple Delivery Services

You’ve probably got a fair question by now: if we’re only using the “Standard” delivery type, how do we work with multiple delivery services? Fair question, and there’s an answer to it, not without a light whiff of the twigs-and-turds school of software engineering.

I picked up this life hack from a few other CRMs. It comes down to creating special delivery “products”. AlterCPA’s and CPAmoe’s product settings even have a dedicated product group built in for exactly this.

An example of an order’s goods field, containing both the main item and a delivery item:

[
   {
      "id":11,
      "name":"Dick Extender",
      "short":"dexter",
      "count":2,
      "price":990,
      "param":{
         "abc":"123",
         "def":"456"
      }
   },
   {
      "id":22,
      "name":"Courier Delivery",
      "short":"courier",
      "count":1,
      "price":350,
      "param": []
   }
]

To avoid identifying delivery types by their full name, CPAmoe recommends using the “Short Name” field to set a string code for the delivery type, for example courier. When you export order data, that shows up on the item in the short field. Owners of full-featured AlterCPA can also use custom item parameters for this, which show up in the export under the params field.

Schemosis as a Diagnosis

In the CPA world, advertisers would skip a meal for the chance to cook up some cunning scheme to cut costs. And delivery is one of the hungriest line items there is – trim it down, and the profits can be fabulous.

The most classic way to optimize a delivery service is to use multiple accounts – dozens, hundreds, thousands of them – for sending parcels. Sometimes they’re even registered to individual people, to make returns or other processes easier.

For a setup like that, the simple send-a-parcel approach won’t cut it anymore, and it’s worth building your logistics service as its own serious piece of software – one that stores all the necessary shipment data and talks to some kind of external interface.

Set up storage for the following types of data:

  • Logistics service accounts. This is the table you’ll pick a suitable account from, using whatever clever algorithm you’ve built – presumably something more sophisticated than ORDER BY RAND() – to decide which account’s name ships the selected parcel. Besides the shipping access key itself, it’s worth storing the sender’s name, the return address, and various extra delivery settings, such as the package types in use and so on. Build yourself a convenient interface for managing these accounts, especially for checking whether they’re still active, so you can promptly exclude any that have used up their limit.
  • Parcel data. In this table, store the recipient’s details (full name, phone number, delivery address) and the order contents. Every parcel needs to be tied to one of the accounts from the list above. You won’t need a separate table for the order’s line items – a serialized JSON text field is plenty. There’s no need to build your own stats or track inventory here; the warehouse management interface in both paid AlterCPA and free CPAmoe already handles that beautifully.
  • Parcel status history. This one really does deserve its own table. Depending on which carriers you’re using, you might pull order data far more often than twice a day. That way, whenever AlterCPA asks, you can hand over a ready-made export from this table almost instantly. When you need to, you can also directly ask AlterCPA / CPAmoe to refresh a parcel’s tracking info using the method described below.

A logistics service built like that will let you run whatever scheme your heart desires. It’ll also be ready for any future features you might need for delivery.

Asking AlterCPA / CPAmoe to Refresh Tracking

Sometimes a parcel gets delivered a lot faster than even the “modernized” Russian Post pictured in this article can manage. Or problems crop up mid-delivery that need the call center to jump on them right away. In situations like that, checking the status twice a day just won’t cut it.

We can force a status refresh with a request as simple as this:

https://api.cpa.moe/comp/retrack.json?id=x-x&oid=123

The oid parameter should hold the order’s ID on the AlterCPA / CPAmoe side. The assumption here is that if you’re running a proper logistics service, you’re already storing that ID in your parcel data table.

What Else Is (and Isn’t) Worth Building?

Now that you’ve built a whole logistics service just to run your schemes, it’s worth thinking about rounding out its feature set with things like:

  • Preparing and printing documents for a batch of parcels, for a smooth handoff to the courier
  • Preparing and printing shipping labels for parcels
  • Calculating delivery costs for parcels

You don’t need to give a second thought to any of the following:

  • Packing: already handled in AlterCPA and CPAmoe, “Extended order statuses” will come in handy
  • Delivery calls: already handled in AlterCPA and CPAmoe, operator teams for delivery calls and the ability to easily reschedule a callback on orders in any status will come in handy. In the full version, you can even hand delivery-call orders off to third-party call centers.
  • Warehouse management: available in AlterCPA and CPAmoe, the full version even supports syncing stock levels with third-party services.
  • Buyout analysis: available in AlterCPA and CPAmoe, for orders it’s in the “Delivery Analytics” section, for items it’s in the warehouse’s “Statistics” section.

With this guide, it’ll be a lot easier to build your own delivery workflow in full-featured AlterCPA or CPAmoe, the free CRM for CPA networks.