AfterShip – WooCommerce Tracking - Version 1.9.19

Version Description

  • Update plugin banner
Download this release

Release Info

Developer aftership
Plugin Icon 128x128 AfterShip – WooCommerce Tracking
Version 1.9.19
Comparing to
See all releases

Code changes from version 1.9.18 to 1.9.19

aftership.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: AfterShip - WooCommerce Tracking
4
  Plugin URI: http://aftership.com/
5
  Description: Add tracking number and carrier name to WooCommerce, display tracking info at order history page, auto import tracking numbers to AfterShip.
6
- Version: 1.9.18
7
  Author: AfterShip
8
  Author URI: http://aftership.com
9
 
3
  Plugin Name: AfterShip - WooCommerce Tracking
4
  Plugin URI: http://aftership.com/
5
  Description: Add tracking number and carrier name to WooCommerce, display tracking info at order history page, auto import tracking numbers to AfterShip.
6
+ Version: 1.9.19
7
  Author: AfterShip
8
  Author URI: http://aftership.com
9
 
api/class-aftership-api-v2-json-handler.php DELETED
@@ -1,129 +0,0 @@
1
- <?php
2
- /**
3
- * AfterShip API
4
- *
5
- * Handles parsing JSON request bodies and generating JSON responses
6
- *
7
- * @author AfterShip
8
- * @category API
9
- * @package AfterShip/API
10
- * @since 1.0
11
- */
12
-
13
- if (!defined('ABSPATH')) {
14
- exit;
15
- } // Exit if accessed directly
16
-
17
- class AfterShip_API_V2_JSON_Handler implements AfterShip_API_Handler
18
- {
19
- /**
20
- * Get the content type for the response
21
- *
22
- * @return string
23
- * @since 2.1
24
- */
25
- public function get_content_type()
26
- {
27
- return 'application/json; charset=' . get_option('blog_charset');
28
- }
29
-
30
- /**
31
- * Parse the raw request body entity
32
- *
33
- * @param string $body the raw request body
34
- *
35
- * @return array|mixed
36
- * @since 2.1
37
- *
38
- */
39
- public function parse_body($body)
40
- {
41
- return json_decode($body, true);
42
- }
43
-
44
- /**
45
- * Generate a JSON response given an array of data
46
- *
47
- * @param array $data the response data
48
- *
49
- * @return string
50
- * @since 2.1
51
- *
52
- */
53
- public function generate_response($data)
54
- {
55
- if (isset($_GET['_jsonp'])) {
56
- // JSONP enabled by default
57
- if (!apply_filters('aftership_api_jsonp_enabled', true)) {
58
-
59
- WC()->api->server->send_status(400);
60
-
61
- $data = [
62
- [
63
- 'code' => 'aftership_api_jsonp_disabled',
64
- 'message' => __('JSONP support is disabled on this site', 'aftership')
65
- ]
66
- ];
67
- }
68
-
69
- // Check for invalid characters (only alphanumeric allowed)
70
- if (preg_match('/\W/', $_GET['_jsonp'])) {
71
-
72
- WC()->api->server->send_status(400);
73
-
74
- $data = [
75
- [
76
- 'code' => 'aftership_api_jsonp_callback_invalid',
77
- __('The JSONP callback function is invalid', 'aftership')
78
- ]
79
- ];
80
- }
81
-
82
- return $_GET['_jsonp'] . '(' . json_encode($data) . ')';
83
- }
84
-
85
- $ok = [
86
- 'meta' => [
87
- 'code' => 20000,
88
- 'type' => 'OK',
89
- 'message' => 'Everything worked as expected'
90
- ],
91
- 'data' => $data
92
- ];
93
-
94
- if (isset($data['errors'])) {
95
- $error = [
96
- 'meta' => [
97
- 'code' => $this->map_error_code($data['errors'][0]['code']),
98
- 'type' => $data['errors'][0]['code'],
99
- 'message' => $data['errors'][0]['message'],
100
-
101
- ],
102
- 'data' => '{}'
103
- ];
104
- return json_encode($error);
105
- }
106
-
107
-
108
- return json_encode($ok);
109
- }
110
-
111
- /**
112
- * get error code by error message
113
- * @param $code_text
114
- * @return int
115
- */
116
- private function map_error_code($code_text)
117
- {
118
- $code = 40010;
119
- switch ($code_text) {
120
- case 'aftership_api_disabled':
121
- $code = 400011;
122
- break;
123
- default:
124
- break;
125
- }
126
-
127
- return $code;
128
- }
129
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
api/class-aftership-api-v2-orders.php DELETED
@@ -1,424 +0,0 @@
1
- <?php
2
- /**
3
- * AfterShip API Orders Class
4
- *
5
- * Handles requests to the /orders endpoint
6
- *
7
- * @author AfterShip
8
- * @category API
9
- * @package AfterShip/API
10
- * @since 1.0
11
- */
12
-
13
- if (!defined('ABSPATH')) {
14
- exit;
15
- } // Exit if accessed directly
16
-
17
- class AfterShip_API_V2_Orders extends AfterShip_API_Resource
18
- {
19
-
20
- /** @var string $base the route base */
21
- protected $base = '/v2/orders';
22
-
23
- /**
24
- * Register the routes for this class
25
- *
26
- * GET /orders
27
- *
28
- * @param array $routes
29
- *
30
- * @return array
31
- * @since 2.1
32
- *
33
- */
34
- public function register_routes($routes)
35
- {
36
- # GET /orders/ping
37
- $routes[$this->base . '/ping'] = [
38
- [[$this, 'ping'], AfterShip_API_Server::READABLE],
39
- ];
40
-
41
- # GET /orders
42
- $routes[$this->base] = [
43
- [[$this, 'get_orders'], AfterShip_API_Server::READABLE]
44
- ];
45
-
46
- # GET /orders/:id
47
- $routes[$this->base . '/(?P<id>[\d]+)'] = [
48
- [[$this, 'get_order'], AfterShip_API_Server::READABLE],
49
- ];
50
-
51
- return $routes;
52
- }
53
-
54
- /**
55
- * heath checkendpoint for wordpress url validation
56
- *
57
- * @return string
58
- * @since 2.1
59
- */
60
- public function ping()
61
- {
62
- return 'pong';
63
- }
64
-
65
- /**
66
- * Get orders
67
- *
68
- * @param string $updated_at_min
69
- * @param string $updated_at_max
70
- * @param string $max_results_number
71
- *
72
- * @return array
73
- * @throws Exception
74
- * @since 2.1
75
- *
76
- */
77
- public function get_orders($updated_at_min = null, $updated_at_max = null, $max_results_number = null)
78
- {
79
- $args = [
80
- 'updated_at_min' => $updated_at_min,
81
- 'updated_at_max' => $updated_at_max,
82
- 'orderby' => 'modified',
83
- 'order' => 'ASC',
84
- 'limit' => $max_results_number,
85
- 'page' => !empty($_GET['page']) && intval($_GET['page']) > 1 ? absint($_GET['page']) : 1
86
- ];
87
-
88
- $query = $this->query_orders($args);
89
-
90
- //define pagination
91
- $pagination = [
92
- 'page' => $query->query['paged'],
93
- 'limit' => intval($query->query['posts_per_page']),
94
- 'total' => intval($query->found_posts)
95
- ];
96
-
97
- $orders = [];
98
- foreach ($query->posts as $order_id) {
99
- if (!$this->is_readable($order_id)) {
100
- continue;
101
- }
102
- $orders[] = $this->get_order($order_id);
103
- }
104
-
105
- return ['orders' => $orders, 'pagination' => $pagination];
106
- }
107
-
108
- /**
109
- * get single order by id
110
- * @param $id
111
- * @return array|int|WP_Error
112
- * @throws Exception
113
- */
114
- public function get_order($id)
115
- {
116
- $weight_unit = get_option('woocommerce_weight_unit');
117
- // ensure order ID is valid & user has permission to read
118
- $id = $this->validate_request($id, 'shop_order', 'read');
119
- if (is_wp_error($id)) {
120
- return $id;
121
- }
122
- $order = new WC_Order($id);
123
- $customer = new WC_Customer($order->get_customer_id());
124
- $current_shipping_method = current($order->get_shipping_methods());
125
- $shipping_method = null;
126
- if($current_shipping_method['method_id'] && $current_shipping_method['name']) {
127
- $shipping_method = [
128
- 'code' => $current_shipping_method['method_id'],
129
- 'name' => $current_shipping_method['name'],
130
- ];
131
- }
132
- $order_data = [
133
- 'id' => (string)$order->get_id(),
134
- 'order_number' => $order->get_order_number(),
135
- 'order_name' => $order->get_order_number(),
136
- 'taxes_included' => ($order->get_total_tax() > 0),
137
- 'shipping_method' => $shipping_method,
138
- 'order_total' => [
139
- 'currency' => $order->get_currency(),
140
- 'amount' => (float)wc_format_decimal($order->get_total(), 2),
141
- ],
142
- 'note' => $order->get_customer_note(),
143
- 'locale' => get_locale(),
144
- 'metrics' => [
145
- 'placed_at' => $this->server->format_datetime($order->get_date_created()),
146
- 'updated_at' => $this->server->format_datetime($order->get_date_modified()),
147
- 'fully_shipped_at' => null,
148
- 'expected_earliest_delivery_at' => null,
149
- 'expected_last_delivery_at' => null,
150
- ],
151
- 'customer' => [
152
- 'id' => (string)$order->get_customer_id(),
153
- 'first_name' => $customer->get_first_name(),
154
- 'last_name' => $customer->get_last_name(),
155
- 'emails' => ($customer->get_email()) ? [$customer->get_email()] : [],
156
- 'phones' => ($customer->get_billing_phone()) ? [[
157
- 'country_code' => null,
158
- 'number' => $customer->get_billing_phone()
159
- ]] : [],
160
- ],
161
- 'shipping_address' => [
162
- 'first_name' => $order->get_shipping_first_name(),
163
- 'last_name' => $order->get_shipping_last_name(),
164
- 'company' => $order->get_shipping_company(),
165
- 'address_line_1' => $order->get_shipping_address_1(),
166
- 'address_line_2' => $order->get_shipping_address_2(),
167
- 'city' => $order->get_shipping_city(),
168
- 'state' => $order->get_shipping_state(),
169
- 'country' => $this->server->convert_country_code($order->get_shipping_country()),
170
- 'postal_code' => $order->get_shipping_postcode(),
171
- 'email' => $order->get_billing_email(),
172
- 'phone' => [
173
- 'country_code' => null,
174
- 'number' => $order->get_billing_phone()
175
- ],
176
- 'address_type' => null,
177
- 'tax_number' => null,
178
- ],
179
- 'billing_address' => array(
180
- 'first_name' => $order->get_billing_first_name(),
181
- 'last_name' => $order->get_billing_last_name(),
182
- 'company' => $order->get_billing_company(),
183
- 'address_line_1' => $order->get_billing_address_1(),
184
- 'address_line_2' => $order->get_billing_address_2(),
185
- 'city' => $order->get_billing_city(),
186
- 'state' => $order->get_billing_state(),
187
- 'postal_code' => $order->get_billing_postcode(),
188
- 'country' => $this->server->convert_country_code($order->get_billing_country()),
189
- 'email' => $order->get_billing_email(),
190
- 'phone' => [
191
- 'country_code' => null,
192
- 'number' => $order->get_billing_phone()
193
- ],
194
- 'address_type' => null,
195
- 'tax_number' => null,
196
- ),
197
- 'status' => $order->get_status(),
198
- 'items' => [],
199
- 'trackings' => []
200
- ];
201
-
202
-
203
- // add line items
204
- foreach ($order->get_items() as $item_id => $item) {
205
- if (is_callable($item, 'get_product')) {
206
- $product = $item->get_product();
207
- } else {
208
- $product = $order->get_product_from_item($item);
209
- }
210
- if (empty($product)) continue;
211
- $weight = $product->get_weight();
212
- $product_id = (isset($product->variation_id)) ? $product->variation_id : $product->get_id();
213
- // set the response object
214
- $terms_tags = get_the_terms($product_id, 'product_tag');
215
- $product_tags = [];
216
- foreach ($terms_tags as $termsKey => $termsVal) {
217
- $product_tags[] = $termsVal->name;
218
- }
219
- $product_categories = [];
220
-
221
- $categories = get_the_terms($product_id, 'product_cat');
222
- foreach ($categories as $categoriesKey => $categoriesVal) {
223
- $product_categories[] = $categoriesVal->name;
224
- }
225
- $order_data['items'][] = [
226
- 'id' => (string)$item_id,
227
- 'product_id' => (string)$product_id,
228
- 'sku' => is_object($product) ? $product->get_sku() : null,
229
- 'title' => $item['name'],
230
- 'quantity' => (int)$item['qty'],
231
- 'returnable_quantity' => (int)($item['qty'] - $order->get_qty_refunded_for_item($item_id)),
232
-
233
- 'unit_weight' => [
234
- 'unit' => $weight_unit,
235
- 'value' => (float)$weight,
236
- ],
237
- 'unit_price' => [
238
- 'currency' => $order->get_currency(),
239
- 'amount' => (float)wc_format_decimal($order->get_item_total($item), 2),
240
- ],
241
- 'discount' => null,
242
- 'image_urls' => wp_get_attachment_url($product->image_id) ? [wp_get_attachment_url($product->image_id)] : [],
243
- 'tags' => $product_tags,
244
- 'categories' => $product_categories,
245
- ];
246
- }
247
-
248
- // tracking field will be
249
- /*
250
- {
251
- tracking_number: fulfillment.tracking_number,
252
- slug: mapped_slug,
253
- additional_fields: {
254
- account_number: null,
255
- key: null,
256
- postal_code: (data.shipping_address && data.shipping_address.zip) ? data.shipping_address.zip : null,
257
- ship_date: moment(fulfillment.updated_at).utcOffset('+0000').format('YYYYMMDD'),
258
- state: null,
259
- origin_country: null,
260
- destination_country: (data.shipping_address && data.shipping_address.country_code) ? beautifyAddress({country: data.shipping_address.country_code}).country_iso3 : null,
261
- },
262
- }
263
- */
264
-
265
- $trackings = [];
266
- //The function definition will be available after installing the aftership plugin.
267
- if(function_exists('order_post_meta_getter')) {
268
- $aftership_tracking_number = order_post_meta_getter($order, 'aftership_tracking_number');
269
- if (!empty($aftership_tracking_number)) {
270
- $trackings[] = [
271
- 'slug' => order_post_meta_getter($order, 'aftership_tracking_provider'),
272
- 'tracking_number' => $aftership_tracking_number,
273
- 'additional_fields' => [
274
- 'postal_code' => order_post_meta_getter($order, 'aftership_tracking_postal'),
275
- ],
276
- ];
277
- }
278
-
279
- // 兼容 woocommerce 官方的 tracking 插件
280
- $woocommerce_tracking_arr = order_post_meta_getter($order, 'wc_shipment_tracking_items');
281
- if (empty($aftership_tracking_number) && !empty($woocommerce_tracking_arr)) {
282
- foreach ($woocommerce_tracking_arr as $trackingKey => $trackingVal) {
283
- $trackingArr = $this->getTrackingInfoByShipmentTracking($trackingVal);
284
- if (!empty($trackingArr)) {
285
- $trackings[] = [
286
- 'slug' => $trackingArr['tracking_provider'],
287
- 'tracking_number' => $trackingVal["tracking_number"],
288
- 'additional_fields' => [
289
- 'postal_code' => $trackingArr['tracking_postal_code'],
290
- ],
291
- ];
292
- } else {
293
- $trackings[] = [
294
- 'slug' => $trackingVal["tracking_provider"],
295
- 'tracking_number' =>$trackingVal["tracking_number"],
296
- 'additional_fields'=> [
297
- 'postal_code' => null,
298
- ]
299
- ];
300
- }
301
- }
302
- }
303
- $order_data['trackings'] = $trackings;
304
- }
305
-
306
- return $order_data;
307
- }
308
-
309
- /**
310
- * 从wc ShipmentTracking 插件获取 Postalcode - postnl
311
- * @param $tracking_items
312
- * @return array
313
- */
314
- private function getTrackingInfoByShipmentTracking($tracking_items)
315
- {
316
- if (!isset($tracking_items['custom_tracking_link'])) {
317
- return array();
318
- }
319
-
320
- // 获取 postnl Postalcode
321
- $urlArr = parse_url(stripslashes($tracking_items['custom_tracking_link']));
322
-
323
- if ($urlArr === false) {
324
- return array();
325
- }
326
-
327
- if (!isset($urlArr['host'])) {
328
- return array();
329
- }
330
-
331
- $hostArr = explode(".", $urlArr['host']);
332
- $hostArrIndex = count($hostArr) - 2;
333
- if (empty($hostArr) || !isset($hostArr[$hostArrIndex])) {
334
- return array();
335
- }
336
-
337
- if ($hostArr[$hostArrIndex] == 'postnl') {
338
- parse_str($urlArr['query'], $queryArr);
339
- if (!isset($queryArr['Postalcode'])) {
340
- return array();
341
- }
342
-
343
- return array(
344
- 'tracking_provider' => 'postnl',
345
- 'tracking_postal_code' => str_replace(" ", "", $queryArr['Postalcode']),
346
- );
347
- }
348
- return array();
349
- }
350
-
351
-
352
- /**
353
- * Helper method to get order post objects
354
- *
355
- * @param array $args request arguments for filtering query
356
- *
357
- * @return WP_Query
358
- * @since 2.1
359
- *
360
- */
361
- private function query_orders($args)
362
- {
363
-
364
- function aftership_wpbo_get_woo_version_number()
365
- {
366
- // If get_plugins() isn't available, require it
367
- if (!function_exists('get_plugins'))
368
- require_once(ABSPATH . 'wp-admin/includes/plugin.php');
369
-
370
- // Create the plugins folder and file variables
371
- $plugin_folder = get_plugins('/' . 'woocommerce');
372
- $plugin_file = 'woocommerce.php';
373
-
374
- // If the plugin version number is set, return it
375
- if (isset($plugin_folder[$plugin_file]['Version'])) {
376
- return $plugin_folder[$plugin_file]['Version'];
377
-
378
- } else {
379
- // Otherwise return null
380
- return NULL;
381
- }
382
- }
383
-
384
- $woo_version = aftership_wpbo_get_woo_version_number();
385
-
386
- if ($woo_version >= 2.2) {
387
- // set base query arguments
388
- $query_args = array(
389
- 'fields' => 'ids',
390
- 'post_type' => 'shop_order',
391
- // 'post_status' => 'publish',
392
- 'post_status' => array_keys(wc_get_order_statuses())
393
- );
394
- } else {
395
- // set base query arguments
396
- $query_args = array(
397
- 'fields' => 'ids',
398
- 'post_type' => 'shop_order',
399
- 'post_status' => 'publish',
400
- );
401
- }
402
-
403
- // add status argument
404
- if (!empty($args['status'])) {
405
-
406
- $statuses = explode(',', $args['status']);
407
-
408
- $query_args['tax_query'] = array(
409
- array(
410
- 'taxonomy' => 'shop_order_status',
411
- 'field' => 'slug',
412
- 'terms' => $statuses,
413
- ),
414
- );
415
-
416
- unset($args['status']);
417
- }
418
-
419
- $query_args = $this->merge_query_args($query_args, $args);
420
-
421
- return new WP_Query($query_args);
422
- }
423
-
424
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
readme.txt CHANGED
@@ -1,41 +1,70 @@
1
  === Plugin Name ===
2
  Contributors: aftership
3
  Donate link: https://www.aftership.com/
4
- Tags: shipping, tracking, ups, usps, fedex, dhl, tnt, dpd, post, shipment, woocommerce, tracking number, aftership, package tracking, fulfilment, tracking link, carrier, courier, woo commerce, woocommerce shipment tracking, shipping details plugin, widget, shipstation, track, package
5
  Requires at least: 2.9
6
  Tested up to: 5.2.1
7
- Stable tag: 1.9.18
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
11
- Auto import tracking of all your shipments in one place to WooCommerce (Free), branded tracking page to view order status in one click and ensure great post-purchase experience for your customers, send email / SMS delivery notifications to engage your customers after sales (Premium).
12
- AfterShip is free for 100 first shipments, then try Premium.
13
 
14
  == Description ==
15
 
16
  ###Top Shipment Tracking Plugin (Free)
17
- By installing AfterShip plugin, you can automatically add Tracking Number and Courier fields to your admin panel. After you fulfill an order, simply enter the tracking number and select a courier at WooCommerce, the same info will be displayed at customer's order history page. AfterShip supports over 550+ carriers worldwide, you can select couriers by [signing up a free AfterShip account](https://secure.aftership.com/signup).
 
 
18
 
19
  ###Display tracking info at order history page (Free)
20
- The plugin allows you to insert the AfterShip Track Button to order history page, so that your customers can track the latest order status in one click.
21
 
22
- ###Support 550+ International Courier (Free)
23
- AfterShip supports UPS tracking, FedEx tracking, USPS tracking, DHL tracking and shipment tracking of over 550+ carriers worldwide. Please scroll down to see the full list of our supported carriers.
 
 
 
24
 
25
 
26
  ###Track all shipments in one place (Free)
27
  By setting up an auto import of tracking numbers to AfterShip, you can get the latest tracking info of all your shipments in one place. Each free account comes with a Dashboard to monitor current statuses of all shipments. You can also filter your shipments by dates, statuses, couriers and destination. Find out if all your shipments are delivered on time and discover any exceptions. Support [WooCommerce Shipment Tracking Plugin](http://www.woothemes.com/products/shipment-tracking/) as well.
28
 
 
29
  ###Branded Tracking Page (Free)
30
 
31
  AfterShip automatically generates a tracking page for each shipment. Customize tracking page by adding your brand logo, store URL and Instagram pictures to improve SEO and generate more sales. You can also embed the [AfterShip Track Button](http://support.aftership.com/article/111-how-can-i-add-track-button-to-wordpress-or-woocommerce) to allow tracking at your store. Improve your customer experience on tracking.
32
 
 
33
  ###Notify customers of delivery updates (Premium)
 
34
  Upgrade to [Premium](https://www.aftership.com/pricing) to automatically send out delivery notifications to customers or yourself. Your choice of notification triggers - In transit, Out for delivery, Delivered, Failed delivery attempt or Exceptions. Use your own email to send out notifications, and customize messages to add store logo, URL, a tracking link to get more returned customers after shipping!
35
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  [youtube http://www.youtube.com/watch?v=1zCCx8Ap9ms]
37
 
38
- ###Partial list of supported carriers (550+):
 
39
  **①. US, Canada & Global Tracking (35)**
40
  ABF Freight • APC Postal Logistics • Aramex • Asendia USA • Canada Post • Canpar Courier • Con-way Freight • DACHSER • DHL Express • DHL eCommerce • DHL Express (Piece ID) • DPD • DSV • Echo • Ensenda • Estes • FedEx • FedEx Freight • Globegistics Inc. • Greyhound • i-parcel • LaserShip • Newgistics • Old Dominion Freight Line • OnTrac • Purolator • RL Carriers • RR Donnelley • TNT • TNT Reference • UPS • UPS Freight • UPS Mail Innovations • USPS • YRC
41
 
@@ -97,6 +126,9 @@ You'll find the FAQ on [AfterShip.com](https://aftership.uservoice.com/knowledge
97
 
98
  == Changelog ==
99
 
 
 
 
100
  = 1.9.18 =
101
  * Add new couriers (borderexpress)
102
 
1
  === Plugin Name ===
2
  Contributors: aftership
3
  Donate link: https://www.aftership.com/
4
+ Tags: shipping, tracking, ups, usps, fedex, dhl, tnt, dpd, post, shipment tracking, wordpress, woocommerce, tracking number, order tracking for WooCommerce, parcel tracking device, package tracking, fulfilment, tracking link, returns management for WordPress, returns management solutions
5
  Requires at least: 2.9
6
  Tested up to: 5.2.1
7
+ Stable tag: 1.9.19
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
11
+ Auto import all your shipment tracking in one place for WooCommerce (free), branded tracking page to view order status and ensure great post-purchase experience, send delivery notifications to engage your customers after sales (Premium).
 
12
 
13
  == Description ==
14
 
15
  ###Top Shipment Tracking Plugin (Free)
16
+
17
+ By installing AfterShip - Shipment tracking plugin for WordPress, you can automatically add Tracking Number and Courier fields to your admin panel. After you fulfill an order, simply enter the order tracking number and select a courier at WooCommerce, the same info will be displayed at customer’s order history page. AfterShip supports over 657+ carriers worldwide, you can select couriers by [signing up a free AfterShip account](https://secure.aftership.com/signup).
18
+
19
 
20
  ###Display tracking info at order history page (Free)
 
21
 
22
+ The plugin allows you to insert the AfterShip Track Button to order history pages, so that your customers can track the latest order status in one click.
23
+
24
+ ###Support 668+ International Courier (Free)
25
+
26
+ AfterShip supports UPS tracking, FedEx tracking, USPS tracking, DHL tracking and shipment tracking of over 668+ carriers worldwide. Please scroll down to see the full list of our supported carriers.
27
 
28
 
29
  ###Track all shipments in one place (Free)
30
  By setting up an auto import of tracking numbers to AfterShip, you can get the latest tracking info of all your shipments in one place. Each free account comes with a Dashboard to monitor current statuses of all shipments. You can also filter your shipments by dates, statuses, couriers and destination. Find out if all your shipments are delivered on time and discover any exceptions. Support [WooCommerce Shipment Tracking Plugin](http://www.woothemes.com/products/shipment-tracking/) as well.
31
 
32
+
33
  ###Branded Tracking Page (Free)
34
 
35
  AfterShip automatically generates a tracking page for each shipment. Customize tracking page by adding your brand logo, store URL and Instagram pictures to improve SEO and generate more sales. You can also embed the [AfterShip Track Button](http://support.aftership.com/article/111-how-can-i-add-track-button-to-wordpress-or-woocommerce) to allow tracking at your store. Improve your customer experience on tracking.
36
 
37
+
38
  ###Notify customers of delivery updates (Premium)
39
+
40
  Upgrade to [Premium](https://www.aftership.com/pricing) to automatically send out delivery notifications to customers or yourself. Your choice of notification triggers - In transit, Out for delivery, Delivered, Failed delivery attempt or Exceptions. Use your own email to send out notifications, and customize messages to add store logo, URL, a tracking link to get more returned customers after shipping!
41
 
42
+
43
+ ###BRANDED RETURNS PAGE (FREE)
44
+
45
+ Get the top-rated returns management solution for WordPress. Customize your branded returns center with your logo, custom URL and return policy. Offer a customer-friendly returns experience. Improve your brand image, customer satisfaction and loyalty.
46
+
47
+
48
+ ###MANAGE ALL RETURNS REQUESTS (FREE)
49
+
50
+ Track and manage all returns requests in one place to save processing time. Automatically generate an RMA# once a return request is submitted.
51
+ product returns management
52
+
53
+
54
+ ###PREPAID SHIPPING LABELS
55
+
56
+ Automatically generate or manually upload prepaid labels to provide a seamless returns experience. Customers will receive an email with shipping instructions, simply print the label out and tap them to the box.
57
+
58
+
59
+ ###CUT RETURNS COSTS WITH ADVANCED AUTOMATION RULES (FREE)
60
+
61
+ Set up eligibility rules to prevent customers from returning an old order or product in certain categories. Automatically select a returns method and set shipping rates based on the region and reason of returns (e.g. damaged, defective, or wrong item).
62
+
63
+
64
  [youtube http://www.youtube.com/watch?v=1zCCx8Ap9ms]
65
 
66
+
67
+ ###Partial list of supported carriers (668+):
68
  **①. US, Canada & Global Tracking (35)**
69
  ABF Freight • APC Postal Logistics • Aramex • Asendia USA • Canada Post • Canpar Courier • Con-way Freight • DACHSER • DHL Express • DHL eCommerce • DHL Express (Piece ID) • DPD • DSV • Echo • Ensenda • Estes • FedEx • FedEx Freight • Globegistics Inc. • Greyhound • i-parcel • LaserShip • Newgistics • Old Dominion Freight Line • OnTrac • Purolator • RL Carriers • RR Donnelley • TNT • TNT Reference • UPS • UPS Freight • UPS Mail Innovations • USPS • YRC
70
 
126
 
127
  == Changelog ==
128
 
129
+ = 1.9.19 =
130
+ * Update plugin banner
131
+
132
  = 1.9.18 =
133
  * Add new couriers (borderexpress)
134