Header documentation

Technical requirements

When introducing the header into your Nederlandse Loterij website, you need to take a few things into account:

  • The header only works with https, so your website needs to force the user to https.
  • The header introduces a new object on the window scope, named "nlPortal". This object will contain features that allow your site to communicate with the header.
  • Because the header runs on your page, make sure the use of !important in your css is limited.
  • The header has a z-index of 10000, you should make sure all elements are below it (with a few exceptions, like modals). When rendering elements like modals and their overlays over the header, make sure to stay within the range 10001-10999. Flash messages are rendered at 11000, and should ALWAYS render over modals to account for error's happening within the modals.
  • Any old-browser checks/pages should be removed, the portal header will take care of old browsers.
  • When a logged in user needs to accept the terms and conditions or has to fill in mandatory fields, the header will always redirect the user to these pages. The user is not allowed to use the system until the mandatory steps are completed.

Adding the header to your website

To include the external header within your own nlPortal website, add the following code to your page:

<div id="nlportal" style="min-height:60px; background:#f4f7fa;"></div>
<script
type="module"
id="nlportal-header-script"
data-vertical="VERTICAL"
data-theme-overwrite=""
data-regsrc="REGSRC"
data-portal-domain="www.nederlandseloterij.nl"
data-menu-structure="[]"
data-footer="{&quot;copyrightText&quot;:&quot;Copyright Nederlandse Loterij 2020. Alle rechten voorbehouden.&quot;,&quot;linkList&quot;:[{&quot;href&quot;:&quot;https://www.nederlandseloterij.nl/acties&quot;,&quot;target&quot;:&quot;&quot;,&quot;showLoginModal&quot;:false,&quot;noFollow&quot;:false,&quot;title&quot;:&quot;Acties&quot;},{&quot;href&quot;:&quot;https://www.nederlandseloterij.nl/over-ons&quot;,&quot;target&quot;:&quot;&quot;,&quot;showLoginModal&quot;:false,&quot;noFollow&quot;:false,&quot;title&quot;:&quot;Over ons&quot;},{&quot;href&quot;:&quot;https://over.nederlandseloterij.nl/werken-bij&quot;,&quot;target&quot;:&quot;&quot;,&quot;showLoginModal&quot;:false,&quot;noFollow&quot;:false,&quot;title&quot;:&quot;Werken bij&quot;}],&quot;socialMenu&quot;:[{&quot;name&quot;:&quot;x&quot;,&quot;href&quot;:&quot;Q42.Cms.Core.Domain.Atoms.UrlLink&quot;,&quot;target&quot;:&quot;_self&quot;},{&quot;name&quot;:&quot;youtube&quot;,&quot;href&quot;:&quot;Q42.Cms.Core.Domain.Atoms.UrlLink&quot;,&quot;target&quot;:&quot;_self&quot;},{&quot;name&quot;:&quot;instagram&quot;,&quot;href&quot;:&quot;Q42.Cms.Core.Domain.Atoms.UrlLink&quot;,&quot;target&quot;:&quot;_self&quot;},{&quot;name&quot;:&quot;facebook&quot;,&quot;href&quot;:&quot;Q42.Cms.Core.Domain.Atoms.UrlLink&quot;,&quot;target&quot;:&quot;_self&quot;},{&quot;name&quot;:&quot;linkedin&quot;,&quot;href&quot;:&quot;Q42.Cms.Core.Domain.Atoms.UrlLink&quot;,&quot;target&quot;:&quot;_self&quot;},{&quot;name&quot;:&quot;tiktok&quot;,&quot;href&quot;:&quot;Q42.Cms.Core.Domain.Atoms.UrlLink&quot;,&quot;target&quot;:&quot;_self&quot;}],&quot;nloLinkList&quot;:null}"
data-search-url="/zoeken?q="
data-no-auth-refresh
data-no-login
data-no-age
src="https://portal-header-cdn.nederlandseloterij.nl/statics/nlportal-header.mjs"
async></script>
<script
nomodule
id="nlportal-header-script"
data-vertical="VERTICAL"
data-theme-overwrite=""
data-regsrc="REGSRC"
data-portal-domain="www.nederlandseloterij.nl"
data-menu-structure="[]"
data-footer="{&quot;copyrightText&quot;:&quot;Copyright Nederlandse Loterij 2020. Alle rechten voorbehouden.&quot;,&quot;linkList&quot;:[{&quot;href&quot;:&quot;https://www.nederlandseloterij.nl/acties&quot;,&quot;target&quot;:&quot;&quot;,&quot;showLoginModal&quot;:false,&quot;noFollow&quot;:false,&quot;title&quot;:&quot;Acties&quot;},{&quot;href&quot;:&quot;https://www.nederlandseloterij.nl/over-ons&quot;,&quot;target&quot;:&quot;&quot;,&quot;showLoginModal&quot;:false,&quot;noFollow&quot;:false,&quot;title&quot;:&quot;Over ons&quot;},{&quot;href&quot;:&quot;https://over.nederlandseloterij.nl/werken-bij&quot;,&quot;target&quot;:&quot;&quot;,&quot;showLoginModal&quot;:false,&quot;noFollow&quot;:false,&quot;title&quot;:&quot;Werken bij&quot;}],&quot;socialMenu&quot;:[{&quot;name&quot;:&quot;x&quot;,&quot;href&quot;:&quot;Q42.Cms.Core.Domain.Atoms.UrlLink&quot;,&quot;target&quot;:&quot;_self&quot;},{&quot;name&quot;:&quot;youtube&quot;,&quot;href&quot;:&quot;Q42.Cms.Core.Domain.Atoms.UrlLink&quot;,&quot;target&quot;:&quot;_self&quot;},{&quot;name&quot;:&quot;instagram&quot;,&quot;href&quot;:&quot;Q42.Cms.Core.Domain.Atoms.UrlLink&quot;,&quot;target&quot;:&quot;_self&quot;},{&quot;name&quot;:&quot;facebook&quot;,&quot;href&quot;:&quot;Q42.Cms.Core.Domain.Atoms.UrlLink&quot;,&quot;target&quot;:&quot;_self&quot;},{&quot;name&quot;:&quot;linkedin&quot;,&quot;href&quot;:&quot;Q42.Cms.Core.Domain.Atoms.UrlLink&quot;,&quot;target&quot;:&quot;_self&quot;},{&quot;name&quot;:&quot;tiktok&quot;,&quot;href&quot;:&quot;Q42.Cms.Core.Domain.Atoms.UrlLink&quot;,&quot;target&quot;:&quot;_self&quot;}],&quot;nloLinkList&quot;:null}"
data-search-url="/zoeken?q="
data-no-auth-refresh
data-no-login
data-no-age
src="https://portal-header-cdn.nederlandseloterij.nl/statics/nlportal-header.js"
async></script>

