When I started my still unnamed dating site project nearly a year ago, I barely knew the first thing about web development. Yes, I have this blog, but it’s a CMS installation. It’s just pre-packaged, click-and-go WordPress. There’s no actual coding involved. And while I knew some rudimentary HTML from back in the MySpace days, it wasn’t enough. Thus, I had to start from almost nothing.
The whole project started from a tutorial for a login system by CodeShack which is still mostly in use today (although, it’s been heavily modified). With that, I learned basic HTML, CSS, PHP and MySQL. Over the months I focused on those four languages, and tried to use as little JavaScript as possible because JavaScript seemed like an esoteric language to me. I could understand WHAT it was doing, but I couldn’t understand HOW it was doing it. My understanding was “it does this, this, this, and this, then magic happens and we get the results”. There were a few instances of using JavaScript (switching to edit mode on profiles, the original photo gallery from CodeShack (which has since been completely replaced), the location dropdown, etc), but I tried to keep it to a minimum.
This meant the website was clunky. It required page refreshes for actions to take effect. For example, if you sent a message, the page would reload after sending the message to show the message you just sent in your message window, and you would have to reload the page to see a new message sent to you. This obviously wasn’t good. I wanted an instant messaging system, where messages would be sent and received without the need to refresh.
So, with the guidance of ChatGPT, I upgraded the messaging system to use JavaScript on the frontend to send messages to a WebSocket server which would update the database in the same way we did before, but also have the WebSocket server send the message to the JavaScript on the receiver’s end and update the messaging window with the new message without the need to refresh the page. We also use this code to lazy load messages: on page load, we only load the most recent 10 messages, and then load the previous 10 when you scroll up, ad infinitum until you reach the start of the conversation. This helps reduce the time it takes message pages to load. There’s also a handy little button that pops up and allows you to jump back to the first most recent message without having to scroll all the way back down. We also have a menu button on each message, which allows you to delete or report individual messages, and this is seamless as well (we handle the reporting/deleting on the server-side, and update the client-side to show the message as having been reported or deleted without the need to ever refresh the page).[i]
This was my breakthrough with JavaScript, and I decided to implement it elsewhere.
Over the last two months or so, I updated the login system, the notification system, profiles, some of the image handling, the updates[ii] and a few other things to use JavaScript and make using the site almost seamless with as little refreshing and page loading as possible. There are still instances where the page has to load (for example, switching between the about and the photos tabs on profiles (I tried to do something to handle this with JavaScript, but it would have required too much work with very little payoff, especially when there were more urgent needs)), but, most importantly, when receiving notifications, messages, and updates, there’s no refresh required.
Notifications is a big part of this. Before, notifications were only displayed as number on the relevant button, and they were only updated when the user refreshed the page. Now, with our new notification system, we not only update notifications when they happen without the user having to reload the page, but, we can also put pop-up notifications on the screen that hang around for 10 seconds, so there’s less chance of the user missing them. At the moment, there are four types of notifications that pop up: when a bookmarked user logs on (which will also add the user to the favourites section on your sidebar); when a bookmarked user logs off (which will also remove the user from the favourites section on your sidebar); when someone looks at your profile; and, most importantly, when you receive a message (which doesn’t pop up when you’re actually viewing the message in question). There is still some refining to do with styles and what data we display (I’m thinking about adding profile pictures to logging on/off users like we do with message and profile view notifications, and supressing the pop up when the received message is going to your ‘other’ box), but it’s a start. I’m also considering moving the messenger system (including message folders) to a pop-up so you can access your messages wherever you are on the site without the need to navigate to another page.
Favourite user login notification
Favourite user log out notification
Profile view notifications
Message notification
We also do something similar to the pop-up notifications with login confirmation. Failed logins will display a relevant message (wrong password, unknown email address, unknown username, etc) in a pop-up. We’ve also revamped how we handle lockouts after a certain number of failed login attempts. Before, we just blocked your IP address and displayed a plain text message without no real way to get unblocked (I’d planned to make an unblock request, but never got around to it). Now, on the fifth consecutive failed login attempt, you’re locked out for an hour. In this time, we hide the login form and display a countdown timer (I’m considering adding a note to the fourth failed login message that warns you that you only have one attempt left, and that you probably should use the forgotten password form).
Incorrect password message
Unknown user message
Unknown email notification
Too many failed login message
Lockout screen
Profile updates now happen seamlessly. When you write something new on your profile, the new content will be displayed (with formatting if you use our markdown language) without refreshing the page, so you can easily move onto the next section without having to scroll all the way down from the top of the page. We also display an error message if you have an unclosed markdown tag. Unfortunately, we no longer offer a preview to help you find unclosed tags, but I think we should be able to add this back (now that I’ve learned more JavaScript).
Unclosed markdown tag message
Photos are also almost seamless. Updating captions and deleting images are seamless. Reordering images still requires a page reload (which is only there to update the main profile picture on the top of the page), but we can easily change this to be seamless (I’m sure I can also update the main profile pictures[iii] with JavaScript if need be). I need to completely rewrite our upload form to make that seamless and not require a redirect to another page (I’m thinking a pop-up window with the form on the main gallery page).
We now get your location from your IP address. Okay, we’ve always done this for security reasons (so you can see unauthorized logins). However, we now use this to suggest what location to put on your profile. On profile setup, you’ll see the location box automatically populated with what we believe is your location (based on your IP address). You’re welcome to change it if our guess is wrong, and, to make it easier for you (or harder if you’re planning on spoofing your location), suggestions will be ordered by distance from where your IP address tells us you are. The same is true of all other instances of the location search (on your profile, the search page, etc). We also have some code to crack down on location spoofing. Basically, when you log in, we cross-reference your IP location with our locations database and then store all the locations within 10 miles in our record of the login. We go with 10 miles because, we know geolocating IP addresses isn’t accurate, which will throw up false negatives, and hopefully to account for large cities (for example, if you live in the Roehampton neighbourhood of London, it won’t get mad at you for putting “London” as your location instead of “Roehampton” (I think in all my time using OkCupid from London, I only twice saw users put in their neighbourhood instead of just “London” (I actually dated one of them for a while)). Then, when someone looks at your profile, we look to see if your listed location appears in the list of all the locations you’ve logged in from (and all locations within 10 miles) and display a note saying if you’ve logged in from the shown location or not. It’s not 100% accurate, it cannot take VPNs into account (yet), and it doesn’t take tourists into account (e.g. someone in Brazil could spoof their location as being in London if they’d been on vacation in London) (although, putting a date limit on this could help reduce the chances of this), so I’m debating if we should make it available to everyone or just Super Members. But location spoofing is a serious problem with online dating, so having a way to weed out location spoofers, regardless of how accurate it is, it should be a useful feature.
Accurate location
Inaccurate location
I’ve also been working on session retention. Basically, if you closed the browser tab, it would end the session. This is because we were relying on basic PHPSESSID, which gets removed on close of the last instance (or when Chrome for Android is inactive for more than 5 minutes). I found a workaround for this with custom cookies, but it also screwed up the remote logout. When you force an unauthorized session to log out, it didn’t log them out because our custom cookie was just logging them back in again, so, I had to find a workaround for that as well. It seems to work, but still needs more testing. I also use a custom cookie to make logging in from the same device you’ve used before but with a different IP address less annoying. Before, if we spotted a login from a new IP address, even if it was the same device (say, logging in from your phone while travelling), it would block your login and send you an email with a confirmation code that you’d have to enter before regaining access to your account. This, obviously, would be annoying. Now, it should only require the login confirmation if you log in from a different device. Obviously, this is all security critical, so I can’t go into too much detail on how it works.
Finally, a quick update I did earlier today (well, yesterday now) that I’d been thinking about for a while. On my OkCupid profile, I had links to some of my favourite songs on YouTube (more specifically, I had an A to Z list of my favourite artists (in c.2014) with links to some of my favourite tracks from each of them). In fact, they’re still there (see below). The only problem is that, in around 2017, Match Group changed how profile sections are populated with the user generated content (i.e. what you write on your profile). As a result, it just shows the HTML as plain text now (although, it does convert the URL to a hyperlink). I loved having this on my profile because it helped me stand out. The favourites section on anyone’s profile was always the most boring part, and I would often skip reading it, but it didn’t have to be boring. So, linking to music that helped define me made my favourites section less boring than most, and I got some compliments about it. So, recently, I’d been thinking about making it more widely available, and having it so people didn’t have to open a new browser tab to be able to listen to the music. The solution was to add a YouTube tag to our markdown language that embeds YouTube videos on your profile. You can use more or less any style of YouTube URL (I think I’ve tested all of them, but who knows) or even just the video ID, and it will embed the video on your profile for anyone to see. Obviously, the original purpose was to give people an idea of the kind of music you’re into and give your profile a soundtrack; however, it can be used for more than that. For example, you could record a video of yourself doing your favourite hobby, maybe have a video intro where you talk about yourself and what you’re looking for, or maybe recite your favourite poem. The possibilities are endless. Just upload your video to YouTube, paste the URL somewhere on your profile (within the [yt]/[/yt] tags), and let people see/hear you. Unfortunately, it doesn’t work with playlists yet, but that shouldn’t be too hard to implement.
Snippet from my OkCupid profile
Embedded YouTube video
The markdown tag for the embedded YouTube video
With all that done, there’s still a LOT more to do.
I want to make the search page completely JavaScript-based. At the moment, the only JavaScript we use is for updating the results with an infinite scroll (similar to what we did with updates (see endnotes)), the location search, and the interest search bar. Form population and submission are handled completely by PHP. This means having to reload the page on form submission, even when changing the sort order. What I want to do is handle form submission with JavaScript/AJAX, which should give you a seamless experience with less waiting. We could also have the form submit on change, meaning you get results as soon as you check a box or change anything without having to click ‘search’. And, most importantly for me, it should simplify the code, removing about 1,000 lines of redundant code (the search function in its entirety is about 3,000 lines of code).
The same needs to be done with questions. I’ve never been happy with our questions section, so it will be a complete overhaul from the ground up. I also want to add an ‘answer in private’ option so people won’t be able to see your answers to questions you don’t want others to see your answer to. Of course, questions answered in private will still count towards your match/friend/enemy ratings.
I want to add tests/quizzes. We have some code for it, but, like everything else I wrote about 10 months ago, it’s very clunky. I wasn’t happy with it, so I ended up removing it completely. So, a JavaScript update is much needed.
Mobile styles need to be overhauled. I started it, made a new navigation bar, but never got around to making EVERYTHING stylized for mobile (mainly because it would require rewriting EVERYTHING… or, nearly everything).
Mobile layout
And, on the subject of the navigation bar: I want to redesign the desktop navigation bar (again) to make it look more modern and make it easier to use. However, that won’t happen until I’m ready to completely overhaul the design on the website.
I’m also honing in on a name, but suggestions are always welcome.
I’ve seen a bit online about profile linking for people in non-monogamous relationships (mainly because Match Group are in the process of removing it from OkCupid). I’m considering adding something like this, but, until I do, there’s always just tagging other users on your profile. And, while we’re on the subject of tagging, I think I might make it consensual. Like, if you tag a user, they would have to accept it before the tag would appear on your profile. I need to figure out how to implement that.
And, while we’re on the topic of things OkCupid used to have: I really enjoyed the ability to suggest edits to other people’s profiles. This was back in 2010/2011, and was one of the first things to be scrapped in the Match Group takeover (along with quizzes, user blogs, and The Psychologist Game). My partner at the time and I would have full on conversations on each other’s profiles that everyone could see. She would edit my profile, I would respond to what she said, then she’d edit my profile again responding to my response. I need to come up with a way to recreate that.
A few months ago, I overhauled how we handle genders; a side effect of this is that we can easily add new genders (as soon as I write the code for adding them). Related to this, I do want to overhaul how to handle pronouns. At the moment, the pronouns we use are based on gender. So, a woman (either cis and trans) is referred to as ‘she’/’her’, an intersex or non-binary person is referred to ‘them’/’they’, etc. However, I want to have user-selected/user-added pronouns, so you can decide which pronouns are used when the site refers to you.
I’m considering using locations based on IP address with the messaging filters instead of user input locations, so, if you do have the distance filter set, messages from location spoofers who claim to be within your search radius but are actually outside of it will be put in your ‘other’ message box instead of your inbox.
Finally, I’m planning initial deployment within the next couple of months (which I’ve been saying for the last couple of months). I’ve got a server I can use to deploy a beta version of the site, I just need to set it up. Membership levels (either Free Member or Super Member) for beta testers will be selected at random (literally the roll of the dice), and then all beta testers will be given free lifetime Super Member status at the end of the beta programme, regardless of which member level you’re assigned.
Addendum:
Here’s how far the website has come in the last 50 weeks.
How it started
How it’s going
[i] On the subject of the messaging system, there are is still two one slight bugs. Firstly, long story short: we had to switch to a fixed height for the main element on the message page, as a result, our expanding textarea (where you type out the message you’re going to send) bumps into this when you’re writing a long message, which makes the page jump up and down. There should be an easy fix… just limit the height of the textarea so it doesn’t bump into the limit of the main element (similar to how textareas work on other app/websites, like the message textarea on Facebook Messenger and comment textareas on Facebook). Secondly, at the moment, if you receive a message when scrolled up, it automatically jumps back down to the most recent message; I’d like to have a button pop up that notifies you of the new message, and only scroll down when you click it (I thought I had implemented it, but it clearly doesn’t work).
[ii] The Updates section on the Home page was already using JavaScript/AJAX to load additional updates when the user scrolls down, but it still required reloading to switch between update types, sort order, refresh, etc, and it also meant duplicate PHP code (once on the home page, and once on the backend), but now the user interaction is completely handled by JavaScript, so, when you change the type of updates you’re looking at, the JavaScript clears the updates window and populates it with the new type without refreshing, and we only need the PHP code on the backend.
[iii] We now have three main profile pictures that pop out from under the main one when the user hovers over the thumbnail.
[UPDATE]
I’ve got embedded YouTube playlists working. I’ve tested it with a few kinds of playlist URL and they all work. However, I don’t know if I’ve got them all, so I’ll keep an eye on it. The markdown tags for playlists are the same as with regular YouTube videos, so you can just post the link and the backend will do all the hard work for you.
Playlists (three different ones)
The markdown for playlists.