GDPR Compliance for UK Web Developers: A Practical Explainer

GDPR Compliance for UK Web Developers: A Practical Explainer

Most UK-facing web apps have a privacy policy. Far fewer have a data map, a consent log, or a documented way to pull everything held about one person into a single file. That gap is where GDPR problems usually sit: not in the wording of the policy, but in the plumbing underneath it.

UK GDPR, sitting alongside the Data Protection Act 2018, applies to almost anything you build for a British audience. You won't be choosing your client's lawful basis, and you shouldn't try. You will be implementing it, though, and the detail lives in the implementation. The Information Commissioner's Office does not fine people for ugly privacy pages. It fines them for collecting data they cannot justify, keeping it longer than they said, and being unable to prove any of it when asked.

Know whether you are a controller or a processor

The client usually decides why data is processed, which makes them the controller. You process it on their instructions, which makes you a processor. That distinction sets your obligations: a written contract with data processing terms, action only on documented instructions, and help with requests and breaches when they arrive.

Step outside that role, by running your own analytics on their users or emailing those users about your services, and you become a controller for that activity. Build your own product and you are the controller throughout. Both roles can apply to the same codebase, sometimes in the same request: you process a customer's data on the client's behalf, then log the request into your own error tracker, where you are deciding the purpose.

Get this wrong and everything downstream is muddled. The contract is the cheap part; the discipline of staying inside your instruction set is the hard part.

Start with a data map, not a privacy policy

A data map lists every place personal data enters, moves and rests. Write it before the privacy policy, otherwise the policy describes what you hope happens rather than what does.

For each flow, record:

  • what is collected (email, name, IP address, device fingerprint, payment reference)
  • where it comes from (signup form, payment webhook, support inbox)
  • why it is needed, and the lawful basis the controller relies on
  • where it is stored (database, object storage, CRM, log aggregator)
  • who can see it (staff roles, subprocessors, regions)
  • how long it is kept, and what deletes it

Keep the map in the repository as Markdown or YAML beside the schema. If a pull request adds a date_of_birth column, the map changes in the same commit. A document nobody updates is worse than none at all, because it creates false confidence.

A worked example

An accounts table with email, hashed password and created_at is simple. Add signup IP, a marketing consent flag, last login and a payment provider's customer ID and the same table now touches UK GDPR, PECR and financial data. None of that is a problem, so long as someone can say where each field came from and when it goes.

Run the exercise against your own schema and count how many columns you cannot justify to a stranger in one sentence. That number is your backlog.

Cookies, consent, and where tags actually load

Cookies fall under PECR, with UK GDPR covering the personal data they produce. Strictly necessary cookies can be set without consent. Everything else needs consent first.

The details that catch people out:

  • Block at the tag level. Rendering a banner while your analytics script has already fired is consent theatre, and it is the first thing a complainant or auditor spots.
  • Reject must be as easy as accept. One click each, equal prominence, no grey-on-grey.
  • Pre-ticked boxes are not consent. Neither is "by continuing to browse".
  • Record what was shown and chosen: banner version, timestamp, categories accepted. If you cannot show consent, you cannot rely on it.
  • Make withdrawal as simple as giving it. A footer link that reopens the banner is enough.

Store the consent record server-side as well as in localStorage. Users clear browser storage, and then you have no evidence. Tag managers deserve particular suspicion: it is easy to add a pixel through the interface months after launch, bypassing the consent gate entirely. If tags are configured outside the codebase, review them on a schedule.

Subject access requests and erasure

A controller generally has one month to answer a subject access request. If the answer means a developer exporting rows by hand from three systems, you will miss it.

Build two capabilities early:

  1. A lookup that finds every record for a given identifier across the main database, file storage, support tooling and any processor with an API.
  2. An export that produces a single, human-readable bundle — JSON plus attachments — with a checksum and a covering note.

Test both against a real test account each quarter. An untested export is a hypothesis, not a capability.

Erasure is the harder half. Deletion requests usually meet three obstacles: data copied into a warehouse, rows in immutable backups, and free-text fields such as support tickets where a name is buried in prose. The defensible answers are documented ones. Give the warehouse a rebuild-from-source policy, let backups expire on a fixed window rather than trying to edit them, and treat support tickets with a scripted redaction step. Partial deletion with a written rationale beats pretending everything vanished.

Breach response and the 72-hour clock

If personal data is exposed accidentally or unlawfully — a misconfigured bucket, a leaked API key, a laptop left on a train — the controller must notify the ICO within 72 hours of becoming aware, where the breach is likely to risk people's rights. As a processor you must tell the controller without undue delay, which in practice means a named contact and a phone number, not a support queue.

Do the prep before the incident:

  • Know who to call. Put the client's data protection contact in the runbook, not a wiki page nobody opens.
  • Keep logs that answer the right questions. What was accessed, by whom, from where, for how long.
  • Have a template ready. A short factual write-up — what happened, what data, how many people, what you have done — is most of the notification.
  • Do not investigate in silence for a week. A partial update within hours beats a complete one after the deadline.
Auditors rarely ask whether you had a breach. They ask how long it took you to know, and what you did next.

Retention, deletion and the backups problem

Everything in the data map needs an expiry. "We keep it forever" is not a retention policy; it is a liability with a schema.

  • Default to short: logs thirty to ninety days, session data until logout, marketing data until consent is withdrawn plus a brief grace period.
  • Automate deletion and show what it removed. Manual clean-ups die at the first busy sprint.
  • Handle backups honestly. You cannot delete one row from an immutable snapshot; document the window and confirm restores do not resurrect deleted accounts.
  • Check third parties. Your database host, email provider and error tracker all have retention defaults, and some default to indefinite.

Make it testable

Compliance that only exists in a document is a promise. Compliance that exists as code is a property you can check. A quarterly review that runs a test export, verifies the consent log records a withdrawal, and confirms the retention job ran is worth more than a folder of policies nobody has opened since delivery.

None of this is glamorous. It is schema, cron jobs, contracts and a phone number that someone actually answers. That is the whole job.

Photo: Markus Winkler / Pexels