<script
id="nlportal-browser-detection"
src="https://portal-header-cdn.nederlandseloterij.nl/statics/nlportal-browser-detection.js"
async></script>

Please make sure you set the data-vertical attribute to the appropriate vertical slug value, selected from the list below:

Also, make sure to modify the data-regsrc attribute to have the value of the vertical's assigned registration source (should be an integer).


Additional attributes/options:

  • data-no-cookie-banner

    Use with caution only when there's another cookie banner succeeding the portal cookie banner this should be used.

  • data-no-auth-refresh

    Disables refresh on login. Do not include this attribute if you specifically depend on a refresh.

  • data-no-login

    Hides the login/register button.

  • data-no-age

    Hides the 18+ logo and link from the header. If you already loggedin via a vertical the right portal menu will still be visible.

  • /?hideHeader=true

    Add this to the url of site that includes the portal header, and it will hide the header (with css) but all functionality will be available.

    This will propogate throughout all the verticals in the same session. This is setting a cookie that will keep this hidden for the session.
  • /?hideFooter=true

    Add this to the url of site that includes the portal footer, and it will blcok the footer render.

    This will propogate throughout all the verticals in the same session. This is setting a cookie that will keep this hidden for the session.

Adding main navigation

It is possible to add navigation items inside the main header bar. This should primarily be used for main navigation to vertical pages.

The links will be shown when a valid JSON structure is supplied inside the data-menu-structure attribute. Inside the menu structure you can supply title, href, target (optional) and showLoginModal (optional).

Two examples:

data-menu-structure='[
  {"title": "Over ons", "href": "/over-ons"},
  {"title": "Video&#39;s", "href": "/videos", "target": "_blank"}
]'
data-menu-structure='[
  {"title": "Over ons", "href": "/over-ons"},
  {"title": "Mijn Vertical", "href": "/mijn-vertical", "showLoginModal": true}
]'

