We just launched a fun little tool called Phantom Analyzer. It’s a 100% serverless tool that scans websites for hidden tracking pixels.

I want to talk about how we built it 👇

The idea came about early this year after @mijustin gave us an idea about badges/certification, which developed into “what if we could scan websites for Google Analytics?!”. But we left the idea in Basecamp for many months.
Fast forward to Halloween, we’re thinking about fun ideas we could do to entertain people. We discussed “Phantom Analytics” in response to people getting confused with our product name, and had various ideas. And then we landed on the URL analyzer idea.
Once we’d finalized the spec, Paul got to work on our Halloween themed product and then coded up the HTML/CSS for it all. I then took it, put it into a Laravel application. Nice and easy.
Off the bat, I already knew the base stack I was using.

> Laravel Vapor
> ChipperCI for deployment
> SQS for queues
> DynamoDB for the database

We went with DynamoDB as we don’t want to worry about our database scaling!
So with our infrastructure known, we had a few challenges left to solve:

> How will we scan websites for tracking pixels?
> How will we utilize the queue and check the job is done?
> How will we validate the URL?
For scanning websites, the first thing I did was write out a complex, multi-level regex matching, guzzle executing scanner. But the problem was that it didn’t automatically run the javascript, which often includes additional requests, so the results weren’t accurate.
After spending a long time on that, I was searching for website crawlers and came across Puppeteer, which is a headless Chrome Node.js API. I then searched for how to get it running on Laravel Vapor and saw that someone had already solved that challenge!
I then spent 8 hours trying to start from scratch with Puppeteer, copying from @spatie_be’s Browsershot code, but I just couldn’t get it working. I went to bed, woke up the next morning, and decided that I’d start with Browsershot and simply modify it to what I needed.
I woke up the next day, and within 15 minutes I get a screenshot generated on Laravel Vapor, hooray! I then start to modify Browsershot…

Wait a minute...

Yes, out of the box, Browsershot already had what I needed. Are you kidding me?
So I modified my job and had it all working within minutes. Browsershot returns a list of network requests when loading a web page and returns them, bloody perfect. I then simply compared them against a list of around 10,000 known third party trackers that we had.
The next step was working out how we would get permanent storage in DynamoDB without bringing in anything extra. I wanted to keep it simple. So with DynamoDB as the driver, and “resources” as the storage root, I wrote a command that cached the tracking pixels indefinitely.
One of the initial concerns I had was regarding security. We would be passing user input to the command line and that wouldn't be safe. I spoke with @marcelpociot and he gave me some great advice, and I added in some validation. The active_url rule is fantastic.
I also wanted to have a way so that if a user entered a full URL (e.g. https://t.co/66d4eLDaOu) and not just "https://t.co/GA31muKcta", it still redirected them to the correct results page. Especially since our "tidying up" was opinionated. So we ran this code.
We then had to think about how to configure our Vapor app, and I went with the following settings

> 1024MB of RAM
> 2048 of RAM for the queue (could likely reduce!)
> Warm of 500
> CLI Timeout of 180 seconds

Those settings all worked nicely.
For our Vapor layers, we ran it like this. Very cool. My first time using Layers. Incredible work by the Vapor team (@themsaid @taylorotwell @enunomaduro).
For the "is it ready?" check, I debated using a UUID but I decided that we might have multiple users trying a website at the same time, and they should benefit from the same cache entry (we cache results for 5 minutes).
So for the ping, we went super old school. Interval and redirect when done. Very effective. And when it reloaded the page, it would hit the cache, see the entry and display it.
All in all, this was a fun project to build. I love working with Paul. The only design addition I made was the bats & fade, Paul did everything else. Very grateful for that 😂
I am still in awe over how quickly we deployed this with Vapor. I'm not kidding, it was all coded up and we just created it in the UI, deployed it and we were done. Remarkable experience. Infinite scale without any server work 😎

Hope you all enjoy Phantom Analyzer!

More from Tech

"I really want to break into Product Management"

make products.

"If only someone would tell me how I can get a startup to notice me."

Make Products.

"I guess it's impossible and I'll never break into the industry."

MAKE PRODUCTS.

Courtesy of @edbrisson's wonderful thread on breaking into comics –
https://t.co/TgNblNSCBj – here is why the same applies to Product Management, too.


There is no better way of learning the craft of product, or proving your potential to employers, than just doing it.

You do not need anybody's permission. We don't have diplomas, nor doctorates. We can barely agree on a single standard of what a Product Manager is supposed to do.

But – there is at least one blindingly obvious industry consensus – a Product Manager makes Products.

And they don't need to be kept at the exact right temperature, given endless resource, or carefully protected in order to do this.

They find their own way.

You May Also Like

शमशान में जब महर्षि दधीचि के मांसपिंड का दाह संस्कार हो रहा था तो उनकी पत्नी अपने पति का वियोग सहन नहीं कर पायी और पास में ही स्थित विशाल पीपल वृक्ष के कोटर में अपने तीन वर्ष के बालक को रख के स्वयं चिता पे बैठ कर सती हो गयी ।इस प्रकार ऋषी दधीचि और उनकी पत्नी की मुक्ति हो गयी।


परन्तु पीपल के कोटर में रखा बालक भूख प्यास से तड़पने लगा। जब कुछ नहीं मिला तो वो कोटर में पड़े पीपल के गोदों (फल) को खाकर बड़ा होने लगा। कालान्तर में पीपल के फलों और पत्तों को खाकर बालक का जीवन किसी प्रकार सुरक्षित रहा।

एक दिन देवर्षि नारद वहां से गुजर रहे थे ।नारद ने पीपल के कोटर में बालक को देख कर उसका परिचय मांगा -
नारद बोले - बालक तुम कौन हो?
बालक - यही तो मैं भी जानना चहता हूँ ।
नारद - तुम्हारे जनक कौन हैं?
बालक - यही तो मैं भी जानना चाहता हूँ ।

तब नारद ने आँखें बन्द कर ध्यान लगाया ।


तत्पश्चात आश्चर्यचकित हो कर बालक को बताया कि 'हे बालक! तुम महान दानी महर्षि दधीचि के पुत्र हो । तुम्हारे पिता की अस्थियों का वज्रास्त्र बनाकर ही देवताओं ने असुरों पर विजय पायी थी।तुम्हारे पिता की मृत्यु मात्र 31 वर्ष की वय में ही हो गयी थी'।

बालक - मेरे पिता की अकाल मृत्यु का क्या कारण था?
नारद - तुम्हारे पिता पर शनिदेव की महादशा थी।
बालक - मेरे उपर आयी विपत्ति का कारण क्या था?
नारद - शनिदेव की महादशा।
इतना बताकर देवर्षि नारद ने पीपल के पत्तों और गोदों को खाकर बड़े हुए उस बालक का नाम पिप्पलाद रखा और उसे दीक्षित किया।