Skip to content

Safari

Setting up Developer Account

Note

You should have a MacBook to complete the full Dev Account setup.

  1. Go to https://developer.apple.com/account/resources/identifiers/list and create a new indentifier.
  2. Choose 'Webite Push IDs' and click 'Continue'.
  3. Specify the description and indentifier (preferred to use the app reversed-domain name) and click 'Continue'.
  4. Get certSigningRequest opening Keychain.app > Keychain Access > Certificate Assistant > Request a Certificate From a Certificate Authority..., fill the fields and click 'Continue'.
  5. Go back to the created Website Push ID and click 'Create certificate' to upload the certificate from the previous step. After some small steps you will be able to download the website_aps_production.cer.
  6. Add the downloaded certificate file to Keychain.app and click 'Export 2 items...' to get the certificate and private key (.p12).

Front-end integration

  1. Setup Google Analytics on your main page:

    index.html
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <html lang="en">
      <script type="text/javascript" async="" src="https://www.google-analytics.com/analytics.js"></script>
      <script type="text/javascript" async="" src="https://www.googletagmanager.com/gtag/js?id=<YOUR_ID>&amp;l=dataLayer&amp;cx=c"></script>
      <script type="module" src="chrome-extension://jdkknkkbebbapilgoeccciglkfbmbnfm/hook.js"></script>
      <head>
        <meta charset="UTF-8">
        <title>Push test</title>
        <link rel="manifest" href="manifest.json"/>
        <!-- Global site tag (gtag.js) - Google Analytics -->
        <script async="" src="https://www.googletagmanager.com/gtag/js?<YOUR_ID>"></script>
        <script>
          window.dataLayer = window.dataLayer || [];
          function gtag(){dataLayer.push(arguments);}
          gtag('js', new Date());
    
          gtag('config', '<YOUR_ID>');
        </script>
      </head>
    

  2. Setup APNS script:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    <script>
      const googleAnalyticsData = () => {
        const data = {};
        gtag('get', '<YOUR_GTAG>', 'client_id', clientId => { data.clientId = clientId; })
        return data;
      };
    
      const requestPerm = () => {
        if ('safari' in window && 'pushNotification' in window.safari) {
          let permissionData = window.safari.pushNotification.permission('web.com.artemHrytsenko.fcmflutternotification');
          checkRemotePermission(permissionData);
        }
      };
    
      let gaData = googleAnalyticsData();
    
      const checkRemotePermission = (permissionData) => {
        if (permissionData.permission === 'default') {
          window.safari.pushNotification.requestPermission(
            'https://app.neucurrent.com/push/api', // The web service URL.
            '<WEBSITE_PUSH_ID>',
            {
              "retailer_name": "<RETAILER_NANE>",
              "website_name": "<WEBSITE_TITLE>",
              "allowed_domains": '["https://app.neucurrent.com"]',
              "url_format_string": "https://app.neucurrent.com/push/api/v2",
              "web_service_url": "https://app.neucurrent.com/push/api",
              "device_id": gaData.clientId
            },
            checkRemotePermission
          );
        } 
        else if (permissionData.permission === 'denied') {
          // The user said no.
          console.log('denied')
        } 
        else if (permissionData.permission === 'granted') {
          // permissionData.deviceToken is now available to use.
          // send request to the NeuCurrent method for token registartion according to NeuCurrent API Swagger UI. See example below
        }
      };
    </script>
    

    Request sending to the NeuCurrent API

    Please, notice that in the code you should send a HTTP request to NeuCurrent API with a received device token. See example below:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    else if (permissionData.permission === 'granted') {
      let credentials = {
        username: '<>',
        password: '<>'
      };  // request credentials from the NeuCurrent Team
    
      fetch('https://app.neucurrent.com/push/api/v1/oauth/rotate-token/', {
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify(credentials)
      })
        .then(async response => {
          let {access_token, access_token_type} = await response.json();
          let body = {
            "device_data": {
              "device_token": permissionData.deviceToken,
              "platform": "WEB",
              "event_name": "device_token_event",
              "device_id": gaData.clientId
            },
            "client_keys": {
              "device_id": gaData.clientId,
              "client_id": gaData.clientId,
              "email": "<USER_EMAIL_IF_EXISTS>",
              "phone": "<USER_PHONE_IF_EXISTS>",
              "loyalty_card_number": "<LOYALTY_CARD_NUMBER_IF_EXISTS>"
            }
          };
    
          fetch('https://app.neucurrent.com/push/api/v1/device-token/add/', {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json',
              Authorization: `${access_token_type} ${access_token}`
            },
            body: JSON.stringify(body)
          })
            .catch(err => {
              console.error(err)
            })
        })
    }
    
  3. Full example:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    <script>
      const googleAnalyticsData = () => {
        const data = {};
        gtag('get', '<YOUR_GTAG>', 'client_id', clientId => { data.clientId = clientId; })
        return data;
      };
    
      const requestPerm = () => {
        if ('safari' in window && 'pushNotification' in window.safari) {
          let permissionData = window.safari.pushNotification.permission('<WEBSITE_PUSH_ID>');
          checkRemotePermission(permissionData);
        }
      };
    
      let gaData = googleAnalyticsData();
    
      const checkRemotePermission = (permissionData) => {
        if (permissionData.permission === 'default') {
          window.safari.pushNotification.requestPermission(
            'https://app.neucurrent.com/push/api',
            '<WEBSITE_PUSH_ID>',
            {
              "retailer_name": "<RETAILER_NANE>",
              "website_name": "<WEBSITE_TITLE>",
              "allowed_domains": '["https://app.neucurrent.com"]',
              "url_format_string": "https://app.neucurrent.com/push/api/v2",
              "web_service_url": "https://app.neucurrent.com/push/api",
              "device_id": gaData.clientId
            },
            checkRemotePermission
          );
        } 
        else if (permissionData.permission === 'denied') {
          // The user said no.
          console.log('denied')
        }
        else if (permissionData.permission === 'granted') {
          let credentials = {
            username: '<>',
            password: '<>'
          };  // request credentials from the NeuCurrent Team
    
          fetch('https://app.neucurrent.com/push/api/v1/oauth/rotate-token/', {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify(credentials)
          })
            .then(async response => {
              let {access_token, access_token_type} = await response.json();
              let body = {
                "device_data": {
                  "device_token": permissionData.deviceToken,
                  "platform": "WEB",
                  "event_name": "device_token_event",
                  "device_id": gaData.clientId
                },
                "client_keys": {
                  "device_id": gaData.clientId,
                  "client_id": gaData.clientId,
                  "email": "<USER_EMAIL_IF_EXISTS>",
                  "phone": "<USER_PHONE_IF_EXISTS>",
                  "loyalty_card_number": "<LOYALTY_CARD_NUMBER_IF_EXISTS>"
                }
              };
    
              fetch('https://app.neucurrent.com/push/api/v1/device-token/add/', {
                method: 'POST',
                headers: {
                  'Content-Type': 'application/json',
                  Authorization: `${access_token_type} ${access_token}`
                },
                body: JSON.stringify(body)
              })
                .catch(err => {
                  console.error(err)
                })
            })
        }
      };
    </script>
    

  4. Congratulations! You've finished the integration process.

The NeuCurrent integration

Please, provide the *.p12 certificate, it's password, and iconset (icon_16x16.png, icon_16x16@2x.png, icon_32x32.png, icon_32x32@2x.png, icon_128x128.png, icon_128x128@2x.png) to the NeuCurrent Team.