Optionally you can also provide a nested link structure to show a dropdown menu.

  • You can supply an optional dropdownLinks property with an array of link objects as documented above.
  • The href property will then be optional, as it toggles the dropdown and doesn't redirect the user anywhere.
  • Theres also the option to open specific dropdown links by default for mobile users, by setting `dropdownLinksInitiallyOpenedOnMobile` to true for that group. By default it is false and the group will be collapsed.

Nested dropdown example:

data-menu-structure='[
  {
    "title": "Over ons",
    "href": "/over-ons"
  },
  {
    "title": "Mijn Vertical",
    "dropdownLinksInitiallyOpenedOnMobile": true,
    "dropdownLinks": [
      {
        "title":"Loten",
        "href": "/mijn/loten",
        "showLoginModal": true
      },
      {
        "title":"Abonnement",
        "href": "/mijn/abonnement",
        "showLoginModal": true
      },
    ]
  }
]'

Demos:

Important

There is currently no mechanism that checks if the amount of menu items fits in the portal header. Please check it yourself. The breakpoint for the mobile navigation is at 1200px. So make sure that all items fit on a 1201px wide viewport.

Adding the footer

To allow nlPortal to render the footer, the optional data-attribute data-footer must be specified to the nlPortal script tag. If this attribute is specified, a footer element will be mounted on the element with id #nlportal-footer or an override specified in the data-footer json object.

It is advised to place the footer as close to the root document as possible to prevent conflicting stylesheets of the vertical inside the portal footer. Therefore a recommended structure would be:

<body>
  <header id="nlportal-header"></header>
  <div id="vertical-site">
    ...
  </div>
  <footer id="nlportal-footer"></footer>
</body>
			

This attribute expects a valid JSON structure and can contain the following properties:


Property Type Default Required Description
id String #nlportal-footer No The id of the element that the footer will mount on
copyrightText String Default NLO copyright string No Copyright paragraph underneath the footer navigation
linkList Array of objects [] No List of vertical specific links (most left navigation)
socialMenu Array of objects [] No List of social links
nloLinkList Array of objects [] No List of portal specific links (third column)

The linkList and nloLinkList array may contain the same object values as the main navigation links, except for dropdownLinks as they are unsupported in the footer navigation. Social links have a similar object signature as the links in the linkList and may contain:


Property Type Default Required Description
name String - Yes The name of the platform, must be:
"facebook" | "instagram" | "linkedin" | "x" | "youtube" | "tiktok"
href String - Yes The URL to the vertical social page of provided platform
target String _blank No Target may be e.g. _self to open in the current tab

Example:

data-footer='{
  id: "#nlportal-staatsloterij-portal",
  copyrightText: "Copyright Nederlandse Loterij 2020. Alle rechten voorbehouden.Copyright Nederlandse Loterij 2020. Alle rechten voorbehouden.",
  linkList: [
    {"title": "Verkooppunten", "href": "/verkooppunten", "target": "_blank"},
    {"title": "Over ons", "href": "/over-ons"}
  ],
  socialLinks: [
    {"name": "facebook", "href": "https://www.facebook.com/Staatsloterij", "target": "_blank"},
    {"name": "x", "href": "https://x.com/staatsloterij", "target": "_blank"}
  ],
  nloLinkList: [
    {"title": "Deelnemersreglement", "href": "https://nederlandseloterij.nl/deelnemersreglementen", "target": "_blank"},
    {"title": "Jaarstukken", "href": "https://www.nederlandseloterij.nl/jaarstukken"}
  ]
}'

Adding extra wallet items

It is possible to add extra wallet items. This should primarily be used to display loyalty program (e.g. Club Staatsloterij) balances.

The balances will be shown when a valid JSON structure is supplied inside the data-wallet-items attribute. Inside the wallet item structure you can supply name and amount.

Example:

data-wallet-items='[
  {"name": "Club Staatsloterij", "amount": "90 punten"}
]'

Demos:

Adding a search button

A search button can be added to the header to search through your site. Clicking the button will open a modal with a search box which allows users to search.

The button is shown if a search URL has been supplied through the data-search-url attribute.

When searching, the supplied URL will be loaded with the entered search terms appended behind the URL. For instance, if the URL /search?q= is supplied, the browser will load /search?q={searchterms} when searching.

Attributes during development

All links and endpoints map to the production environment to avoid end-users being redirected to the development environments. These domain mappings can be overwritten by providing the desired portal domain through a header script tag attribute.

By default the portal domain will be www.nederlandseloterij.nl. This can be overwritten by providing the data-portal-domain attribute:

