EXP 20 Backend Summary Current Implementation

länk applicant newsletters

Summary of all newsletter conditions, sending logic, flow, and email design

This page documents the current backend logic for both applicant newsletters: the regular weekly-style newsletter in `good_matches()` and the infrequent SendGrid newsletter in `infrequent_good_matches()`.

Implementation Map

Eligibility queries
apps/match/utils.py
Regular send task
apps/match/tasks.py::send_good_matches()
Infrequent send task
apps/match/tasks.py::send_infrequent_good_matches()
SendGrid mail assembly
apps/common/sendgrid.py::send_infrequent_job_newsletter_mail()
Email template
templates/emails/infrequent_job_newsletter.hbs

1. Regular Newsletter

Power Automate

Source: good_matches() + send_good_matches()

  • User must not be anonymous.
  • User must not be matching-blocked.
  • Applier must be the latest applier record for that user.
  • Applier must not be historical.
  • Applier must be registered for at least 3 days.
  • Applier must not be older than 180 days since `newest_registration_date`.
  • Applier status must not be `HIDDEN`.
  • If applier status is `HIRED`, the latest hired status change must be at least 90 days old.
  • `CANCELLED` appliers are allowed.
  • Match stage must be `NEW`.
  • Job status must be `ACTIVE`.
  • Match fit probability must be at least `0.70`.
  • Match creation date must be within the last 7 days.
  • Users unsubscribed from `APPLICANT_JOB_NEWSLETTER` are excluded.
Delivery: sends only `match_ids` and `environment` to Power Automate. The mail content is not assembled in Django for this flow.

2. Infrequent Newsletter

SendGrid

Source: infrequent_good_matches() + send_infrequent_good_matches()

  • User must not be anonymous.
  • User must not be matching-blocked.
  • Applier must be the latest applier record for that user.
  • Applier must not be historical.
  • Applier must be registered for at least 21 days.
  • Applier status must not be `HIDDEN`.
  • If applier status is `HIRED`, the latest hired status change must be at least 90 days old.
  • `CANCELLED` appliers are allowed.
  • Applier must have no open application in `open_forwardings` stages.
  • Applier must not have received the regular newsletter in the last 14 days.
  • Applier must never have received this infrequent newsletter, or the last send must be at least 8 weeks ago.
  • Only `NEW` matches on `ACTIVE` jobs qualify.
  • Match fit probability must be at least `0.70`.
  • At least 3 qualifying matches are required.
  • Users unsubscribed from `APPLICANT_JOB_NEWSLETTER` are excluded.
  • SQL result is randomized and capped with `LIMIT %(max_appliers)s`.
Current cap in code: `INFREQUENT_NEWSLETTER_MAX_APPLIERS = 3000`. Each selected applier gets a personalized SendGrid message with rich match payload.

3. Match Selection Rules

Regular newsletter

Keeps all qualifying matches for each applier and forwards their IDs to Power Automate.

Infrequent newsletter

  • Maximum of 5 matches per applier in the rendered email.
  • First pass prefers company variance: ideally one job per company.
  • Second pass fills remaining slots with the next best matches if there are not enough distinct companies.
  • Order is driven by highest `fit_probability`, then `id`.

Links and tracking

  • Match CTA links include UTM params on the applicant match URL.
  • `Alle Jobs ansehen` links also include newsletter UTM params.
  • `Profil aktualisieren` CTA points to the applicant profile with its own UTM campaign.

4. Sending and Volume Constraints

Regular

Sent through Power Automate. Django posts only a minimal payload: match_ids plus environment.

Infrequent

Sent directly through SendGrid with rich per-applier dynamic template data.

SendGrid handling

  • SendGrid request chunk size is controlled by SENDGRID_MAX_PERSONALIZATIONS_PER_REQUEST = 1000.
  • Each personalization contains one recipient, one BCC to verlauf@laenk.de, and dynamic template data.
  • ASM group id for applicant newsletter unsubscribe is 18773.
  • If no template id is configured, the mail send is skipped and a warning is captured.

5. Flow Chart

End-to-end
Start scheduled task weekly good_matches or infrequent_good_matches Run eligibility query status, timing, fit, unsubscribe, match stage, job status, cooldowns Any eligible appliers? If no, task exits early Regular newsletter branch Keep all qualifying match IDs POST match_ids + environment to Power Automate Log applier history on HTTP 200 Infrequent newsletter branch Random SQL sample, capped at 3000 appliers Build rich payload per applier Choose max 5 matches per applier Prefer one job per company when possible Generate UTM links and CTA data SendGrid send phase Skip recipients missing email/template Skip users unsubscribed from mail channel Chunk into 1000 personalizations/request Send template with ASM group 18773 Collect mailed applier ids for history logging Write ApplierHistory Regular: all successful PA recipients Infrequent: only mailed applier ids

6. Infrequent Email Design

Current HBS template

The infrequent newsletter is a responsive SendGrid dynamic template. It is designed as a clean white card on a light gray background, with länk violet as the main accent color.

  • Subject is personalized with first name when available.
  • Hero copy changes between single-job and multi-job mode.
  • Each job card shows company name, top-right logo, position title, location, care type, and working type.
  • Primary CTA on each card: Job ansehen.
  • Secondary global CTA: Alle Jobs ansehen.
  • Footer CTA block: Profil aktualisieren.
  • Footer includes profile/settings link and ASM unsubscribe links.
  • Mobile styles collapse CTAs to full width under 600px.

Data injected per recipient

  • applier: name, first name, email, profile URL, all-jobs URL
  • matches: up to 5 serialized matches
  • more_than_one: toggles singular vs plural copy

7. Practical Takeaways

Regular

Simpler and broader. Time-window based, no open-application check, and still delivered by Power Automate.

Infrequent

More selective and more productized. It has cooldowns, open-app filtering, company variety, and a polished SendGrid email.

Operational note

The current codebase documents a `3000` applier cap for the infrequent flow and SendGrid chunking of `1000` recipients per API request.