Skip to content
Track your deliveries on Magic Mirror 2. Supports 428 couriers worldwide via Aftership.
JavaScript CSS
Branch: master
Clone or download
Pull request Compare This branch is 38 commits ahead of mykle1:master.
martinkooij New release
* Narrow functional enhancement.
* hideDelivered now takes integer
* bug showing "Undefined" fixed
* version 1.3.0 created
Latest commit 31ec835 Mar 30, 2018
Type Name Latest commit message Commit time
Failed to load latest commit information.
pictures free translation and other features (#3) Mar 19, 2018
.gitignore free translation and other features (#3) Mar 19, 2018
LICENSE Initial commit Nov 1, 2017
MMM-Parcel.css Pre-production version Mar 5, 2018
MMM-Parcel.js New release Mar 30, 2018 New release Mar 30, 2018
node_helper.js New release Mar 30, 2018
package.json New release Mar 30, 2018


Track deliveries . Supports 428 couriers worldwide based on

Here's what you get

View parcel tracking status, for display on Magic Mirror. Inspired by MMM-AfterShip by Mykle1.


Example with expected deliveries on a separate line. Expected delivery line is only shown when an ETA is known.

Example of the same in the compact view:

And in the very compact view (one-liner per shipment):


  • Go into the ~/MagicMirror/modules directory and do git clone

  • Go into the MMM-Parcel directory and do npm install

  • Get an account on (Free account is OK if you track less than 100 parcels per month)

  • Get your FREE API Key from via settings -> API.

  • You MUST add couriers to your account at

  • Add your own trackings

  • Tell me what you like, or any issues you have. It is difficult to test as I cannot control or test all variations from AfterShip.


Do a git pull in the MMM-Parcel module directory. Running a npm install again in the same directory is recommended and does no harm. In case supporting features need new packages, such as when you upgrade to a version with the automatic translations feature, the npm install is really needed.

Using the module

To use this module, add it to the modules array in the config/config.js file:

module: 'MMM-Parcel',
position: 'top_right',	// This can be any of the regions. Best results in left or right regions.
header: 'My Parcels',   // This is optional
config: {
	apiKey: 'Your API KEY goes here', // Your free API Key from
	maxNumber: 10, //maximum number of Parcels to show
	showCourier: true,
	autoHide: false, // hide module on mirror when there are no deliveries to be shown
	isSorted: true,  // sort on delivery Status (most important ones first)
	compactness: -1, // 0 = elaborate, 1 = compact display, 2 = very compact, one-liner per shipment, -1 = automatic
	hideExpired: true, // don't show expired parcels
	hideDelivered: 15, // Hide delivered parcels after 15 days. 
	updateInterval: 600000, // 10 minutes = 10 * 60 * 1000 milliseconds. 
	parcelStatusText: ["Exception", "Failed Attempt","In Delivery", "In Transit", 
	                   "Info Received", "Pending", "Delivered", "Expired"], // This is the default. Enter your own language text
	parcelIconColor: ["red", "red", "green", "green", "cornflowerblue", "cornflowerblue", "grey", "grey"], // This is the default. Change for other icon colors
	onlyDaysFormat: {
	  lastDay : '[Yesterday]',
	  sameDay : '[Today]',
	  nextDay : '[Tomorrow]',
	  lastWeek : '[Last] dddd',
	  nextWeek : 'dddd',
	  sameElse : 'L'
	  }, // formatting when only days are shown and time is unknown. 
	expectedDeliveryText: 'Delivery Expected: ',	 // This is the default. Changes time infoline. 
    noParcelText: 'No Shipment Data'	 // This is the default. Changes infoline in case of no trackings. 

The above example is a bit long. If you are OK with English texts and you do like the default colors and settings provided by the module the following simple config suffices!

module: 'MMM-Parcel',
position: 'top_right',	// This can be any of the regions. Best results in left or right regions.
header: 'My Parcels',   // This is optional
config: {
	apiKey: 'Your API KEY goes here' // Your free API Key from

Basic configuration options

The following properties can be configured:

Option Description
apiKey REQUIRED: Your AfterShip API access token, you can get it via This is the only required config field

Possible values: string
Default value: none
maxNumber Maximum number of parcels that are shown

Possible values: int
Default value: 10
showCourier Determines whether the shortcode of the courier in the Parcel header is shown

Possible values: true, false
Default value: true
Example: "3DT123456789(In transit, fedex)" is shown when showCourier: true and "3DT123456789(In transit)" is shown when showCourier: false
hideDelivered Determines how many days parcels with status "Delivered" should be shown.

Possible values: integer or boolean
Default value: false
Examples: When `boolean` the config parameter determines whether delivered packages are hidden. The default is false which means "not hidden". When using an `integer` the parameter value indicates for how many days delivered parcels should be shown. A value of 10 means "hide the Delivered Packages after 10 days".
updateInterval Time between requests to the API in milliseconds

Possible values: int
Default value: 600000 =10 minutes.
Note: Internally the module sets 60000 (1 minute) as an absolute lower bound, whatever the config value is. Don't overload the API!
maxWidth Set the width of your module on the screen in pixels.

Possible values: string
Default value: "450px"
Note: The module will automatically adapt the layout to fit better in a narrower space, when the space given in maxWidth is narrower than 400px.

Advanced Options and Language Options

Option Description
compactness Determines whether the expected delivery time (if known for the parcel) is shown on a separate line or on the same line as the parcel header (see example pictures).

Possible values: -1, 0, 1 or 2
Default value: -1
Note: 0 displays the shipment with expected delivery time (if present) on a separate line. it also displays a separate info line on the latest checkpoint (if present). 1 shows a more compact version and 2 effectively makes it a one-liner per shipment. -1 (=automatic) takes a compactness depending on the #parcels shown (0 when <=3, 1 when <=6, 2 in case of long lists). It mostly has a "vertical" effect (the higher the compactness level, the less lines it takes on the mirror).
forceNarrow, forceWide Manually set the layout for the width. Set one of the two or none (default).

Possible values: true (or false)
Default value: None set.
Example: forceNarrow: true, when set forces a "narrow" layout (= the layout used when maxWidth <400px) even when the module is give a space of 400 pixels or wider. Setting forceWide: true does the reverse. The "narrow" vs "wide" layout mainly has a "horizontal" effect. It changes the layout to fit better in narrow spaces or wider spaces respectively.
Note: Playing with manually set compactness and "narrowness" is possible, however the default automatic behavior should be working for most.
isSorted Parcels are shown in a sorted order depending on status. The module implements a fixed --non-configurable-- sort order for the parcel statuses from the API. The order is: Exception, AttemptFail, OutForDelivery, InTransit, InfoReceived, Pending, Delivered, Expired

Possible values: true, false
Default value: true
Note: Exceptions first, Expired last. Sort is according to urgency of action needed from the receiver. If not sorted the ordering is the ordering as received by the API of
autoHide The module hides itself when there are no parcels found

Possible values: true, false
Default value: false
Note: Hide module from the mirror when there are no Parcels to be shown. Also reduces the update interval to minimally every 15 minutes or else 2 times the configured updateInterval whichever one is the longest. Also it unhides itself and shows "No Shipment Data" on the mirror at a random time between 6AM and 10.30PM for half an hour everyday. This cannot be surpressed.
hideExpired Determines whether parcels with status "Expired" should be shown.

Possible values: true, false
Default value: true.
parcelIconColor Colors of the parcel status icons in the header

Possible values: [string,...,string]. Array of 8 strings defining the icon colors.
Default value: ["red","red","green","green","cornflowerblue","cornflowerblue","grey","grey"]. 8 colors.
Note: The colors are icon colors of the Parcel Status in the same order as the texts in the isSorted option above. When you are comfortable with the above mentioned colors you do not need to specify this item in the module-config.
Note: If the extra info line (whether visible or not) contains the text "to be collected" the parcel is marked as delivered but should still be collected. To make that visible the icon color of the delivered icon changes in that case to the color of OutforDelivery status.
parcelStatusText Text to show for the statuses of the Parcel

Possible values: [string,...,string]. Array of exactly 8 strings defining the names for the statuses in the order mentioned in the isSorted option above.
Default value: ["Exception",...,"Expired"]. English is default. Choose your own language descriptions.
Example: parcelStatusText: ["Fout", "Mislukte bezorging","In bezorging", "Onderweg", "Ingevoerd", "Wachtend", "Afgeleverd", "Te oud"], for Dutch Status texts. If you trust the colored status icons to guide you, you can leave all (or some) of these texts empty by defining empty strings (""). Just take care to specify an array of total 8 strings! Default are English texts, if you are happy with the English descriptions you may leave this item out of your module-config.
onlyDaysFormat Format for delivery time when only date, and no hour is yet known for the Parcel. In moment.js calendar format

Possible values: moment.js calendar locale specification
Default value:
{lastDay : '[Yesterday]',
sameDay : '[Today]',
nextDay : '[Tomorrow]',
lastWeek : '[Last] dddd',
nextWeek : 'dddd',
sameElse : 'L'}
Example: Fill in your language preference. English is default. Only relevant when compactness: 0. This option does nothing otherwise.
expectedDeliveryText Text to show before showing the expected delivery date

Possible values: string
Default value: "Delivery expected: "
Example: Use "Bezorging verwacht:" in Dutch for example. Only relevant when compactness: 0. This option does nothing otherwise.
noParcelText Text to show when there are no trackings to show

Possible values: string
Default value: "No Shipment Data"
Example: Use "Geen Data" in Dutch for example.
autoTranslate Translate text shown on the infoline into your own language of choice via Google Translate free API

Possible values: language string.
Default value: false
Example: See description below for use. The Google API is not called/used if false or if the option is absent.

Auto Translation

Many couriers enter checkpoint message in the language of the country of origin, sometimes aftership decides to translate to English, sometimes not. the MMM-Parcel module contains a translation feature of these information texts based on a free Google Translate API. This only works if autoTranslate is set to a valid language string (see Translation services will not be called if autoTranslate is absent or set to false.

An example of a non-translated view on the mirror:

The infotexts can be automatically translated via Google translate API. Add for example autoTranslate : "en", in the config.js file in the MMM-Parcel descriptions. Restart the mirror and off you go! The translation API is only called when there is a change in the deliveries.

I adapted my mirror module to be a Dutch mirror by setting Dutch language settings and autoTranslate to "nl" in the config:

module: 'MMM-Parcel',
position: 'top_right',
header: 'Pakjes',   
config: {
	apiKey: 'XXXXXXXXXXXXXX', // API key of Aftership
	compactness: -1,
	autoTranslate: "nl",
	parcelStatusText: ["Fout", "Mislukte bezorging","In bezorging","Onderweg", "Ingevoerd", "Wachtend", "Afgeleverd", "Te oud"],
		{lastDay : '[gisteren]',
		 sameDay : '[vandaag]',
		 nextDay : '[morgen]',
		 lastWeek : '[afgelopen] dddd',
		 nextWeek : 'dddd',
		 sameElse : 'L'},
	expectedDeliveryText: 'Bezorging verwacht: ',
	noParcelText: 'Geen Data'

And Yo, see the Dutch mirror:

Advanced users: When you don't like certain automated translations you can put a forced translation JSON file in de MMM-Parcel module directory called force_trans.json Don't worry, the file, if it exists, is ignored by git pull so will not be overwritten by an update. The file is a JSON formatted text file (don't make any JSON syntax errors!) of translation pairs of original texts (in full) and translated texts. The translation translates complete message entries not word by word. Example:

"Departed" : "Vertrokken", 
"Processed Through Facility": "Verwerkt in sorteercentrum"


  • [aftership] (installed via npm install)
  • [google-translate-api] (installed via npm install)
  • [moment] (already available)
  • font-awesome 4.7.0 (already available)

Newest features

  • narrow layout added
  • hideDelivered can take an integer.
  • possibility to translate the info texts.

Latest Releases

  • version 1.3.0. Added Narrow layout, hideDelivered in days + editorials on Readme. Removed bug of showing "undefined" when the parcellist is empty.
  • version 1.2.2. Bug fixed, code linting, now displays time of latest checkpoint when no expected delivery is (yet) known. Message line before clock line.
  • version 1.2.1. Removed spurious debug info to log files
  • version 1.2.0. Functional release (adding translations, autohide and automatic compactness)

Known issues

  • Aftership does a good job in collecting information from the courier but is not perfect. Use the mirror presentation as a hint.
  • On full mirrors with many modules the google API translations (if set) sometimes arrive just after the visual update during start-up. No problem, in the next update cycle the translations are picked up. And a mirror is only booted up once a month or less no?
You can’t perform that action at this time.