data-portal-domain="www.nederlandseloterij.nl"

Important

Please note that the above values should never be released to production. Make sure you use the attributes mentioned only in a development environment.

Headerless mode

When a page is not loading the header, the browser detection script should still be included.

<script
id="nlportal-browser-detection"
src="https://portal-header-cdn.nederlandseloterij.nl/statics/nlportal-browser-detection.js"
async></script>

In this case the data-portal-domain attribute is moved to the browser detection script on development environments. If you forget this, the browser detection script will redirect you to the production environment instead.

JavaScript API

The header has a JavaScript API which can be used by logic on the vertical. The API works by using functions on the globally available "nlPortal" object and returns promises for all function calls.

nlPortal.login()

Opens the login modal. If the user is already logged in, the promise will resolve immediately. If the user closes the login modal window, the promise will reject.

The user will be forwarded to the portal login page, for multifactor requirements. If you want the user to return to your site, add a return-url to the nlPortal.login({ returnUrl: URL }) function call. The user will be forwarded to that url once they are logged on. Make sure it is a url on the Nederlandse Loterij domain.

Resolve

The resolve of the login method receives an argument, which indicates if the user logged on during this nlPortal.login() call. This makes it easier to know if you should refresh your UI.

Usage

nlPortal.login({ returnUrl: window.location.href })
  .then(function() { console.log('Logged in.') })
  .catch(function() { console.error('Not logged in.') })

nlPortal.logout()

Logout user. The user is redirected to the portal logout page and if a return url is given the method will automatically redirect.

Usage

nlPortal.logout(window.location.href);

nlPortal.openPaymentModal()

Opens the payment modal, which will forward the user to the payment flow once the amount and bank selection has been done. It is possible to modify the preset payment amounts in the modal to suit your needs. The function accepts an array containing the amounts in cents.

This function has the following arguments:

  1. Array, containing amounts in cents. This sets the predefined value buttons to the given values. Example [1000, 2500, 7500].
  2. Success return url, this is where the user is taken once the payment is successfull. Will default to current url if no url is given.
  3. Fail return url, this is where the user is taken once the payment has failed. Will default to current url if no url is given.

Usage

nlPortal.openPaymentModal(
  [1000, 2500, 7500],
  'http://example.com/success',
  'http://example.com/fail'
).catch(function() {
  console.log('User has closed the modal before submitting or was not logged in.')
})

nlPortal.getAccount()

Retrieves the account data of the current user. This function returns a promise that will resolve when the account data can be retrieved or reject otherwise.

Usage

nlPortal.getAccount()
  .then(function(data) { console.log('Got account:', data) })
  .catch(function() { console.error('Not logged in.') })

Return data

{ "total": 186500, "cash": 186500, "bonuses": [], "loyaltyPoints": 0 }

nlPortal.getWallet()

Retrieves the wallet of the current user. This function returns a promise that will resolve if the wallet can be retrieved or rejected if the wallet could not be retrieved.

Usage

nlPortal.getWallet()
  .then(function(data) { console.log('Got wallet:', data) })
  .catch(function() { console.error('Not logged in.') })

Return data

{ "total": 186500, "cash": 186500, "bonuses": [], "loyaltyPoints": 0 }

nlPortal.checkLoggedIn()

Retrieves the logged-in status of the user. Returns a promise. The promise resolves if the user is logged in and rejects if the user is not.

Usage

nlPortal.checkLoggedIn()
  .then(function() { console.log('Logged in.') })
  .catch(function() { console.error('Not logged in.') })

nlPortal.onLogin()

Deprecated from april 2023

nlPortal.onLogout()

Deprecated from april 2023

nlPortal.showFlashMessage()

Shows a flash message at the top of the viewport. You can supply a message type (success, notification or error) and the message itself.

Usage

nlPortal.showFlashMessage('success', 'Bet successfully placed.')

Information was previously known as notification, but acts the same since it's the fallback styling.

An optional third parameter can be added to change the auto hide behaviour of the messages. This will default to true if no auto hide behaviour is given.

Usage

nlPortal.showFlashMessage('error', 'Your subscription payment failed.', false)

nlPortal.showEmergencyMessage()

Shows an emergency message just below the header. You can supply a message to be shown until a user dismisses the message. This message is only meant to be show when a vertical is experiencing system disruptions.

Usage

nlPortal.showEmergencyMessage('We are currently experiencing issues regarding our ticket checker, please come back at a later time.')