I made a chrome extension to send WhatsApp messages to phone numbers on a webpage, without saving a contact on the phone. all . GitHub Link Recently, I had the misfortune to look for a rental house. Besides parsing through multiple properties on property rental portals, I had to contact agents. For property that I liked : every (and had a chance to get) I had to copy the agent’s phone number from the computer screen to my phone, wait for WhatsApp to sync contacts, mentally note the listing name from the computer, and only then send a message from my phone. And, I would have to do it : 79 times agents to contact Too much manual labour; there had to be a better solution. After some homework, I settled on making a chrome extension that would parse every webpage, look for phone numbers and send a message Some iterations later, it was able to send messages to number, with a link to the corresponding property, The extension also stores the phone numbers it has already sent to, to prevent repeat messages: with a single click. every with a single click. After running my extension Technical Implementation I figured I could run custom javascript in to send a message. But there was no way to open a of a new user who’s number is not saved. I could pass in query params to with a contact and a message, something like . This would open the to the number +1 23456789 with in the . Then, perform a click on the send button and voila! The message is sent. web.whatsapp.com chatbox web.whatsapp.com https://web.whatsapp.com/send?phone=1234556789&text=Hey chatbox ’Hey’ chatbox With the above plan, I broke it into the following sub-tasks: Parse every page for phone numbers Append a WhatsApp icon to those numbers Search for the hyperlink that phone number. before Open WhatsApp web on click of that icon, with a pre-filled message to the phone number containing the found hyperlink. Add a_“send to all”_ action to send messages to all contacts in the background. A script that runs in web.whatsapp.com to wait for the chatbox (or the popup) to open and send the message. invalid number Sending the message is a long running task, so show the status like: sending, sent, phone invalid. Store the numbers already sent so that I do not accidentally send multiple messages to the same number. I used the awesome library and some javascript to find phone numbers, and add the WhatsApp icon. libphonenumber-js I open the WhatsApp web tab using the chrome extension API. It was a little tricky because the that added the icon, had to send a to the to open the tab along with parameters. With some recursive code I could find the closest hyperlink before the phone number. Almost always this would be the link to the property the agent has put up (who my script would message). On click, content script message background script This marked the half-way point: I could send a WhatsApp message from the browser to an unsaved contact without touching my phone. Then, for WhatsApp Web, I wrote some / code. It had to wait for the web-app to load; specifically, it waited for either for the chat box to open, or the popup to show up. This part was really fun- instead of writing indented anonymous/arrow functions, I wrote linear statements. I passed Sandi Metz’ async await ‘Phone number shared via url is invalid’ await squint test: “Squint you eyes. Lean back. Look for changes in shape. Look for changes in colour. Shape reflects cycolmetric complexity — lots of nested conditionals. Colour reflects differing levels of abstraction, different types of things are in a mish mash. The squint test can help!” Remaining part was simple: use the chrome APIs to send messages between the The chrome APIs to store data between page refreshes was simple enough as well. content and background scripts. I really liked how I added functions to my created element and just called them from different parts in the code. For example, see the function: setStatus // in 1 file:function addSendToWaToNode(node, phoneNumber) {const sendToWaNode = document.createElement('span');...sendToWaNode.setStatus = (status, save = false) => {sendToWaNode.lastChild.textContent = status;if (save) {chrome.storage.sync.set({ [waNumber]: status }, function() {console.log(`saved ${waNumber} : ${status}`);});}}} // in another file, I could use it like:phoneSpans = document.querySelectorAll(`.${WA_SPAN_CLASS_NAME}`);span = phoneSpans[0];span.setStatus('sent', true); Finally, the long awaited production run! I think I contacted 80 agents instead of 30 just because it was so easy. Was nice to write javascript for chrome extension because I didn’t have to worry about compatibility issues for different browsers and could liberally use ES6 features (const, async, await, arrow functions, string interpolation). Initially, I kept my code organized and functions small (~5 lines), but I kind of gave up on it in the end. I was still homeless you know. One thing I sorely missed was the native support of tests. I read people made node apps and some framework like code to support testing for their extensions. But there no out-of-the-box solution, so I just let it go for this project. Parting thoughts Instead of spending a to manually message like 80 agents, I to write this chrome extension. But then there would be nothing to blog about. Nevertheless, I’d do it again. few hours spent a week (or brag) The extension is currently in beta. It needs some more UI, error handling to become a general purpose extension. Not sure if I should publish it on the chrome web store. Tell me if you would like to use something like this. I really liked the idea of extensions. It’s like adding features that the app creators don’t have time for; or they thought of them as bugs, not features. Rest assured, there are more extensions to come. Extension requests open 😉