Toggle document index

What each app does

The hub

The hub handles as much as possible, so that job board apps are as thin as possible. Any functionality that is common to all or many job boards is in the hub.

Handling installs

When the hub is installed, it checks for existing installed job board apps and updates its installed boards table.

Showing the settings page

The hub's settings page lets the admin user control the legacy source code field for each installed board.

The field defaults to defaultLegacySourceCode as passed by the board via GET /jobBoards/forApp.

When legacy source code is set against a board, all linkouts for postings on that board will have a "source=" parameter appended with that value.

Some ATS's will be able to use the information in the tracker for sourcing purposes and won't need this field set.

Showing the job panel

The hub injects a panel for creating and updating postings into the job page in the ATS.

This shows a list of the existing postings for the job, across all boards, including:

  • the board's icon (shrunk)
  • the posting title (truncated)
  • the status message (listing expired, job closed, etc.)
  • menu/links to:
    • Repost (re-open)
    • Edit (shows the posting wizard again)
    • Expire (close)

The panel also allows creating new postings by clicking a board's icon. The user then is redirected to the posting form in a full window.

Showing the posting form

The posting wizard is a web page served by the hub to capture the user data (job title, categories etc.) for a posting.

In the fields section of the posting form, the hub captures the job board's required fields (title, reference, description etc. and category values).

  1. To decide which common fields to display, the hub asks the board for it's settings
  2. To populate the category fields, the hub asks the job board for its categories
  3. To set defaults for the categories, the hub calls the category mapping API
  4. In the scheduled close date field, recruiter sees today + 30, though underneath the field is null
  5. The recruiter could also set scheduled close date to a value, e.g. so the posting is only open for 10 days. Or to a year in the future, in which case the posting would remain active for a year, being re-billed every 30 days.
  6. Once the user has ok-ed the form, the hub:
    1. creates a posting object in its own database. The posting object holds all the data needed to post the job, including the fields.
    2. sends a "new posting" delta ping to the relevant job board app.
note right of poster: poster grabs common details: note right of poster: get title, description poster->ats: GET /jobs/byID/{} note right of poster: get category drop down values poster->board: GET /jobBoards/forApp/categories poster->board: GET /jobBoards/forApp/categories/byID/{} poster->board: GET /jobBoards/forApp/categories/byID/{}/values note right of poster: get mappings (to set defaults) poster->mapper: POST /jobBoards/forApp/{app}/mappings note right of poster: poster pops UI so user can\nedit title, description, categories note right of poster: get link to board's\niframe-ed custom fields UI (if any) poster->board: GET /jobBoards/forApp/postingUI/byID/{posting} note right of poster: Custom fields UI is shown.\n User edits, clicks OK. postMessage\npasses custom fields as json to hub.\nHub updates posting. note right of poster: poster signals that the posting\nhas changed poster->board: POST /jobBoards/postings/byID/{}/tenantDeltaPings

Handling expire, reopen requests

The panel allows the user to click to expire or reopen postings.

The hub responds by:

  1. Updating the posting object (actual close date, close date, status, last updated by email and date)
  2. sending a delta ping to the relevant job board app.
  3. displaying ajax spinning widget in the panel throughout

Building linkout urls, including modern (tracker) and legacy source tracking

For the posting, the hub builds the linkout url leading to the job on the careers site, including source tracking information.

The hub builds this by:

  1. Call GET/BLAH to ask the primary career site for a link to the job
  2. Calling POST /trackers to create a campaign tracker and appending it to the linkout url

If the installed board has its legacy source code set, then the linkout url should have "&source= appended to it."

Processing postings that have expired

A dameon finds all postings that have arrived at their scheduled close date.

The daemon:

  1. sets status = closed
  2. sets actual close date = sysdate
  3. sends delta ping to relevant job board app

Listening for jobs closing in the ATS

The hub listens for jobs closing on the ATS. It closes the attached postings and notifies the relevant job board app.

  1. The hub learns via delta ping that a job has just closed in the ATS
  2. It iterates through all of the postings for that job doing this:
    1. set status = closed
    2. set close date = sysdate
    3. set status message = "Job closed"
    4. send delta ping to relevant job board app

Handling tenant reboots

When the hub starts up after maintenance, or the tenant is rebooted, the hub pulls all category values from all installed job boards.

The job board's categories may have changed, making existing postings held in the hub outdated.

If any existing open postings are found that are using a category value that no longer exists, their stale flag is set. This causes the posting to be displayed e.g. in red in the job panel.

The posting form highlights to the user to which category needs fixing.

When the user successfully submits the posting form, the stale flag is cleared by the hub.

Handling uninstalls

The hub prevents uninstall (returns 400 to DELETE /tenants/{}) if there are installed boards.

When a job board app is uninstalled, the hub preserves all data by updating installed boards table: - prior app shortcode = app shortcode - app shortcode = null

So the tenant can reinstall the app (or another customer who picks up the same tenant shortcode can install it for the first time) and the old data won't be visible.

However the old data can be shown (e.g. with strike through) in the hub's screens and in posting statistics etc.

Maintaining audit history

All changes to postings and installed boards, including who made them and when, are stored in audit tables or otherwise in some persistent store.

Some UI in the hub provides a UI to see and search posting audit data.

More functionality

More UI can be added to the hub that is useful across all job boards, e.g.:

  • List of recent postings across all jobs and boards
  • Show postings per user/category
  • graphs of posting activity
  • Tools like FreshChat

Hub database

Posting objects

  • housekeeping:
    • id
    • installed board id
    • created by email
    • created by date
    • last updated by email
    • last updated by date
    • status (draft, open, closed) - do we need error?
    • status message e.g. "listing expired", "job closed", "error - missing blah", etc.)
    • scheduled close date
    • actual close date
    • stale flag
  • common fields
    • set by user
      • title
      • description
      • ref
      • category values
      • recruiter name
      • recruiter email
      • recruiter team
      • contact person name
      • contact person email
      • application email
      • linkout url
    • set by board
      • preview link
  • board-specific fields
    • custom fields json (e.g. advertiser profile, template, premium features, video)

Installed boards

  • housekeeping:
    • id
    • tenant
    • app shortcode (set before uninstall)
    • prior app shortcode (set after uninstall)
    • legacy source code (when present, causes linkouts for this board to have source=CODE appended to them)
    • setup error message (e.g. invalid credentials). When non-null:
      • new postings can't be created
      • the board appears in the hub's UI with warning icons, which links to the app's setup page

Audit data

Database tables/log files/s3 storage of who did what to which postings and when.

The category mapper

note right of mapper: user opens app note right of mapper: mapper enumerates boards mapper->board: GET /boards/forApp mapper->board2: GET /boards/forApp note right of mapper: mapper gets all nodes\nfrom tenant mapper->board: GET /categories mapper->board: GET /categories/byID/{} mapper->board: GET /categories/byID/{}/values note right of mapper: user starts mapping\nfor first board note right of mapper: mapper gets all nodes from board mapper->board: GET /jobBoards/forApp/categories mapper->board: GET /jobBoards/forApp/categories/byID/{} mapper->board: GET /jobBoards/forApp/categories/byID/{}/values note right of mapper: user maps categories note right of mapper: user maps nodes