Amazon use dynamic pricing and prices of the products we are interested in can vary depending on many things.
We will create a tool to set price alerts on any Amazon product. With no more than 50 lines of codes.
TL;DR: project code is available here: https://github.com/MartinRdw/amazon-price-tracking, feel free to clone/deploy to Heroku it
For this we will use:
- Puppeteer: a Node library which provides a high-level API to control Chrome
- Zenaton: a SaaS service allowing to build tasks and workflows quickly
Puppeteer will allow us to scrape the Amazon product page to get the current price and Zenaton will allow us to run the code every X hours and send alerts.
Configuration
To start using Zenaton, you have to complete 4 steps:
- Sign-up here
- Download and install the Zenaton agent on your machine :
curl https://install.zenaton.com | sh
- Configure it with your Zenaton credentials.
We will use a .env
file, the simplest is to clone the example repo here: https://github.com/zenaton/examples-node
git clone https://github.com/zenaton/examples-node
cp -n .env.example .env
If you are not interested by the examples you can just keep boot.js, client.js, .env and package.json files.
Update .env
with your credentials from https://app.zenaton.com/api and run npm i .
- Launch the Zenaton Agent
Start the agent and make it listen to your configuration:
zenaton start && zenaton listen — env=.env — boot=boot.js
Workflow creation
The workflow will take 4 variables as parameters:
- The name of the product
- The product url
- The price of the alert
- The number of hours between each check
touch Workflows/TrackAmazonPrice.js
The code is quite simple:
'use strict'
const { workflow, duration } = require('zenaton')
module.exports = workflow('TrackAmazonPrice', function * (product, productUrl, alertPrice, hoursBetweenEachCheck) {
const slack = this.connector('slack', 'your_slack_connector_id')
while (true) {
// get product price
const price = yield this.run.task('GetAmazonProductPrice', productUrl)
// send alert if needed
if (parseFloat(price) < alertPrice) {
slack.post('chat.postMessage', {
body: {
text: `🚨 ${product} goes below ${alertPrice}€ \n 💰 Current price: ${price} \n ➡️ ${productUrl}`,
as_user: true,
channel: 'amazon'
}
})
// terminate workflows
this.terminate()
}
// wait 4 hours before next check
yield this.wait.for(duration.hours(hoursBetweenEachCheck))
}
})
TrackAmazonPrice.js
Some explanations:
We use the wait function of Zenaton to wait 4 hours between each price analysis https://zenaton.com/documentation/node/workflow-waiting/#duration
To send the alert, I chose to use one of the new Zenaton features to receive a message in Slack: connectors.
To configure a new connector you just have to go here: https://app.zenaton.com/connectors
Search for Slack and click on “Add”.
Replace your_slack_connector_id
in the code with the id you have here:
More info on connectors here: https://zenaton.com/documentation/node/api-connectors
Task creation
We still have to create the Task which will allow us to get the price on Amazon. TheGetAmazonProductPriceof our workflow code.
touch Tasks/GetAmazonProductPrice.js
This is where we will use Puppeteer:
npm -i puppeteer
Goal of the task:
- Open a Chromium browser
- Go to amazon product URL
- Scrape the webpage to find the #attach-base-productselector (the price is in this input)
- Return the price
Code :
const { task } = require('zenaton')
const puppeteer = require('puppeteer')
const SELECTORS = {
productTitle: '#productTitle',
productPrice: '#attach-base-product-price'
}
module.exports = task('GetAmazonProductPrice', async function (productUrl) {
const browser = await puppeteer.launch(
{
headless: true,
defaultViewport: {
width: 1100,
height: 840
}
}
)
const page = await browser.newPage()
await page.goto(productUrl)
// wait page load
await page.waitForSelector(SELECTORS.productTitle, { visible: true })
// find price
const priceInput = await page.$(SELECTORS.productPrice)
const price = await page.evaluate(element => element.value, priceInput)
await browser.close()
return price
})
GetAmazonProductPrice.js
The few Puppeteer functions used are well documented here: https://github.com/puppeteer/puppeteer/blob/master/docs/api.md
Launch the workflow
It remains for us to launch our workflow.
touch launch_amazon_workflow.js
This is an example to get an alert when the iPhone 11 Pro will drop below $1000:
const run = require('./client').run
const product = 'Iphone 11 Pro - 64go'
const productUrl = 'https://www.amazon.fr/Apple-iPhone-11-Pro-64-Go/dp/B07XRRNYWK'
const alertPrice = 1000
const hoursBetweenEachCheck = 4
// run workflow
run.withTag(`${product} (${alertPrice}€)`).workflow('TrackAmazonPrice', product, productUrl, alertPrice, hoursBetweenEachCheck)
launch_amazon_workflow.js
Just run node launch_amazon_workflow.js
to launch your workflow.
withTag()
allows us to give a name to each of our workflows. Thanks to that, by going back to the Zenaton dashboard we can see the products currently tracked:
Products currently tracked
The code is available here: https://github.com/MartinRdw/amazon-price-tracking/tree/no-web-app
Bonus: Frontend + deploy to Heroku
You can create an interface to more easily interact with your Zenaton workflows:
Create workflows from a frontend application
It’s composed of:
The code (with frontend app + deploy to Heroku) is available here: https://github.com/MartinRdw/amazon-price-tracking