Overview

     The Joshua Project API is a REST based API for retrieving data from the Joshua Project Initiative . If you are not familiar with the term REST, you can read more at Wikipedia . All requests for data from the API must contain a valid API Key, and must pass the data with the GET HTTP request method.

API Keys

     An API Key is a unique 12 character string that identifies your application as the source of every request. Here is a sample of an API key: 233f76f4c84e. Warning: This is not a valid key. You must request your own key to the API. API keys are free and you are allowed to have multiple of them. The only requirement is that you verify your email before you get access to your key. Before starting this tutorial, you will need to retrieve an API key . Here are the steps for retrieving the API Key:

  • Fill out and submit the form on this page (You must fill in all required fields)
  • Visit the email you provided. You should receive an email from the Joshua Project Intiative. (You may need to check your Spam folder)
  • Click the link in the email to retrieve your API Key

GET HTTP Request Method

     Each time you click on a link in your browser, you are sending a GET HTTP request method. There are several HTTP Request methods including POST, PUT, and DELETE, but GET is one of the most common HTTP request methods. GET HTTP requests pass the parameters through the URL string. You may be familiar with URLs like:

http://mysite.com/store_center.html?page=store&task=purchase

     Let us break this URL down. In this URL, you are requesting the http://mysite.com/ domain name, and you want to see the store_center.html file on that web server. We are also passing 2 parameters that follow the ?. The question mark tells the server that we want to send some parameters. Each parameter has a key and a value. Here are the parameters we are sending:

Parameters
Key Value
page store
task purchase

The & is required to seperate each parameter. That is pretty much all you will need to do to make a GET request. We will look at this in more depth below.

     For more information on the REST Architecture and the GET HTTP request method, check out this tutorial at NetTuts.

URL Structure

     Below is a typical request for data from the Joshua Project API. In this example, we will request the Joshua Project's unreached people group of the day for January 11th.

https://api.joshuaproject.net/v1/people_groups/daily_unreached.json?api_key=233f76f4c84e&month=01&day=11

     Here is a breakdown of the URL structure:

https://api.joshuaproject.net/[api_version_number]/[resource_path].[format]?api_key=[your_api_key]&[other_parameters]
URL Definitions
api_version_number The letter "v" followed by an integer indicating the version of the API you want to use. (Current version = v1)
resource_path The path to the data you want to retreived. You can see available resource paths in the documentation.
format The format of the server's response. (json or xml)
your_api_key The API Key your retrieved for your application.
other_parameters A series of parameters (key=value) used to filter your request. Each parameter needs to be seperated by an &.

Response

     Once you make a request, the server will send back a response in either JSON or XML based on the format you specified. Here is the JSON response for the request above:

[
    {
        "ROG3": "SF",
        "PeopleID3": 18995,
        "PeopNameInCountry": "Malay, Cape",
        "ROG2": "AFR",
        "Continent": "Africa",
        "RegionName": "Africa, East and Southern",
        "PeopleID1": 17,
        "AffinityBloc": "Malay Peoples",
        "PeopleID2": 215,
        "PeopleCluster": "Malay",
        "PeopNameAcrossCountries": "Malay, Cape",
        "Population": 324000,
        "ROL3": "afr",
        "PrimaryLanguageName": "Afrikaans",
        "BibleYear": "1933-2022",
        "NTYear": "1941-1980",
        "PortionsYear": "1893-1929",
        "JPScale": "1",
        "LeastReached": "Y",
        "JF": "Y",
        "AudioRecordings": "Y",
        "NTOnline": "AFRLPF",
        "RLG3": 6,
        "PrimaryReligion": "Islam",
        "LRofTheDayMonth": 11,
        "LRofTheDaySet": null,
        "LRofTheDayDay": 1,
        "PhotoAddress": "p18995.jpg",
        "PhotoCredits": "Anonymous",
        "PhotoCreditURL": null,
        "PhotoCreativeCommons": "N",
        "PhotoCopyright": "N",
        "PhotoPermission": "N",
        "CountOfCountries": 1,
        "Longitude": 21.61887,
        "Latitude": -30.62109,
        "Ctry": "South Africa",
        "PercentAdherents": 0.5,
        "PercentEvangelical": 0.2,
        "RegionCode": 7,
        "ROP3": 114855,
        "ISO3": "ZAF",
        "LocationInCountry": "Principally Pretoria and Bloemfontein. Cape Malays mainly in Cape Town; some in Johannesburg, Pretoria, Durban, and Port Elizabeth",
        "ROP1": "A008",
        "ROP2": "C0123",
        "Category": "3",
        "PrimaryLanguageDialect": null,
        "NumberLanguagesSpoken": 2,
        "OfficialLang": "English",
        "SpeakNationalLang": null,
        "BibleStatus": 5,
        "TranslationNeedQuestionable": null,
        "JPScalePC": "4",
        "JPScalePGAC": "1",
        "LeastReachedPC": "N",
        "LeastReachedPGAC": "Y",
        "GSEC": "",
        "RLG3PC": 6,
        "RLG3PGAC": 6,
        "PrimaryReligionPC": "Islam",
        "PrimaryReligionPGAC": "Islam",
        "RLG4": null,
        "ReligionSubdivision": null,
        "PCIslam": 99.5,
        "PCNonReligious": 0,
        "PCUnknown": 0,
        "SecurityLevel": 0,
        "LRTop100": "N",
        "ProfileTextExists": "Y",
        "CountOfProvinces": null,
        "IndigenousCode": "Y",
        "PercentChristianPC": "7.590",
        "PercentChristianPGAC": "0.500",
        "PercentEvangelicalPC": "3.677",
        "PercentEvangelicalPGAC": "0.200",
        "PCBuddhism": 0,
        "PCEthnicReligions": 0,
        "PCHinduism": 0,
        "PCOtherSmall": 0,
        "PopulationPGAC": 324000,
        "Frontier": "N",
        "MapAddress": "m18995_sf.png",
        "MapCreditURL": "https://www.cartomission.com",
        "MapCopyright": "N",
        "MapCredits": "Bryan Nicholson / cartoMission",
        "MapCCVersionText": "",
        "MapCCVersionURL": "",
        "PhotoCCVersionText": "",
        "PhotoCCVersionURL": "",
        "Window1040": "N",
        "PeopleGroupMapURL": "https://joshuaproject.net/assets/media/profiles/maps/m18995_sf.png",
        "PeopleGroupMapExpandedURL": "https://joshuaproject.net/assets/media/profiles/maps/m18995_sf.pdf",
        "PeopleGroupURL": "https://joshuaproject.net/people_groups/18995/SF",
        "PeopleGroupPhotoURL": "https://joshuaproject.net/assets/media/profiles/photos/p18995.jpg",
        "CountryURL": "https://joshuaproject.net/countries/SF",
        "JPScaleText": "Unreached",
        "JPScaleImageURL": "https://joshuaproject.net/images/scale1.jpg",
        "Summary": "Ancestors of the Cape Malay came as hired workers and slaves to serve the Dutch settlement, coming largely from Indonesia and Malaysia. Later, since Islam was introduced in Indonesia as a way of protest against the colonial powers, Islamic leaders from Indonesia were brought to the Cape for imprisonment. They taught their fellow countrymen a lot about Islam and helped to spread it at the Cape. The Cape Malay define themselves as Muslims. If a person comes to know Jesus, he is no longer considered to be a Cape Malay."
    }
]
                    

And here is the XML response:

<?xml version="1.0"?>
<api>
    <people_groups>
        <people_group>
            <ROG3>SF</ROG3>
            <PeopleID3>18995</PeopleID3>
            <PeopNameInCountry>Malay, Cape</PeopNameInCountry>
            <ROG2>AFR</ROG2>
            <Continent>Africa</Continent>
            <RegionName>Africa, East and Southern</RegionName>
            <PeopleID1>17</PeopleID1>
            <AffinityBloc>Malay Peoples</AffinityBloc>
            <PeopleID2>215</PeopleID2>
            <PeopleCluster>Malay</PeopleCluster>
            <PeopNameAcrossCountries>Malay, Cape</PeopNameAcrossCountries>
            <Population>324000</Population>
            <ROL3>afr</ROL3>
            <PrimaryLanguageName>Afrikaans</PrimaryLanguageName>
            <BibleYear>1933-2022</BibleYear>
            <NTYear>1941-1980</NTYear>
            <PortionsYear>1893-1929</PortionsYear>
            <JPScale>1</JPScale>
            <LeastReached>Y</LeastReached>
            <JF>Y</JF>
            <AudioRecordings>Y</AudioRecordings>
            <NTOnline>AFRLPF</NTOnline>
            <RLG3>6</RLG3>
            <PrimaryReligion>Islam</PrimaryReligion>
            <LRofTheDayMonth>11</LRofTheDayMonth>
            <LRofTheDaySet/>
            <LRofTheDayDay>1</LRofTheDayDay>
            <PhotoAddress>p18995.jpg</PhotoAddress>
            <PhotoCredits>Anonymous</PhotoCredits>
            <PhotoCreditURL/>
            <PhotoCreativeCommons>N</PhotoCreativeCommons>
            <PhotoCopyright>N</PhotoCopyright>
            <PhotoPermission>N</PhotoPermission>
            <CountOfCountries>1</CountOfCountries>
            <Longitude>21.61887</Longitude>
            <Latitude>-30.62109</Latitude>
            <Ctry>South Africa</Ctry>
            <PercentAdherents>0.5</PercentAdherents>
            <PercentEvangelical>0.2</PercentEvangelical>
            <RegionCode>7</RegionCode>
            <ROP3>114855</ROP3>
            <ISO3>ZAF</ISO3>
            <LocationInCountry>Principally Pretoria and Bloemfontein. Cape Malays mainly in Cape Town; some in Johannesburg, Pretoria, Durban, and Port Elizabeth</LocationInCountry>
            <ROP1>A008</ROP1>
            <ROP2>C0123</ROP2>
            <Category>3</Category>
            <PrimaryLanguageDialect/>
            <NumberLanguagesSpoken>2</NumberLanguagesSpoken>
            <OfficialLang>English</OfficialLang>
            <SpeakNationalLang/>
            <BibleStatus>5</BibleStatus>
            <TranslationNeedQuestionable/>
            <JPScalePC>4</JPScalePC>
            <JPScalePGAC>1</JPScalePGAC>
            <LeastReachedPC>N</LeastReachedPC>
            <LeastReachedPGAC>Y</LeastReachedPGAC>
            <GSEC/>
            <RLG3PC>6</RLG3PC>
            <RLG3PGAC>6</RLG3PGAC>
            <PrimaryReligionPC>Islam</PrimaryReligionPC>
            <PrimaryReligionPGAC>Islam</PrimaryReligionPGAC>
            <RLG4/>
            <ReligionSubdivision/>
            <PCIslam>99.5</PCIslam>
            <PCNonReligious>0</PCNonReligious>
            <PCUnknown>0</PCUnknown>
            <SecurityLevel>0</SecurityLevel>
            <LRTop100>N</LRTop100>
            <ProfileTextExists>Y</ProfileTextExists>
            <CountOfProvinces/>
            <IndigenousCode>Y</IndigenousCode>
            <PercentChristianPC>7.590</PercentChristianPC>
            <PercentChristianPGAC>0.500</PercentChristianPGAC>
            <PercentEvangelicalPC>3.677</PercentEvangelicalPC>
            <PercentEvangelicalPGAC>0.200</PercentEvangelicalPGAC>
            <PCBuddhism>0</PCBuddhism>
            <PCEthnicReligions>0</PCEthnicReligions>
            <PCHinduism>0</PCHinduism>
            <PCOtherSmall>0</PCOtherSmall>
            <PopulationPGAC>324000</PopulationPGAC>
            <Frontier>N</Frontier>
            <MapAddress>m18995_sf.png</MapAddress>
            <MapCreditURL>https://www.cartomission.com</MapCreditURL>
            <MapCopyright>N</MapCopyright>
            <MapCredits>Bryan Nicholson / cartoMission</MapCredits>
            <MapCCVersionText/>
            <MapCCVersionURL/>
            <PhotoCCVersionText/>
            <PhotoCCVersionURL/>
            <Window1040>N</Window1040>
            <PeopleGroupMapURL>https://joshuaproject.net/assets/media/profiles/maps/m18995_sf.png</PeopleGroupMapURL>
            <PeopleGroupMapExpandedURL>https://joshuaproject.net/assets/media/profiles/maps/m18995_sf.pdf</PeopleGroupMapExpandedURL>
            <PeopleGroupURL>https://joshuaproject.net/people_groups/18995/SF</PeopleGroupURL>
            <PeopleGroupPhotoURL>https://joshuaproject.net/assets/media/profiles/photos/p18995.jpg</PeopleGroupPhotoURL>
            <CountryURL>https://joshuaproject.net/countries/SF</CountryURL>
            <JPScaleText>Unreached</JPScaleText>
            <JPScaleImageURL>https://joshuaproject.net/images/scale1.jpg</JPScaleImageURL>
            <Summary>Ancestors of the Cape Malay came as hired workers and slaves to serve the Dutch settlement, coming largely from Indonesia and Malaysia. Later, since Islam was introduced in Indonesia as a way of * Connection #0 to host localhost left intact
protest against the colonial powers, Islamic leaders from Indonesia were brought to the Cape for imprisonment. They taught their fellow countrymen a lot about Islam and helped to spread it at the Cape. The Cape Malay define themselves as Muslims. If a person comes to know Jesus, he is no longer considered to be a Cape Malay.</Summary>
        </people_group>
    </people_groups>
</api>
                    

     Once you have a response, you can use and manipulate the provided data.

Getting Started (All Tutorials)

     In the following tutorials, we will walk through four different approaches for creating the Joshua Project's unreached people group of the day widget using the new API. These tutorials come in a variety of programming languages including Javascript using the JQuery library, PHP, Python and Ruby. Feel free and choose the programming language that you feel more comfortable programming in. Before starting this tutorial, you will need to retrieve an API key.

Starting Code

     We have created zip files containing the starting code for each programming language. You can download these files from the following links:

     After downloading and unzipping the directory, look for the styles.css file. This file offers the basic design for the widget. Here is a look at the code:

.upgotd {
    color: #000000;
    font-family: Arial, Helvetica, Verdana, sans-serif;
}
#jp_widget {
    background-color: #EEE;
    border: #CCCCCC 1px dashed;
    text-align: center;
    width: 215px;
    font-size:12px;
}
#jp_widget a {
    color: #000000 !important;
    text-decoration: none;
}
#jp_widget a:hover {
    color: #0000FF !important;
    text-decoration: none;
}
.upgotd-title, .upgotd-footer {
    padding: 3px;
    background-color: #BBDDFF;
}
.upgotd-title, .upgotd-title a {
    font-weight: bold; font-size:13px !important;
    margin-bottom: 5px;
}
.upgotd-image {
    text-align: center;
}
.upgotd-pray {
    font-style: italic;
    font-weight: normal;
    padding: 3px 0px;
    font-size: 12px;
}
.upgotd-people {
    font-weight: normal;
    font-size:12px !important;
    padding-bottom:4px;
}
.upgotd-people a {
    font-weight: bold;
}
.upgotd-table td {
    font-family: Tahoma, Verdana, Arial, Helvetica, sans-serif;
    font-size:11px;
    font-weight: normal;
    color: #000;
    line-height: 14px;
    text-align: left;
    border: 0px;
    background-color: #EEE;
    margin: 0px;
    padding: 0px 0px 0px 3px;
}
.upgotd-more, .upgotd-more a {
    font-size: 10px;
}
.upgotd-footer, .upgotd-footer a {
    font-weight: normal ;
    font-size: 11px;
    margin-top: 3px;
}
a#progress-scale-image img {
    border: none;
}
.hidden {
    display: none;
}
                    

     You will also find an index file. (The extension varies based on the programming language) This file offers the basic structure of the final widget. The code looks like this:

<!DOCTYPE html>
<html>
    <head>
        <title>Joshua Project</title>
        <link rel="stylesheet" type="text/css" href="css/styles.css">
    </head>
    <body>
        <div id="jp_widget">
            <div class="upgotd upgotd-title">
                <a href="https://joshuaproject.net/upgotdfeed.php" class="upgotd-link">
                Unreached of the Day
                </a>
            </div>
            <div class="upgotd-image">
                <a href="#" class="upgotd-link pg-link" id="people-group-image">
                </a>
            </div>
            <div class="upgotd upgotd-pray">Please pray for the ...</div>
            <div class="upgotd upgotd-people">
                <a href="#" class="upgotd-link pg-link pg-name"></a> of
                <a href="#" class="upgotd-link country-link country-name"></a>
            </div>
            <table align="center" class="upgotd-table" cellpadding="0" cellspacing="0">
                <tbody><tr>
                    <td width="65">Population:</td>
                    <td width="135" class="pg-population"></td>
                </tr>
                <tr>
                    <td>Language:</td>
                    <td class="pg-language"></td>
                </tr>
                <tr>
                    <td>Religion:</td>
                    <td class="pg-religion"></td>
                </tr>
                <tr>
                    <td>Evangelical:</td>
                    <td class="pg-evangelical"></td>
                </tr>
                <tr>
                    <td>Status:</td>
                    <td>
                        <a
                        href="https://joshuaproject.net/definitions.php?term=25"
                        class="upgotd-link pg-scale-text">
                        </a> (
                        <a
                        href="https://joshuaproject.net/global-progress-scale.php"
                        class="upgotd-link pg-scale">
                        </a> 
                        <a
                        href="https://joshuaproject.net/global-progress-scale.php"
                        class="upgotd-link"
                        id="progress-scale-image">
                        </a>
                        )
                    </td>
                </tr>
            </tbody></table>
            <div class="upgotd upgotd-footer">
            Add this daily global vision feature to <br>
            <a href="/upgotdfeed.php" class="upgotd-link">your website</a> or get it
            <a href="http://www.unreachedoftheday.org/unreached-email.php" class="upgotd-link">
            by email
            </a>.</div>
        </div>
    </body>
</html>
                    

     We will use this starting code to launch into developing a widget that pulls in the data from our API. To get started, please choose your preferred programming language to continue this tutorial:

     Before beginning this tutorial, you should have a good understanding of the Javascript programming language, and the JQuery library! You will also need to download the starting code.

The JQuery Library

     JQuery is a Javascript library designed to make scripting in Javascript much more enjoyable and faster. It helps speed up common tasks like traversing the DOM, animating and manipulating DOM elements, and running Ajax calls. In order to use the library, we need to include it in the head tag of our index.html file. So open the index.html file and add the following line between the tags <head></head>:

<script type="text/javascript" src="http://code.jquery.com/jquery-1.10.2.min.js"></script>

     We do not need to download the JQuery library, because we will just use the file on their hosted CDN.

Calling the API

     Before calling the API, we can use a common JQuery method .ready() (Jquery Docs) to check if the DOM has loaded before running our Ajax request. So in the <head></head> tag, after the declaring the JQuery library, we need to add the following code:

<script type="text/javascript">
    jQuery(document).ready(function($) {

    });
</script>
                    

     We should also declare two variables to hold the API's domain name, and your API key. Remember to add your API key!

<script type="text/javascript">
    var DOMAIN = 'https://api.joshuaproject.net';
    var API_KEY = "YOUR_API_KEY";
    jQuery(document).ready(function($) {

    });
</script>
                    

     We are now ready to make the API request using JQuery's .ajax() ( Jquery Docs ) method. If you are not familiar with Ajax, it is an acronym for Asynchronous Javascript and XML. Wikipedia states:

With Ajax, web applications can send data to, and retrieve data from, a server asynchronously (in the background) without interfering with the display and behavior of the existing page.

Wikipedia

     Here is the code to run the Ajax request after the DOM has loaded:

<script type="text/javascript">
    var DOMAIN = 'https://api.joshuaproject.net';
    var API_KEY = "YOUR_API_KEY";
    jQuery(document).ready(function($) {
        $.ajax({
            url: DOMAIN+'/v1/people_groups/daily_unreached.json',
            dataType: 'json',
            data: {api_key: API_KEY},
            type: 'GET'
        })
        .done(function(data) {
            /* Code in here runs when the request is completed */
        })
        .fail(function(jqXHR, textStatus, errorThrown) {
            /* Code in here runs when the request failed */
        });
    });
</script>
                    

     As you can see in the code above, we send the following settings to JQuery's .ajax() ( Jquery Docs ) method:

JQuery Ajax Settings
Setting Description
url https://api.joshuaproject.net/v1/people_groups/daily_unreached.json - The URL of the web page to request. (See the URL Structure section)
dataType json - The type of data returned from the web page
data {api_key: API_KEY} - The additional paramaters to pass the web page.
type GET - The HTTP Request Method

     When this request is completed, it will call the empty function we provided for JQuery's .done() callback ( Jquery Docs ). If the request fails, the empty function provided for the .fail() callback (Jquery Docs) is triggered.

Handling the Error

     Let us start with handling any errors. This will help us debug any problems we may run into later. If the request for the web page is unsuccessful, it will trigger the .fail() callback ( Jquery Docs ). If this happens, we should let the visitor know. We will do this by appending an error message at the top of the page. Here is the updated code:

<script type="text/javascript">
    var DOMAIN = 'https://api.joshuaproject.net';
    var API_KEY = "YOUR_API_KEY";
    jQuery(document).ready(function($) {
        $.ajax({
            url: DOMAIN+'/v1/people_groups/daily_unreached.json',
            dataType: 'json',
            data: {api_key: API_KEY},
            type: 'GET'
        })
        .done(function(data) {
            /* Code in here runs when the request is completed */
        })
        .fail(function(jqXHR, textStatus, errorThrown) {
            var pTagSettings = {'color': 'red', 'font-weight': 'bold'};
            var pTag = $('<p/>').text('There was an error: '+errorThrown).css(pTagSettings);
            $('body').prepend(pTag);
        });
    });
</script>
                    

     We start by declaring CSS styles (Red & Bold) for the <p></p> tag that will hold the message:

var pTagSettings = {'color': 'red', 'font-weight': 'bold'};

     We then create the <p></p> tag, add the warning message using JQuery's .text() method ( JQuery Docs ), and add the CSS styles using JQuery's .css() method ( JQuery Docs ):

var pTag = $('<p/>').text('There was an error: '+errorThrown).css(pTagSettings);

     We finally prepend the new <p></p> tag to the body of the web page using JQuery's .prepend() method ( JQuery Docs ).

$('body').prepend(pTag);

     That is all we need to do to warn the user when the Ajax fails.

Creating the Widget

     Now that we have handled the errors, let us deal with the response sent back from the API. When the Ajax has successfully received a response from the API, it triggers JQuery's .done() callback ( Jquery Docs ). One of the parameters passed to our empty function is data. This is the API's response. As you remember, we asked the server for JSON. So now we need to handle that JSON response. This code is temporary, but it will help us understand what we are receiving from the API. In the .done() callback ( Jquery Docs ) we will prepend the data to the body of our HTML similar to the .fail() callback ( Jquery Docs ). Here is the code:

<script type="text/javascript">
    var DOMAIN = 'https://api.joshuaproject.net';
    var API_KEY = "YOUR_API_KEY";
    jQuery(document).ready(function($) {
        $.ajax({
            url: DOMAIN+'/v1/people_groups/daily_unreached.json',
            dataType: 'json',
            data: {api_key: API_KEY},
            type: 'GET'
        })
        .done(function(data) {
            /* JSON.stringify is only supported in IE 8 > */
            $('body').prepend(JSON.stringify(data));
        })
        .fail(function(jqXHR, textStatus, errorThrown) {
            var pTagSettings = {'color': 'red', 'font-weight': 'bold'};
            var pTag = $('<p/>').text('There was an error: '+errorThrown).css(pTagSettings);
            $('body').prepend(pTag);
        });
    });
</script>
                    

     When you save and run this code, you will see something similar to the response code we showed up above. If you do not get a response, then you need to check if you created your URL structure correctly. As you can see in the response, we are receiving a Javascript Array of a single JSON object. So to get the first JSON object, we simply set a variable to the first object of the array (data[0]) like this:

<script type="text/javascript">
    var DOMAIN = 'https://api.joshuaproject.net';
    var API_KEY = "YOUR_API_KEY";
    jQuery(document).ready(function($) {
        $.ajax({
            url: DOMAIN+'/v1/people_groups/daily_unreached.json',
            dataType: 'json',
            data: {api_key: API_KEY},
            type: 'GET'
        })
        .done(function(data) {
            var unreached = data[0];
        })
        .fail(function(jqXHR, textStatus, errorThrown) {
            var pTagSettings = {'color': 'red', 'font-weight': 'bold'};
            var pTag = $('<p/>').text('There was an error: '+errorThrown).css(pTagSettings);
            $('body').prepend(pTag);
        });
    });
</script>
                    

     Now we can access any of the supplied attributes of that JSON object using it's key. So if we want to get the people group's name, we can access it like this: unreached['PeopNameInCountry']. Now that we can access the data, we just need to start putting the data into the HTML we already provided. If you look at the HTML of the index.html file you have been working on, you will see the following code:

<div id="jp_widget">
    <div class="upgotd upgotd-title">
        <a href="https://joshuaproject.net/upgotdfeed.php" class="upgotd-link">Unreached of the Day</a>
    </div>
    <div class="upgotd-image">
        <a href="#" class="upgotd-link pg-link" id="people-group-image">
        </a>
    </div>
    <div class="upgotd upgotd-pray">Please pray for the ...</div>
    <div class="upgotd upgotd-people">
        <a href="#" class="upgotd-link pg-link pg-name"></a>
         of <a href="#" class="upgotd-link country-link country-name"></a>
    </div>
    <table align="center" class="upgotd-table" cellpadding="0" cellspacing="0">
        <tbody><tr>
            <td width="65">Population:</td>
            <td width="135" class="pg-population"></td>
        </tr>
        <tr>
            <td>Language:</td>
            <td class="pg-language"></td>
        </tr>
        <tr>
            <td>Religion:</td>
            <td class="pg-religion"></td>
        </tr>
        <tr>
            <td>Evangelical:</td>
            <td class="pg-evangelical"></td>
        </tr>
        <tr>
            <td>Status:</td>
            <td>
                <a
                href="https://joshuaproject.net/definitions.php?term=25"
                class="upgotd-link pg-scale-text">
                </a>
                (<a
                href="https://joshuaproject.net/global-progress-scale.php"
                class="upgotd-link pg-scale">
                </a>
                 <a
                href="https://joshuaproject.net/global-progress-scale.php"
                class="upgotd-link"
                id="progress-scale-image"></a>)
            </td>
        </tr>
    </tbody></table>
    <div class="upgotd upgotd-footer">Add this daily global vision feature to <br>
    <a href="/upgotdfeed.php" class="upgotd-link">your website</a>
    or get it <a
    href="http://www.unreachedoftheday.org/unreached-email.php"
    class="upgotd-link">by email</a>.</div>
</div>
                    

     As you look through that code, you will see unique classes and ids set to different elements. We will use these classes/ids to let Javascript manipulate it and add the appropriate content from the API. Here is a list of all the classes/ids, and how we will manipulate those elements to show people group data:

Widget Classes
ID/Class Data Accessible With Changes
class country‑link unreached['CountryURL'] We will set the link's href to the Joshua Project's people group's country URL
class country‑name unreached['Ctry'] We will set the text to the people group's country name
id people‑group‑image unreached['PeopleGroupPhotoURL'] We will create an image with a src equal to the location of the people group's image. We will also set it's dimensions to 128 X 160
class pg‑evangelical unreached['PercentEvangelical'] We will set a percentage formatted number totaling the people group's percentage of Evangelicals
class pg‑language unreached['PrimaryLanguageName'] We will set the text to the people group's primary language
class pg‑link unreached['PeopleGroupURL'] We will set the link's href to the Joshua Project's people group's URL
class pg‑name unreached['PeopNameInCountry'] We will set the text to the people group name
class pg‑population unreached['Population'] We will set a comma formatted number totaling the people group's population
class pg‑religion unreached['PrimaryReligion'] We will set the text to the people group's primary religion
class pg‑scale unreached['JPScale'] We will set the text to the people group's progress scale number
id  progress‑scale‑image unreached['JPScaleImageURL'] We will create an image with a src equal to the progress scale image for the people group
class pg‑scale‑text unreached['JPScaleText'] We will set the text to the people group's progress scale text

     So let us begin by completing all the tasks that say "We will set the text to...". This is easy to accomplish by using JQuery's .text() method. (JQuery Docs) Here is the code:

<script type="text/javascript">
    var DOMAIN = 'https://api.joshuaproject.net';
    var API_KEY = "YOUR_API_KEY";
    jQuery(document).ready(function($) {
        $.ajax({
            url: DOMAIN+'/v1/people_groups/daily_unreached.json',
            dataType: 'json',
            data: {api_key: API_KEY},
            type: 'GET'
        })
        .done(function(data) {
            var unreached = data[0];
            /* Set the text of each class to the appropriate data */
            $('.country-name').text(unreached['Ctry']);
            $('.pg-language').text(unreached['PrimaryLanguageName']);
            $('.pg-name').text(unreached['PeopNameInCountry']);
            $('.pg-religion').text(unreached['PrimaryReligion']);
            $('.pg-scale').text(unreached['JPScale']);
            $('.pg-scale-text').text(unreached['JPScaleText']);
        })
        .fail(function(jqXHR, textStatus, errorThrown) {
            var pTagSettings = {'color': 'red', 'font-weight': 'bold'};
            var pTag = $('<p/>').text('There was an error: '+errorThrown).css(pTagSettings);
            $('body').prepend(pTag);
        });
    });
</script>
                    

     If you refresh the webpage, you should see something like this with different data:

Snapshot Adding text() method

     Mine looks different! If you do not supply a month or day parameter, the API will return today's unreached people group of the day by default. Most likely you are not doing this tutorial the same day as I was. This now leaves us with the following tasks:

Widget Classes
ID/Class Data Accessible With Changes
class country‑link unreached['CountryURL'] We will set the link's href to the Joshua Project's people group's country URL
id people‑group‑image unreached['PeopleGroupPhotoURL'] We will create an image with a src equal to the location of the people group's image. We will also set it's dimensions to 128 X 160
class pg‑evangelical unreached['PercentEvangelical'] We will set a percentage formatted number totaling the people group's percentage of Evangelicals
class pg‑link unreached['PeopleGroupURL'] We will set the link's href to the Joshua Project's people group's URL
class pg‑population unreached['Population'] We will set a comma formatted number totaling the people group's population
id  progress‑scale‑image unreached['JPScaleImageURL'] We will create an image with a src equal to the progress scale image for the people group

     Let us now handle the two links that need URLS (.country-link, and .pg-link). We will use JQuery's .attr() method (JQuery Docs) to handle it. Here is the code:

<script type="text/javascript">
    var DOMAIN = 'https://api.joshuaproject.net';
    var API_KEY = "YOUR_API_KEY";
    jQuery(document).ready(function($) {
        $.ajax({
            url: DOMAIN+'/v1/people_groups/daily_unreached.json',
            dataType: 'json',
            data: {api_key: API_KEY},
            type: 'GET'
        })
        .done(function(data) {
            var unreached = data[0];
            /* Set the text of each class to the appropriate data */
            $('.country-name').text(unreached['Ctry']);
            $('.pg-language').text(unreached['PrimaryLanguageName']);
            $('.pg-name').text(unreached['PeopNameInCountry']);
            $('.pg-religion').text(unreached['PrimaryReligion']);
            $('.pg-scale').text(unreached['JPScale']);
            $('.pg-scale-text').text(unreached['JPScaleText']);
            /* Handle the two links that need URL's*/
            $('.country-link').attr('href', unreached['CountryURL']);
            $('.pg-link').attr('href', unreached['PeopleGroupURL']);
        })
        .fail(function(jqXHR, textStatus, errorThrown) {
            var pTagSettings = {'color': 'red', 'font-weight': 'bold'};
            var pTag = $('<p/>').text('There was an error: '+errorThrown).css(pTagSettings);
            $('body').prepend(pTag);
        });
    });
</script>
                    

     If you refresh the page, you may not see a difference. Just hover your mouse over either the people group name or country name and verify the URL is set. So here is what is remaining:

Widget Classes
ID/Class Data Accessible With Changes
id people‑group‑image unreached['PeopleGroupPhotoURL'] We will create an image with a src equal to the location of the people group's image. We will also set it's dimensions to 128 X 160
class pg‑evangelical unreached['PercentEvangelical'] We will set a percentage formatted number totaling the people group's percentage of Evangelicals
class pg‑population unreached['Population'] We will set a comma formatted number totaling the people group's population
id  progress‑scale‑image unreached['JPScaleImageURL'] We will create an image with a src equal to the progress scale image for the people group

     OK, we are getting close. Let us now tackle the two images. We will create an <img> tag similar to how we created the <p></p> tag in the .fail() callback ( Jquery Docs). We will use JQuery's .attr() method ( JQuery Docs) to set the src attribute, and JQuery's .css() method ( JQuery Docs) to add width and height. Finally, we will append the image to the element using JQuery's .append() method (JQuery Docs). Here is the code:

<script type="text/javascript">
    var DOMAIN = 'https://api.joshuaproject.net';
    var API_KEY = "YOUR_API_KEY";
    jQuery(document).ready(function($) {
        $.ajax({
            url: DOMAIN+'/v1/people_groups/daily_unreached.json',
            dataType: 'json',
            data: {api_key: API_KEY},
            type: 'GET'
        })
        .done(function(data) {
            var unreached = data[0];
            /* Set the text of each class to the appropriate data */
            $('.country-name').text(unreached['Ctry']);
            $('.pg-language').text(unreached['PrimaryLanguageName']);
            $('.pg-name').text(unreached['PeopNameInCountry']);
            $('.pg-religion').text(unreached['PrimaryReligion']);
            $('.pg-scale').text(unreached['JPScale']);
            $('.pg-scale-text').text(unreached['JPScaleText']);
            /* Handle the two links that need URL's*/
            $('.country-link').attr('href', unreached['CountryURL']);
            $('.pg-link').attr('href', unreached['PeopleGroupURL']);
            /* Append the images */
            var pgSettings = {'height': '160px', 'width': '128px'};
            var pgImg = $('<img/>').attr('src', unreached['PeopleGroupPhotoURL']).css(pgSettings);
            $('#people-group-image').append(pgImg);
            var scaleImg = $('<img/>').attr('src', unreached['JPScaleImageURL']);
            $('#progress-scale-image').append(scaleImg);
        })
        .fail(function(jqXHR, textStatus, errorThrown) {
            var pTagSettings = {'color': 'red', 'font-weight': 'bold'};
            var pTag = $('<p/>').text('There was an error: '+errorThrown).css(pTagSettings);
            $('body').prepend(pTag);
        });
    });
</script>
                    

     If you refresh the page in your browser, you should see something like this:

Snapshot of the images

     So here is what is remaining:

Widget Classes
ID/Class Data Accessible With Changes
class pg‑evangelical unreached['PercentEvangelical'] We will set a percentage formatted number totaling the people group's percentage of Evangelicals
class pg‑population unreached['Population'] We will set a comma formatted number totaling the people group's population

     So let's tackle the percentage of Evangelicals in the people group. We first need to check if it is set to null, if so then we will display 0.00. If not null, we will use Javascript's parseFloat() method ( Docs) to turn the number to a float. After that we format it to 2 decimals using Javascripts toFixed() method ( Docs). Finally, we will use JQuery's .text() method ( JQuery Docs) to set the text for the element. Here is the code:

<script type="text/javascript">
    var DOMAIN = 'https://api.joshuaproject.net';
    var API_KEY = "YOUR_API_KEY";
    jQuery(document).ready(function($) {
        $.ajax({
            url: DOMAIN+'/v1/people_groups/daily_unreached.json',
            dataType: 'json',
            data: {api_key: API_KEY},
            type: 'GET'
        })
        .done(function(data) {
            var unreached = data[0];
            /* Set the text of each class to the appropriate data */
            $('.country-name').text(unreached['Ctry']);
            $('.pg-language').text(unreached['PrimaryLanguageName']);
            $('.pg-name').text(unreached['PeopNameInCountry']);
            $('.pg-religion').text(unreached['PrimaryReligion']);
            $('.pg-scale').text(unreached['JPScale']);
            $('.pg-scale-text').text(unreached['JPScaleText']);
            /* Handle the two links that need URL's*/
            $('.country-link').attr('href', unreached['CountryURL']);
            $('.pg-link').attr('href', unreached['PeopleGroupURL']);
            /* Append the images */
            var pgSettings = {'height': '160px', 'width': '128px'};
            var pgImg = $('<img/>').attr('src', unreached['PeopleGroupPhotoURL']).css(pgSettings);
            $('#people-group-image').append(pgImg);
            var scaleImg = $('<img/>').attr('src', unreached['JPScaleImageURL']);
            $('#progress-scale-image').append(scaleImg);
            /* Set the Percent Evangelical */
            if (unreached['PercentEvangelical'] == null) {
                percent_evangelical = '0.00';
            } else {
                percent_evangelical = parseFloat(unreached['PercentEvangelical']).toFixed(2);
            };
            $('.pg-evangelical').text(percent_evangelical+'%');
        })
        .fail(function(jqXHR, textStatus, errorThrown) {
            var pTagSettings = {'color': 'red', 'font-weight': 'bold'};
            var pTag = $('<p/>').text('There was an error: '+errorThrown).css(pTagSettings);
            $('body').prepend(pTag);
        });
    });
</script>
                    

     Once you reload the web page, you should now see the percentage like this:

Percent Evangelical

     So we only have one item remaining:

Widget Classes
ID/Class Data Accessible With Changes
class pg‑population unreached['Population'] We will set a comma formatted number totaling the people group's population

     First, we will need to create a custom function for formatting a comma seperated value. We will use Javascript's toString() method ( Docs) to make sure the value is a string. We then will use Regular Expressions to format it. Here is the code:

<script type="text/javascript">
    var DOMAIN = 'https://api.joshuaproject.net';
    var API_KEY = "YOUR_API_KEY";
    jQuery(document).ready(function($) {
        $.ajax({
            url: DOMAIN+'/v1/people_groups/daily_unreached.json',
            dataType: 'json',
            data: {api_key: API_KEY},
            type: 'GET'
        })
        .done(function(data) {
            var unreached = data[0];
            /* Set the text of each class to the appropriate data */
            $('.country-name').text(unreached['Ctry']);
            $('.pg-language').text(unreached['PrimaryLanguageName']);
            $('.pg-name').text(unreached['PeopNameInCountry']);
            $('.pg-religion').text(unreached['PrimaryReligion']);
            $('.pg-scale').text(unreached['JPScale']);
            $('.pg-scale-text').text(unreached['JPScaleText']);
            /* Handle the two links that need URL's*/
            $('.country-link').attr('href', unreached['CountryURL']);
            $('.pg-link').attr('href', unreached['PeopleGroupURL']);
            /* Append the images */
            var pgSettings = {'height': '160px', 'width': '128px'};
            var pgImg = $('<img/>').attr('src', unreached['PeopleGroupPhotoURL']).css(pgSettings);
            $('#people-group-image').append(pgImg);
            var scaleImg = $('<img/>').attr('src', unreached['JPScaleImageURL']);
            $('#progress-scale-image').append(scaleImg);
            /* Set the Percent Evangelical */
            if (unreached['PercentEvangelical'] == null) {
                percent_evangelical = '0.00';
            } else {
                percent_evangelical = parseFloat(unreached['PercentEvangelical']).toFixed(2);
            };
            $('.pg-evangelical').text(percent_evangelical+'%');
        })
        .fail(function(jqXHR, textStatus, errorThrown) {
            var pTagSettings = {'color': 'red', 'font-weight': 'bold'};
            var pTag = $('<p/>').text('There was an error: '+errorThrown).css(pTagSettings);
            $('body').prepend(pTag);
        });
    });
    /* Number formating method. */
    function numberWithCommas(x) {
        return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
    };
</script>
                    

     Finally we use JQuery's .text() method. ( JQuery Docs) to set the text of the element.

<script type="text/javascript">
    var DOMAIN = 'https://api.joshuaproject.net';
    var API_KEY = "YOUR_API_KEY";
    jQuery(document).ready(function($) {
        $.ajax({
            url: DOMAIN+'/v1/people_groups/daily_unreached.json',
            dataType: 'json',
            data: {api_key: API_KEY},
            type: 'GET'
        })
        .done(function(data) {
            var unreached = data[0];
            /* Set the text of each class to the appropriate data */
            $('.country-name').text(unreached['Ctry']);
            $('.pg-language').text(unreached['PrimaryLanguageName']);
            $('.pg-name').text(unreached['PeopNameInCountry']);
            $('.pg-religion').text(unreached['PrimaryReligion']);
            $('.pg-scale').text(unreached['JPScale']);
            $('.pg-scale-text').text(unreached['JPScaleText']);
            /* Handle the two links that need URL's*/
            $('.country-link').attr('href', unreached['CountryURL']);
            $('.pg-link').attr('href', unreached['PeopleGroupURL']);
            /* Append the images */
            var pgSettings = {'height': '160px', 'width': '128px'};
            var pgImg = $('<img/>').attr('src', unreached['PeopleGroupPhotoURL']).css(pgSettings);
            $('#people-group-image').append(pgImg);
            var scaleImg = $('<img/>').attr('src', unreached['JPScaleImageURL']);
            $('#progress-scale-image').append(scaleImg);
            /* Set the Percent Evangelical */
            if (unreached['PercentEvangelical'] == null) {
                percent_evangelical = '0.00';
            } else {
                percent_evangelical = parseFloat(unreached['PercentEvangelical']).toFixed(2);
            };
            $('.pg-evangelical').text(percent_evangelical+'%');
            /* Set the Population */
            $('.pg-population').text(numberWithCommas(unreached['Population']));
        })
        .fail(function(jqXHR, textStatus, errorThrown) {
            var pTagSettings = {'color': 'red', 'font-weight': 'bold'};
            var pTag = $('<p/>').text('There was an error: '+errorThrown).css(pTagSettings);
            $('body').prepend(pTag);
        });
    });
    /* Number formating method. */
    function numberWithCommas(x) {
        return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
    };
</script>
                    

     Here is the final result of our newly created widget:

Snapshot of Final Widget

Finishing Touches

     If you reload the web page, you will notice a delay before all the information is correctly displayed. Visitors may find this unappealing. So we will hide the widget, and display it when it is ready. First we need to add a hidden class to the widget. This class hides the widget from view. Here is the code:

<div id="jp_widget" class="hidden">
    <div class="upgotd upgotd-title">
        <a href="https://joshuaproject.net/upgotdfeed.php" class="upgotd-link">Unreached of the Day</a>
    </div>
    <div class="upgotd-image">
        <a href="#" class="upgotd-link pg-link" id="people-group-image">
        </a>
    </div>
    <div class="upgotd upgotd-pray">Please pray for the ...</div>
    <div class="upgotd upgotd-people">
        <a
        href="#"
        class="upgotd-link pg-link pg-name">
        </a> of
        <a
        href="#"
        class="upgotd-link country-link country-name">
        </a>
    </div>
    <table align="center" class="upgotd-table" cellpadding="0" cellspacing="0">
        <tbody><tr>
            <td width="65">Population:</td>
            <td width="135" class="pg-population"></td>
        </tr>
        <tr>
            <td>Language:</td>
            <td class="pg-language"></td>
        </tr>
        <tr>
            <td>Religion:</td>
            <td class="pg-religion"></td>
        </tr>
        <tr>
            <td>Evangelical:</td>
            <td class="pg-evangelical"></td>
        </tr>
        <tr>
            <td>Status:</td>
            <td>
                <a
                href="https://joshuaproject.net/definitions.php?term=25"
                class="upgotd-link pg-scale-text">
                </a> (
                <a
                href="https://joshuaproject.net/global-progress-scale.php"
                class="upgotd-link pg-scale">
                </a> 
                <a
                href="https://joshuaproject.net/global-progress-scale.php"
                class="upgotd-link"
                id="progress-scale-image">
                </a>)
            </td>
        </tr>
    </tbody></table>
    <div class="upgotd upgotd-footer">
    Add this daily global vision feature to <br>
    <a
    href="/upgotdfeed.php"
    class="upgotd-link">
    your website</a> or get it
    <a
    href="http://www.unreachedoftheday.org/unreached-email.php"
    class="upgotd-link">
    by email
    </a>.
    </div>
</div>
                    

     Then we will use JQuery's .fadeIn() method ( JQuery Docs) to fade in the widget when we finished setting it up.

<script type="text/javascript">
    var DOMAIN = 'https://api.joshuaproject.net';
    var API_KEY = "YOUR_API_KEY";
    jQuery(document).ready(function($) {
        $.ajax({
            url: DOMAIN+'/v1/people_groups/daily_unreached.json',
            dataType: 'json',
            data: {api_key: API_KEY},
            type: 'GET'
        })
        .done(function(data) {
            var unreached = data[0];
            /* Set the text of each class to the appropriate data */
            $('.country-name').text(unreached['Ctry']);
            $('.pg-language').text(unreached['PrimaryLanguageName']);
            $('.pg-name').text(unreached['PeopNameInCountry']);
            $('.pg-religion').text(unreached['PrimaryReligion']);
            $('.pg-scale').text(unreached['JPScale']);
            $('.pg-scale-text').text(unreached['JPScaleText']);
            /* Handle the two links that need URL's*/
            $('.country-link').attr('href', unreached['CountryURL']);
            $('.pg-link').attr('href', unreached['PeopleGroupURL']);
            /* Append the images */
            var pgSettings = {'height': '160px', 'width': '128px'};
            var pgImg = $('<img/>').attr('src', unreached['PeopleGroupPhotoURL']).css(pgSettings);
            $('#people-group-image').append(pgImg);
            var scaleImg = $('<img/>').attr('src', unreached['JPScaleImageURL']);
            $('#progress-scale-image').append(scaleImg);
            /* Set the Percent Evangelical */
            if (unreached['PercentEvangelical'] == null) {
                percent_evangelical = '0.00';
            } else {
                percent_evangelical = parseFloat(unreached['PercentEvangelical']).toFixed(2);
            };
            $('.pg-evangelical').text(percent_evangelical+'%');
            /* Set the Population */
            $('.pg-population').text(numberWithCommas(unreached['Population']));
            /* Fade in the widget */
            $('div#jp_widget').fadeIn('slow');
        })
        .fail(function(jqXHR, textStatus, errorThrown) {
            var pTagSettings = {'color': 'red', 'font-weight': 'bold'};
            var pTag = $('<p/>').text('There was an error: '+errorThrown).css(pTagSettings);
            $('body').prepend(pTag);
        });
    });
    /* Number formating method. */
    function numberWithCommas(x) {
        return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
    };
</script>
                    

     Congratulations! You have completed the Javascript tutorial. If you would like to download the sample code, you can visit our Github Account .

Setup

     Before you start this tutorial, you will need some understanding of the PHP programming language. You will also need a PHP environment setup on your local machine , or be able to upload your code to a PHP web server. This tutorial does not cover how to accomplish that. Once you have an environment setup, you will need to download the starting code.

Calling the API

     Open the index.php file in your favorite text editor. Let us start by creating 3 variables to hold the API domain, API key, and the URL to get the unreached of the day information. Remember to add your API key! Add the following code to the top of the index.php file:

<?php
$domain = "https://api.joshuaproject.net";
$api_key = "YOUR_API_KEY";
$url = $domain . "/v1/people_groups/daily_unreached.json?api_key=" . $api_key;
?>
                    

     To access an API with PHP, we need to use the cURL Library.

cURL is a computer software project providing a library and command-line tool for transferring data using various protocols.

Wikipedia

     PHP offers methods for making cURL requests in the code. Let us begin by opening a cURL connection using PHP's curl_init() function ( PHP DOCS).

<?php
$domain = "https://api.joshuaproject.net";
$api_key = "YOUR_API_KEY";
$url = $domain . "/v1/people_groups/daily_unreached.json?api_key=" . $api_key;
/**
 * open connection
 *
 * @author Johnathan Pulos
 */
$ch = curl_init();
?>
                    

     Next we need to set some options for the request using PHP's curl_setopt() function ( PHP DOCS).

<?php
$domain = "https://api.joshuaproject.net";
$api_key = "YOUR_API_KEY";
$url = $domain . "/v1/people_groups/daily_unreached.json?api_key=" . $api_key;
/**
 * open connection
 *
 * @author Johnathan Pulos
 */
$ch = curl_init();
/**
 * Setup cURL
 *
 * @author Johnathan Pulos
 */
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
?>
                    

     Here are the options that we set:

Option Description Value
CURLOPT_URL The URL to fetch https://api.joshuaproject.net/v1/people_groups/daily_unreached.json?api_key=YOUR_API_KEY
CURLOPT_RETURNTRANSFER Returns the response from CURL_EXEC as a string 1 (true)
CURLOPT_TIMEOUT The maximum number of seconds cURL should execute request 60 seconds
CURLOPT_CUSTOMREQUEST Set a custom HTTP request method GET

     Now we need to execute the cURL request using PHP's curl_exec() function ( PHP DOCS). If the request fails, we will call PHP's die() function ( PHP DOCS) to stop executing the script. If it is successful, we will assign the result to a variable so we can access the JSON response.

<?php
$domain = "https://api.joshuaproject.net";
$api_key = "YOUR_API_KEY";
$url = $domain . "/v1/people_groups/daily_unreached.json?api_key=" . $api_key;
/**
 * open connection
 *
 * @author Johnathan Pulos
 */
$ch = curl_init();
/**
 * Setup cURL
 *
 * @author Johnathan Pulos
 */
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
/**
 * execute request
 *
 * @author Johnathan Pulos
 */
$result = curl_exec($ch) or die(curl_error($ch));
?>
                    

     Now we need to clean up by closing the cURL request. We do this by using PHP's curl_close() function ( PHP DOCS).

<?php
$domain = "https://api.joshuaproject.net";
$api_key = "YOUR_API_KEY";
$url = $domain . "/v1/people_groups/daily_unreached.json?api_key=" . $api_key;
/**
 * open connection
 *
 * @author Johnathan Pulos
 */
$ch = curl_init();
/**
 * Setup cURL
 *
 * @author Johnathan Pulos
 */
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
/**
 * execute request
 *
 * @author Johnathan Pulos
 */
$result = curl_exec($ch) or die(curl_error($ch));
/**
 * close connection
 *
 * @author Johnathan Pulos
 */
curl_close($ch);
?>
                    

     We have now completed the request. Let's add some temporary code to verify we have the data. We will remove this code before moving forward.

<?php
$domain = "https://api.joshuaproject.net";
$api_key = "YOUR_API_KEY";
$url = $domain . "/v1/people_groups/daily_unreached.json?api_key=" . $api_key;
/**
 * open connection
 *
 * @author Johnathan Pulos
 */
$ch = curl_init();
/**
 * Setup cURL
 *
 * @author Johnathan Pulos
 */
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
/**
 * execute request
 *
 * @author Johnathan Pulos
 */
$result = curl_exec($ch) or die(curl_error($ch));
/**
 * close connection
 *
 * @author Johnathan Pulos
 */
curl_close($ch);
/**
 * TEMP: Print out the results
 *
 * @author Johnathan Pulos
 */
print_r($result);
exit();
?>
                    

     When you save and run this code, you will see something similar to the response code we showed up above. If you do not get a response, then you need to check if you created your URL structure correctly. As you can see in the response, we are receiving a PHP Array of a single JSON object. In order to use this JSON object in PHP, we need to convert it to a PHP multidimensional array. We can do this with a handy PHP function decoded_json() ( PHP DOCS)

<?php
$domain = "https://api.joshuaproject.net";
$api_key = "YOUR_API_KEY";
$url = $domain . "/v1/people_groups/daily_unreached.json?api_key=" . $api_key;
/**
 * open connection
 *
 * @author Johnathan Pulos
 */
$ch = curl_init();
/**
 * Setup cURL
 *
 * @author Johnathan Pulos
 */
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
/**
 * execute request
 *
 * @author Johnathan Pulos
 */
$result = curl_exec($ch) or die(curl_error($ch));
/**
 * close connection
 *
 * @author Johnathan Pulos
 */
curl_close($ch);
/**
 * decode the response JSON
 *
 * @author Johnathan Pulos
 */
$decoded_json = json_decode($result, true);
?>
                    

     We should also add error checking. If the multidimensional array is not an array, we will stop executing the code with a message. We will use PHP's is_array() function ( PHP Docs) to do the check.

<?php
$domain = "https://api.joshuaproject.net";
$api_key = "YOUR_API_KEY";
$url = $domain . "/v1/people_groups/daily_unreached.json?api_key=" . $api_key;
/**
 * open connection
 *
 * @author Johnathan Pulos
 */
$ch = curl_init();
/**
 * Setup cURL
 *
 * @author Johnathan Pulos
 */
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
/**
 * execute request
 *
 * @author Johnathan Pulos
 */
$result = curl_exec($ch) or die(curl_error($ch));
/**
 * close connection
 *
 * @author Johnathan Pulos
 */
curl_close($ch);
/**
 * decode the response JSON
 *
 * @author Johnathan Pulos
 */
$decoded_json = json_decode($result, true);
if (!is_array($decoded_json)) {
    echo "Unable to retrieve the JSON.";
    exit;
}
?>
                    

     Now that we created a multidimensional array, we can access the first object using its index like this: $decoded_json[0]. We will set this to a variable for easy access.

<?php
$domain = "https://api.joshuaproject.net";
$api_key = "YOUR_API_KEY";
$url = $domain . "/v1/people_groups/daily_unreached.json?api_key=" . $api_key;
/**
 * open connection
 *
 * @author Johnathan Pulos
 */
$ch = curl_init();
/**
 * Setup cURL
 *
 * @author Johnathan Pulos
 */
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
/**
 * execute request
 *
 * @author Johnathan Pulos
 */
$result = curl_exec($ch) or die(curl_error($ch));
/**
 * close connection
 *
 * @author Johnathan Pulos
 */
curl_close($ch);
/**
 * decode the response JSON
 *
 * @author Johnathan Pulos
 */
$decoded_json = json_decode($result, true);
if (!is_array($decoded_json)) {
    echo "Unable to retrieve the JSON.";
    exit;
}
/**
 * Assign the first object to a variable
 *
 * @author Johnathan Pulos
 */
$unreached = $decoded_json[0];
?>
                    

Creating the Widget

     Now we can access any of the supplied attributes of that JSON object using it's key. So if we want to get the people group's name, we can access it like this: $unreached['PeopNameInCountry'].

     There are a few attributes that need to be formatted correctly. The attribute percentage of Evangelicals in the people group can be set to null, if so then we should display 0.00. So let's add a check to evaluate the value, and set it to 0 if it is null. Here is the code:

<?php
$domain = "https://api.joshuaproject.net";
$api_key = "YOUR_API_KEY";
$url = $domain . "/v1/people_groups/daily_unreached.json?api_key=" . $api_key;
/**
 * open connection
 *
 * @author Johnathan Pulos
 */
$ch = curl_init();
/**
 * Setup cURL
 *
 * @author Johnathan Pulos
 */
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
/**
 * execute request
 *
 * @author Johnathan Pulos
 */
$result = curl_exec($ch) or die(curl_error($ch));
/**
 * close connection
 *
 * @author Johnathan Pulos
 */
curl_close($ch);
/**
 * decode the response JSON
 *
 * @author Johnathan Pulos
 */
$decoded_json = json_decode($result, true);
if (!is_array($decoded_json)) {
    echo "Unable to retrieve the JSON.";
    exit;
}
/**
 * Assign the first object to a variable
 *
 * @author Johnathan Pulos
 */
$unreached = $decoded_json[0];
/**
 * Handle the null value
 *
 * @author Johnathan Pulos
 */
if ($unreached['PercentEvangelical'] == null) {
    $unreached['PercentEvangelical'] = 0;
}
?>
                    

     Now we just need to add the data to the HTML widget code for displaying. We will use PHP's echo() function ( PHP DOCS) to display the data in the appropriate place. We will also use PHP's number_format() function ( PHP DOCS) to format the people group's population, and percent of Evangelicals. In the HTML portion of the index.php file, update the code to what is below:

<div id="jp_widget">
    <div class="upgotd upgotd-title">
        <a href="https://joshuaproject.net/upgotdfeed.php" class="upgotd-link">Unreached of the Day</a>
    </div>
    <div class="upgotd-image">
        <a href="
        <?php echo $unreached['PeopleGroupURL']; ?>
        " class="upgotd-link pg-link" id="people-group-image">
            <img src="
                <?php echo $unreached['PeopleGroupPhotoURL']; ?>
                " height="160" width="128" alt="Unreached of the Day Photo">
        </a>
    </div>
    <div class="upgotd upgotd-pray">Please pray for the ...</div>
    <div class="upgotd upgotd-people">
        <a href="<?php echo $unreached['PeopleGroupURL']; ?>"
        class="upgotd-link pg-link pg-name">
        <?php echo $unreached['PeopNameInCountry']; ?>
        </a> of
        <a href="<?php echo $unreached['CountryURL']; ?>"
        class="upgotd-link country-link country-name">
        <?php echo $unreached['Ctry']; ?>
        </a>
    </div>
    <table align="center" class="upgotd-table" cellpadding="0" cellspacing="0">
        <tbody>
        <tr>
            <td width="65">
                Population:
            </td>
            <td width="135" class="pg-population">
                <?php echo number_format($unreached['Population']); ?>
            </td>
        </tr>
        <tr>
            <td>
                Language:
            </td>
            <td class="pg-language">
                <?php echo $unreached['PrimaryLanguageName']; ?>
            </td>
        </tr>
        <tr>
            <td>
                Religion:
            </td>
            <td class="pg-religion">
                <?php echo $unreached['PrimaryReligion']; ?>
            </td>
        </tr>
        <tr>
            <td>
                Evangelical:
            </td>
            <td class="pg-evangelical">
            <?php echo number_format($unreached['PercentEvangelical'], 2); ?>%
            </td>
        </tr>
        <tr>
            <td>Status:</td>
            <td>
                <a href="https://joshuaproject.net/definitions.php?term=25" class="upgotd-link pg-scale-text">
                    <?php echo $unreached['JPScaleText']; ?>
                </a> (
                <a href="https://joshuaproject.net/global-progress-scale.php" class="upgotd-link pg-scale">
                    <?php echo $unreached['JPScale']; ?>
                </a>
                <a
                href="https://joshuaproject.net/global-progress-scale.php"
                class="upgotd-link"
                id="progress-scale-image">
                <img
                    src="<?php echo $unreached['JPScaleImageURL']; ?>"
                    alt="Progress Scale">
                </a>)
            </td>
        </tr>
    </tbody></table>
    <div class="upgotd upgotd-footer">
        Add this daily global vision feature to <br>
        <a href="/upgotdfeed.php" class="upgotd-link">your website</a> or get it
        <a href="http://www.unreachedoftheday.org/unreached-email.php" class="upgotd-link">by email</a>.
    </div>
</div>
                    

     If you reload the webpage, you should see the widget with all the API data. Your data might be different.

Snapshot of Final Widget

     Mine looks different! If you do not supply a month or day parameter, the API will return today's unreached people group of the day by default. Most likely you are not doing this tutorial the same day as I was.

     Congratulations! You have completed the PHP tutorial. If you would like to download the sample code, you can visit our Github Account.

Setup

     Before starting this tutorial, you will need to have some understanding of the Python programming language. We will be using Python version 3.3. You will also need Python running in your command line utility. This tutorial does not show how to install Python.

     In this tutorial, we will build a generator that creates the necessary HTML & CSS for the widget. Everytime you run the script from the command line, it will create the widget with the latest people group data. Once you have downloaded and unzipped the Python starting code, open it up and look around. Here is the basic code structure:

  • css - directory for CSS Stylesheets
    • styles.css - the basic styles for the widget
  • generated_code - directory for the code created by our generator
  • templates - directory for the HTML templates
    • index.html - the HTML template for the widget
  • generate_widget.py - the generator script we will build

     Go ahead and open the generate_widget.py file in your favorite text editor. We will begin by including several Python modules using the import statement ( Python Docs). We will need the following modules: json ( Python Docs), urllib.request ( Python Docs), urllib.error ( Python Docs), string ( Python Docs), and sys (Python Docs). The code looks like this:

#!/usr/bin/python
# import the necessary libraries
import json
import urllib.request
import urllib.error
import string
import sys
                    

Calling the API

     Now that we have imported the necessary modules, we will need to generate the API request. We will start by creating 3 variables for the API domain, API key, and the API URL for the request. Remember to add your API key! Here is the code:

#!/usr/bin/python
# import the necessary libraries
import json
import urllib.request
import urllib.error
import string
import sys
# set some important variables
domain = "https://api.joshuaproject.net"
api_key = "YOUR_API_KEY"
url = domain+"/v1/people_groups/daily_unreached.json?api_key="+api_key
                    

     We will call the API within a try...except block. ( Python Docs) Using Python's urllib.error module ( Python Docs ), we will be warned if the API request returns aHTTPError or URLError. Here is the block:

#!/usr/bin/python
# import the necessary libraries
import json
import urllib.request
import urllib.error
import string
import sys
# set some important variables
domain = "https://api.joshuaproject.net"
api_key = "YOUR_API_KEY"
url = domain+"/v1/people_groups/daily_unreached.json?api_key="+api_key
try:
    # request the API for the Daily Unreached People Group
except urllib.error.HTTPError as e:
    print('The server couldn\'t fulfill the request.')
    print('Error code: ', e.code)
    exit
except urllib.error.URLError as e:
    print('We failed to reach a server.')
    print('Reason: ', e.reason)
    exit
else:
    # Everything worked
                    

     Now if there is a HTTPError or URLError, we will be able to see what happened. Now we need to make the request using the urllib.request module ( Python Docs) by calling the urlopen() function ( Python Docs). Here is the code:

#!/usr/bin/python
# import the necessary libraries
import json
import urllib.request
import urllib.error
import string
import sys
# set some important variables
domain = "https://api.joshuaproject.net"
api_key = "YOUR_API_KEY"
url = domain+"/v1/people_groups/daily_unreached.json?api_key="+api_key
try:
    # request the API for the Daily Unreached People Group
    request = urllib.request.urlopen(api_url)
except urllib.error.HTTPError as e:
    print('The server couldn\'t fulfill the request.')
    print('Error code: ', e.code)
    exit
except urllib.error.URLError as e:
    print('We failed to reach a server.')
    print('Reason: ', e.reason)
    exit
else:
    # Everything worked
                    

     If everything is done correctly, we should be able to run the code from your command line utility, and see no errors. Let's add some temporary code to see if we got a response. Add the following code:

#!/usr/bin/python
# import the necessary libraries
import json
import urllib.request
import urllib.error
import string
import sys
# set some important variables
domain = "https://api.joshuaproject.net"
api_key = "YOUR_API_KEY"
url = domain+"/v1/people_groups/daily_unreached.json?api_key="+api_key
try:
    # request the API for the Daily Unreached People Group
    request = urllib.request.urlopen(api_url)
except urllib.error.HTTPError as e:
    print('The server couldn\'t fulfill the request.')
    print('Error code: ', e.code)
    exit
except urllib.error.URLError as e:
    print('We failed to reach a server.')
    print('Reason: ', e.reason)
    exit
else:
    # Everything worked
    response = request.read()
    print(response)
                    

     If everything went according to plan, you should see something similar to the API response shown above. Using the response of the request, which is set to the request variable, we need to use the .read() function of the urllib.request module ( Python Docs). We will also need to use the decode() function of the module to decode it to UTF-8. Here is how it should be written:

#!/usr/bin/python
# import the necessary libraries
import json
import urllib.request
import urllib.error
import string
import sys
# set some important variables
domain = "https://api.joshuaproject.net"
api_key = "YOUR_API_KEY"
url = domain+"/v1/people_groups/daily_unreached.json?api_key="+api_key
try:
    # request the API for the Daily Unreached People Group
    request = urllib.request.urlopen(api_url)
except urllib.error.HTTPError as e:
    print('The server couldn\'t fulfill the request.')
    print('Error code: ', e.code)
    exit
except urllib.error.URLError as e:
    print('We failed to reach a server.')
    print('Reason: ', e.reason)
    exit
else:
    # Everything worked
    # decode the response
    response = request.read().decode("utf8")
                    

     Next we need to convert the JSON to a Python object using the json module's (Python Docs ) loads() function ( Python Docs ). We will also print out the result temporarily so we can look at it. Here is how you will accomplish this:

#!/usr/bin/python
# import the necessary libraries
import json
import urllib.request
import urllib.error
import string
import sys
# set some important variables
domain = "https://api.joshuaproject.net"
api_key = "YOUR_API_KEY"
url = domain+"/v1/people_groups/daily_unreached.json?api_key="+api_key
try:
    # request the API for the Daily Unreached People Group
    request = urllib.request.urlopen(api_url)
except urllib.error.HTTPError as e:
    print('The server couldn\'t fulfill the request.')
    print('Error code: ', e.code)
    exit
except urllib.error.URLError as e:
    print('We failed to reach a server.')
    print('Reason: ', e.reason)
    exit
else:
    # Everything worked
    # decode the response
    response = request.read().decode("utf8")
    # load the JSON
    data = json.loads(response)
    print(data)
                    

     If you look at the response, you can see that we have a Python list ( Python Docs) containing a single Python dict ( Python Docs). To access the first dict, we can refer to it using the index of 0 similar to data[0]. So let's set a variable to the first dict:

#!/usr/bin/python
# import the necessary libraries
import json
import urllib.request
import urllib.error
import string
import sys
# set some important variables
domain = "https://api.joshuaproject.net"
api_key = "YOUR_API_KEY"
url = domain+"/v1/people_groups/daily_unreached.json?api_key="+api_key
try:
    # request the API for the Daily Unreached People Group
    request = urllib.request.urlopen(api_url)
except urllib.error.HTTPError as e:
    print('The server couldn\'t fulfill the request.')
    print('Error code: ', e.code)
    exit
except urllib.error.URLError as e:
    print('We failed to reach a server.')
    print('Reason: ', e.reason)
    exit
else:
    # Everything worked
    # decode the response
    response = request.read().decode("utf8")
    # load the JSON
    data = json.loads(response)
    unreached = data[0]
                    

Creating the Widget

     Now we can access any of the supplied attributes of that dict object using it's key. So if we want to get the people group's name, we can access it like this: unreached['PeopNameInCountry'].

     Let's now turn our attention to formating the data for proper displaying. The population of the people group needs to be a comma seperated number. We will first convert the population to an integer using Python's built-in int() function. ( Python Docs) We will then use Python's built-in format() function ( Python Docs) to format it into a comma seperated integer. Here is the resulting code:

#!/usr/bin/python
# import the necessary libraries
import json
import urllib.request
import urllib.error
import string
import sys
# set some important variables
domain = "https://api.joshuaproject.net"
api_key = "YOUR_API_KEY"
url = domain+"/v1/people_groups/daily_unreached.json?api_key="+api_key
try:
    # request the API for the Daily Unreached People Group
    request = urllib.request.urlopen(api_url)
except urllib.error.HTTPError as e:
    print('The server couldn\'t fulfill the request.')
    print('Error code: ', e.code)
    exit
except urllib.error.URLError as e:
    print('We failed to reach a server.')
    print('Reason: ', e.reason)
    exit
else:
    # Everything worked
    # decode the response
    response = request.read().decode("utf8")
    # load the JSON
    data = json.loads(response)
    unreached = data[0]
    # format population to be a comma seperated integer
    unreached['Population'] = format(int(unreached['Population']), ',d')
                    

     Another formatting issue is related to the percent of Evangelicals. It is possible that it will be set to null. I would prefer to show 0.00 instead of null. So we will use Python's if condition to check if the percent of Evangelicals is None, if so we will set it to 0. We will then use Python's built-in float() function ( Python Docs) to format it as a floating point (decimal). Here is the code:

#!/usr/bin/python
# import the necessary libraries
import json
import urllib.request
import urllib.error
import string
import sys
# set some important variables
domain = "https://api.joshuaproject.net"
api_key = "YOUR_API_KEY"
url = domain+"/v1/people_groups/daily_unreached.json?api_key="+api_key
try:
    # request the API for the Daily Unreached People Group
    request = urllib.request.urlopen(api_url)
except urllib.error.HTTPError as e:
    print('The server couldn\'t fulfill the request.')
    print('Error code: ', e.code)
    exit
except urllib.error.URLError as e:
    print('We failed to reach a server.')
    print('Reason: ', e.reason)
    exit
else:
    # Everything worked
    # decode the response
    response = request.read().decode("utf8")
    # load the JSON
    data = json.loads(response)
    unreached = data[0]
    # format population to be a comma seperated integer
    unreached['Population'] = format(int(unreached['Population']), ',d')
    # check if percent of Evangelicals is None
    if unreached['PercentEvangelical'] is None:
        unreached['PercentEvangelical'] = '0'
    # format percent of Evangelicals to percent
    unreached['PercentEvangelical'] = float(unreached['PercentEvangelical'])
                    

     So we are now on the last stretch! All we have to do now is generate the widget HTML file. We will use Python's Template strings ( Python Docs) in order to substitute unique $-based variables in our template file with the unreached people group information we already retrieved. After we have replaced everything, we will then save the final file as generated_code/widget.html. First, open the templates/index.html file. Now add the following $-based variables to the file:

<!DOCTYPE html>
<html>
    <head>
        <title>Joshua Project | Sample Code (Javascript)</title>
        <link rel="stylesheet" type="text/css" href="../../css/styles.css">
    </head>
    <body>
        <p>
            This Sample Code is designed to demonstrate how to retrieve the Daily Unreached from the
            <a href="" class="domain-link">Joshua Project API</a> using Python.
        </p>
        <div id="jp_widget">
            <div class="upgotd upgotd-title">
                <a href="https://joshuaproject.net/upgotdfeed.php" class="upgotd-link">
                Unreached of the Day
                </a>
            </div>
            <div class="upgotd-image">
                <a
                href="$PeopleGroupURL"
                class="upgotd-link pg-link"
                id="people-group-image">
                    <img
                    src="$PeopleGroupPhotoURL"
                    height="160"
                    width="128"
                    alt="Unreached of the Day Photo">
                </a>
            </div>
            <div class="upgotd upgotd-pray">Please pray for the ...</div>
            <div class="upgotd upgotd-people">
                <a
                href="$PeopleGroupURL"
                class="upgotd-link pg-link pg-name">
                $PeopNameInCountry
                </a> of
                <a
                href="$CountryURL"
                class="upgotd-link country-link country-name">
                $Ctry
                </a>
            </div>
            <table align="center" class="upgotd-table" cellpadding="0" cellspacing="0">
                <tbody><tr>
                    <td width="65">Population:</td>
                    <td width="135" class="pg-population">
                    $Population
                    </td>
                </tr>
                <tr>
                    <td>Language:</td>
                    <td class="pg-language">
                    $PrimaryLanguageName
                    </td>
                </tr>
                <tr>
                    <td>Religion:</td>
                    <td class="pg-religion">
                    $PrimaryReligion
                    </td>
                </tr>
                <tr>
                    <td>Evangelical:</td>
                    <td class="pg-evangelical">
                    $PercentEvangelical%
                    </td>
                </tr>
                <tr>
                    <td>Status:</td>
                    <td>
                        <a
                        href="https://joshuaproject.net/definitions.php?term=25"
                        class="upgotd-link pg-scale-text">
                            $JPScaleText
                        </a> (
                        <a
                        href="https://joshuaproject.net/global-progress-scale.php"
                        class="upgotd-link pg-scale">
                            $JPScale
                        </a>
                        <a
                        href="https://joshuaproject.net/global-progress-scale.php"
                        class="upgotd-link"
                        id="progress-scale-image">
                            <img src="$JPScaleImageURL" alt="Progress Scale">
                        </a>)
                    </td>
                </tr>
            </tbody></table>
            <div class="upgotd upgotd-footer">Add this daily global vision feature to
            <br><a href="/upgotdfeed.php" class="upgotd-link">your website</a> or
            get it <a href="http://www.unreachedoftheday.org/unreached-email.php" class="upgotd-link">
            by email</a>.</div>
        </div>
    </body>
</html>
                    

     As you can see in the code above, we will use Python's Template strings ( Python Docs) to replace $Population with unreached['Population'] in our generate_widget.py script. The first step is to retrieve the template file using Python's built-in open() function ( Python Docs) which will open the file. After opening the file, we want to use Python's file object .read() function ( Python Docs) to read the file contents into a variable. here is the code:

#!/usr/bin/python
# import the necessary libraries
import json
import urllib.request
import urllib.error
import string
import sys
# set some important variables
domain = "https://api.joshuaproject.net"
api_key = "YOUR_API_KEY"
url = domain+"/v1/people_groups/daily_unreached.json?api_key="+api_key
try:
    # request the API for the Daily Unreached People Group
    request = urllib.request.urlopen(api_url)
except urllib.error.HTTPError as e:
    print('The server couldn\'t fulfill the request.')
    print('Error code: ', e.code)
    exit
except urllib.error.URLError as e:
    print('We failed to reach a server.')
    print('Reason: ', e.reason)
    exit
else:
    # Everything worked
    # decode the response
    response = request.read().decode("utf8")
    # load the JSON
    data = json.loads(response)
    unreached = data[0]
    # format population to be a comma seperated integer
    unreached['Population'] = format(int(unreached['Population']), ',d')
    # check if percent of Evangelicals is None
    if unreached['PercentEvangelical'] is None:
        unreached['PercentEvangelical'] = '0'
    # format percent of Evangelicals to percent
    unreached['PercentEvangelical'] = float(unreached['PercentEvangelical'])
    # get the template file
    index_file = open('templates/index.html').read()
                    

     Now that we have the template file's content, we can feed that to Python's string.Template function ( Python Docs) to initialize a new template. Here is the code:

#!/usr/bin/python
# import the necessary libraries
import json
import urllib.request
import urllib.error
import string
import sys
# set some important variables
domain = "https://api.joshuaproject.net"
api_key = "YOUR_API_KEY"
url = domain+"/v1/people_groups/daily_unreached.json?api_key="+api_key
try:
    # request the API for the Daily Unreached People Group
    request = urllib.request.urlopen(api_url)
except urllib.error.HTTPError as e:
    print('The server couldn\'t fulfill the request.')
    print('Error code: ', e.code)
    exit
except urllib.error.URLError as e:
    print('We failed to reach a server.')
    print('Reason: ', e.reason)
    exit
else:
    # Everything worked
    # decode the response
    response = request.read().decode("utf8")
    # load the JSON
    data = json.loads(response)
    unreached = data[0]
    # format population to be a comma seperated integer
    unreached['Population'] = format(int(unreached['Population']), ',d')
    # check if percent of Evangelicals is None
    if unreached['PercentEvangelical'] is None:
        unreached['PercentEvangelical'] = '0'
    # format percent of Evangelicals to percent
    unreached['PercentEvangelical'] = float(unreached['PercentEvangelical'])
    # get the template file
    index_file = open('templates/index.html').read()
    # initialize a new template
    template = string.Template(index_file)
                    

     Let's trigger the substitution of the $-based variables using Python's string.Template .substitute() function ( Python Docs) on the new template object we created. We will pass into it the unreached variable for replacement.

#!/usr/bin/python
# import the necessary libraries
import json
import urllib.request
import urllib.error
import string
import sys
# set some important variables
domain = "https://api.joshuaproject.net"
api_key = "YOUR_API_KEY"
url = domain+"/v1/people_groups/daily_unreached.json?api_key="+api_key
try:
    # request the API for the Daily Unreached People Group
    request = urllib.request.urlopen(api_url)
except urllib.error.HTTPError as e:
    print('The server couldn\'t fulfill the request.')
    print('Error code: ', e.code)
    exit
except urllib.error.URLError as e:
    print('We failed to reach a server.')
    print('Reason: ', e.reason)
    exit
else:
    # Everything worked
    # decode the response
    response = request.read().decode("utf8")
    # load the JSON
    data = json.loads(response)
    unreached = data[0]
    # format population to be a comma seperated integer
    unreached['Population'] = format(int(unreached['Population']), ',d')
    # check if percent of Evangelicals is None
    if unreached['PercentEvangelical'] is None:
        unreached['PercentEvangelical'] = '0'
    # format percent of Evangelicals to percent
    unreached['PercentEvangelical'] = float(unreached['PercentEvangelical'])
    # get the template file
    index_file = open('templates/index.html').read()
    # initialize a new template
    template = string.Template(index_file)
    # make the substitution
    final_code = template.substitute(unreached)
                    

     The variable final_code now holds the final code we need to write into our generated_code/widget.html file. We will use Python's built-in open() function ( Python Docs) to open the new file. You will notice that we added a second parameter ('w') to make the file writable. We will finally write the file using Python's file object .write() function ( Python Docs) passing it the final_code variable.

#!/usr/bin/python
# import the necessary libraries
import json
import urllib.request
import urllib.error
import string
import sys
# set some important variables
domain = "https://api.joshuaproject.net"
api_key = "YOUR_API_KEY"
url = domain+"/v1/people_groups/daily_unreached.json?api_key="+api_key
try:
    # request the API for the Daily Unreached People Group
    request = urllib.request.urlopen(api_url)
except urllib.error.HTTPError as e:
    print('The server couldn\'t fulfill the request.')
    print('Error code: ', e.code)
    exit
except urllib.error.URLError as e:
    print('We failed to reach a server.')
    print('Reason: ', e.reason)
    exit
else:
    # Everything worked
    # decode the response
    response = request.read().decode("utf8")
    # load the JSON
    data = json.loads(response)
    unreached = data[0]
    # format population to be a comma seperated integer
    unreached['Population'] = format(int(unreached['Population']), ',d')
    # check if percent of Evangelicals is None
    if unreached['PercentEvangelical'] is None:
        unreached['PercentEvangelical'] = '0'
    # format percent of Evangelicals to percent
    unreached['PercentEvangelical'] = float(unreached['PercentEvangelical'])
    # get the template file
    index_file = open('templates/index.html').read()
    # initialize a new template
    template = string.Template(index_file)
    # make the substitution
    final_code = template.substitute(unreached)
    # create the widget.html file
    widget_file = open('generated_code/widget.html','w')
    widget_file.write(final_code)
                    

     If you run this script from your command line utility, you will see that it generates the generated_code/widget.html file. Now open that file in your favorite web browser. You should see something similar to this:

Snapshot of Final Widget

     Mine looks different! If you do not supply a month or day parameter, the API will return today's unreached people group of the day by default. Most likely you are not doing this tutorial the same day as I was.

     Congratulations! You have completed the Python tutorial. If you would like to download the sample code, you can visit our Github Account.

Setup

     Before starting this tutorial, you will need to have a basic understanding of the Ruby programming language. We will be using Ruby version 2.0 in this tutorial. You will also need to be able to run ruby scripts in your command line utility. This tutorial does not discuss how to install Ruby.

     In this tutorial, we will build a generator that creates the necessary HTML & CSS for the widget. Everytime you run the script from the command line, it will create the widget with the latest people group data. Once you have downloaded and unzipped the Ruby starting code, open it up and look around. Here is the basic code structure:

  • css - directory for CSS Stylesheets
    • styles.css - the basic styles for the widget
  • generated_code - directory for the code created by our generator
  • templates - directory for the HTML/ERB templates
    • index.html.erb - the HTML/ERB template for the widget
  • generate_widget.rb - the generator script we will build

     Go ahead and open the generate_widget.rb file in your favorite text editor. We will begin by including any modules/gems we will need for the script. We will use Ruby's require method ( Ruby Docs) to include the Net/HTTP module ( Ruby Docs), and JSON module ( Ruby Docs). We will also need the Erubis gem. You will need to install Erubis using to command gem install erubis. Here is the start of our code:

# We will use Erubis for the templating
require "erubis"
# We need net/http to handle the request to the API
require "net/http"
# We will need to parse the JSON response
require "json"
                    

Calling the API

     Now that we have required the necessary gems/modules, we need to generated the API request. We will start by creating 3 variables for the API domain, API key, and the API path for the request. Remember to add your API key! Here is the code:

# We will use Erubis for the templating
require "erubis"
# We need net/http to handle the request to the API
require "net/http"
# We will need to parse the JSON response
require "json"
# set some important variables
domain = "jpapi.codingstudio.org"
api_key = "YOUR_API_KEY"
api_path = "/v1/people_groups/daily_unreached.json?api_key=#{api_key}"
                    

     We will call the API in a Ruby begin...end block. ( Ruby Docs) This will allow us the opportunity to rescue from a failed request, and print out the error. Here is the block:

# We will use Erubis for the templating
require "erubis"
# We need net/http to handle the request to the API
require "net/http"
# We will need to parse the JSON response
require "json"
# set some important variables
domain = "jpapi.codingstudio.org"
api_key = "YOUR_API_KEY"
api_path = "/v1/people_groups/daily_unreached.json?api_key=#{api_key}"
begin
    # Make the request to the Joshua Project API
rescue Exception => e
    # We had an error
    puts "Unable to get the API data"
    puts e.message
    abort
end
                    

     We will now use the Net/HTTP module ( Ruby Docs) to send the GET request to the API. We will use it's .get() method for this. ( Ruby Docs). We will then set the response to the variable response. Here is the code to accomplish this:

# We will use Erubis for the templating
require "erubis"
# We need net/http to handle the request to the API
require "net/http"
# We will need to parse the JSON response
require "json"
# set some important variables
domain = "jpapi.codingstudio.org"
api_key = "YOUR_API_KEY"
api_path = "/v1/people_groups/daily_unreached.json?api_key=#{api_key}"
begin
    # Make the request to the Joshua Project API
    response = Net::HTTP.get(domain, api_path)
rescue Exception => e
    # We had an error
    puts "Unable to get the API data"
    puts e.message
    abort
end
                    

     Now that we have a response, we need to parse the JSON into a Ruby object. This is where the JSON module ( Ruby Docs) comes in handy. Weill use it's .parse() method ( Ruby Docs) to accomplish this. Let us also add some temporary code to display what we receive back. Here is the code:

# We will use Erubis for the templating
require "erubis"
# We need net/http to handle the request to the API
require "net/http"
# We will need to parse the JSON response
require "json"
# set some important variables
domain = "jpapi.codingstudio.org"
api_key = "YOUR_API_KEY"
api_path = "/v1/people_groups/daily_unreached.json?api_key=#{api_key}"
begin
    # Make the request to the Joshua Project API
    response = Net::HTTP.get(domain, api_path)
    # Parse the response
    data = JSON.parse(response)
    puts data
rescue Exception => e
    # We had an error
    puts "Unable to get the API data"
    puts e.message
    abort
end
                    

     Now run this code in your command line utility, and you should see something very similar to the API response we showed you up top. The .parse() method ( Ruby Docs) converted the JSON to a Ruby Array ( Ruby Docs) of Hashes (Ruby Docs). To access the first Hash, we can use the Array index of the first object 0 like this: data[0].

# We will use Erubis for the templating
require "erubis"
# We need net/http to handle the request to the API
require "net/http"
# We will need to parse the JSON response
require "json"
# set some important variables
domain = "jpapi.codingstudio.org"
api_key = "YOUR_API_KEY"
api_path = "/v1/people_groups/daily_unreached.json?api_key=#{api_key}"
begin
    # Make the request to the Joshua Project API
    response = Net::HTTP.get(domain, api_path)
    # Parse the response
    data = JSON.parse(response)
    unreached = data[0]
rescue Exception => e
    # We had an error
    puts "Unable to get the API data"
    puts e.message
    abort
end
                    

Creating the Widget

     Now we can access any of the supplied attributes of that Hash object using it's key. So if we want to get the people group's name, we can access it like this: unreached['PeopNameInCountry'].

     In order to display the information properly, we need to format the population and percent of Evangelicals. For the population, we want to format it as a comma seperated number. To do this, we will convert the population to a string using Ruby's .to_s method. ( Ruby Docs ) After converting it to a string, we will use Ruby's String .gsub() method ( Ruby Docs ) to use a Regular Expression to format the string. Here is the code to format the population:

# We will use Erubis for the templating
require "erubis"
# We need net/http to handle the request to the API
require "net/http"
# We will need to parse the JSON response
require "json"
# set some important variables
domain = "jpapi.codingstudio.org"
api_key = "YOUR_API_KEY"
api_path = "/v1/people_groups/daily_unreached.json?api_key=#{api_key}"
begin
    # Make the request to the Joshua Project API
    response = Net::HTTP.get(domain, api_path)
    # Parse the response
    data = JSON.parse(response)
    unreached = data[0]
rescue Exception => e
    # We had an error
    puts "Unable to get the API data"
    puts e.message
    abort
end
# format the population to a comma seperated value
unreached['Population'] = unreached['Population'].to_s.gsub(/(\d)(?=(\d{3})+$)/,'\1,')
                    

     Sometimes the percent of Evangelicals can be nil. I would prefer to display 0.00 rather then nil. To do this, we will use Ruby's if...end block and the .nil? method ( Ruby Docs) to check it's value.

# We will use Erubis for the templating
require "erubis"
# We need net/http to handle the request to the API
require "net/http"
# We will need to parse the JSON response
require "json"
# set some important variables
domain = "jpapi.codingstudio.org"
api_key = "YOUR_API_KEY"
api_path = "/v1/people_groups/daily_unreached.json?api_key=#{api_key}"
begin
    # Make the request to the Joshua Project API
    response = Net::HTTP.get(domain, api_path)
    # Parse the response
    data = JSON.parse(response)
    unreached = data[0]
rescue Exception => e
    # We had an error
    puts "Unable to get the API data"
    puts e.message
    abort
end
# format the population to a comma seperated value
unreached['Population'] = unreached['Population'].to_s.gsub(/(\d)(?=(\d{3})+$)/,'\1,')
# Lets handle the evangelical number since it can be nil
if unreached['PercentEvangelical'].nil?
    unreached['PercentEvangelical'] = "0.00"
else
    # format the percent to a floating point (decimal)
end
                    

     If the percent of Evangelicals is not nil, then we want to convert it to a floating point (decimal).

# We will use Erubis for the templating
require "erubis"
# We need net/http to handle the request to the API
require "net/http"
# We will need to parse the JSON response
require "json"
# set some important variables
domain = "jpapi.codingstudio.org"
api_key = "YOUR_API_KEY"
api_path = "/v1/people_groups/daily_unreached.json?api_key=#{api_key}"
begin
    # Make the request to the Joshua Project API
    response = Net::HTTP.get(domain, api_path)
    # Parse the response
    data = JSON.parse(response)
    unreached = data[0]
rescue Exception => e
    # We had an error
    puts "Unable to get the API data"
    puts e.message
    abort
end
# format the population to a comma seperated value
unreached['Population'] = unreached['Population'].to_s.gsub(/(\d)(?=(\d{3})+$)/,'\1,')
# Lets handle the evangelical number since it can be nil
if unreached['PercentEvangelical'].nil?
    unreached['PercentEvangelical'] = "0.00"
else
    # format the percent to a floating point (decimal)
    unreached['PercentEvangelical'] = '%.2f' % unreached['PercentEvangelical']
end
                    

     Now that all the attributes have been formatted, we are ready to create the generated_code/widget.html file. We will use a common Ruby templating gem called Erubis. This templating engine gives us the ability to embed Ruby in a HTML template file. All Ruby is wrapped with a <% %> tag. Any ruby within those tags will be run when the template is processed. Open the templates/index.html.erb file and update with the following Erubis code:

<html>
    <head>
        <title>Joshua Project</title>
        <link rel="stylesheet" type="text/css" href="../css/styles.css">
    </head>
    <body>
        <div id="jp_widget">
            <div class="upgotd upgotd-title">
                <a href="https://joshuaproject.net/upgotdfeed.php" class="upgotd-link">
                Unreached of the Day</a>
            </div>
            <div class="upgotd-image">
                <a
                href="<%= unreached['PeopleGroupURL'] %>"
                class="upgotd-link pg-link"
                id="people-group-image">
                    <img
                    src="<%= unreached['PeopleGroupPhotoURL'] %>"
                    height="160"
                    width="128"
                    alt="Unreached of the Day Photo">
                </a>
            </div>
            <div class="upgotd upgotd-pray">Please pray for the ...</div>
            <div class="upgotd upgotd-people">
                <a
                href="<%= unreached['PeopleGroupURL'] %>"
                class="upgotd-link pg-link pg-name">
                <%= unreached['PeopNameInCountry'] %>
                </a> of
                <a
                href="<%= unreached['CountryURL'] %>"
                class="upgotd-link country-link country-name">
                <%= unreached['Ctry'] %>
                </a>
            </div>
            <table align="center" class="upgotd-table" cellpadding="0" cellspacing="0">
                <tbody><tr>
                    <td width="65">Population:</td>
                    <td width="135" class="pg-population">
                        <%= unreached['Population'] %>
                    </td>
                </tr>
                <tr>
                    <td>Language:</td>
                    <td class="pg-language">
                        <%= unreached['PrimaryLanguageName'] %>
                    </td>
                </tr>
                <tr>
                    <td>Religion:</td>
                    <td class="pg-religion">
                        <%= unreached['PrimaryReligion'] %>
                    </td>
                </tr>
                <tr>
                    <td>Evangelical:</td>
                    <td class="pg-evangelical">
                        <%= unreached['PercentEvangelical'] %>%
                    </td>
                </tr>
                <tr>
                    <td>Status:</td>
                    <td>
                        <a
                        href="https://joshuaproject.net/definitions.php?term=25"
                        class="upgotd-link pg-scale-text">
                            <%= unreached['JPScaleText'] %>
                        </a> (
                        <a
                        href="https://joshuaproject.net/global-progress-scale.php"
                        class="upgotd-link pg-scale">
                            <%= unreached['JPScale'] %>
                        </a>
                        <a
                        href="https://joshuaproject.net/global-progress-scale.php"
                        class="upgotd-link"
                        id="progress-scale-image">
                            <img
                            src="<%= unreached['JPScaleImageURL'] %>"
                            alt="Progress Scale">
                        </a>)
                    </td>
                </tr>
            </tbody></table>
            <div class="upgotd upgotd-footer">Add this daily global vision feature to
            <br><a href="/upgotdfeed.php" class="upgotd-link">your website</a>
            or get it <a
            href="http://www.unreachedoftheday.org/unreached-email.php"
            class="upgotd-link">
            by email
            </a>.
            </div>
        </div>
    </body>
</html>
                    

     As you can see in the code above, we will use Erubis to replace <% unreached['Population'] %> with unreached['Population'] in our generate_widget.rb script. So why does the Erubis code start with <%=? The equal (=) sign tells Erubis to print out the variable.

     We now need to read the templating file code into a variable using Ruby's File .read() method. ( Ruby Docs ) After we have the content in the variable, we need to pass it to a new instance of Erubis. We will finally use Erubis' .result() method to replace all the tags with the appropriate variables. Go back to the generate_widget.rb file and add the following code:

# We will use Erubis for the templating
require "erubis"
# We need net/http to handle the request to the API
require "net/http"
# We will need to parse the JSON response
require "json"
# set some important variables
domain = "jpapi.codingstudio.org"
api_key = "YOUR_API_KEY"
api_path = "/v1/people_groups/daily_unreached.json?api_key=#{api_key}"
begin
    # Make the request to the Joshua Project API
    response = Net::HTTP.get(domain, api_path)
    # Parse the response
    data = JSON.parse(response)
    unreached = data[0]
rescue Exception => e
    # We had an error
    puts "Unable to get the API data"
    puts e.message
    abort
end
# format the population to a comma seperated value
unreached['Population'] = unreached['Population'].to_s.gsub(/(\d)(?=(\d{3})+$)/,'\1,')
# Lets handle the evangelical number since it can be nil
if unreached['PercentEvangelical'].nil?
    unreached['PercentEvangelical'] = "0.00"
else
    # format the percent to a floating point (decimal)
    unreached['PercentEvangelical'] = '%.2f' % unreached['PercentEvangelical']
end
# Generate the template
template_file = File.read("templates/index.html.erb")
template = Erubis::Eruby.new(template_file)
# run the Erubis substitution
widget_code = template.result({unreached: unreached})

                    

     We can now write the new templated code to the generated_code/widget.html file. In order to ensure that the file is written correctly, we will use Ruby's begin...rescue...ensure block. This will ensure that the file is closed in case something goes wrong. Add the following code:

# We will use Erubis for the templating
require "erubis"
# We need net/http to handle the request to the API
require "net/http"
# We will need to parse the JSON response
require "json"
# set some important variables
domain = "jpapi.codingstudio.org"
api_key = "YOUR_API_KEY"
api_path = "/v1/people_groups/daily_unreached.json?api_key=#{api_key}"
begin
    # Make the request to the Joshua Project API
    response = Net::HTTP.get(domain, api_path)
    # Parse the response
    data = JSON.parse(response)
    unreached = data[0]
rescue Exception => e
    # We had an error
    puts "Unable to get the API data"
    puts e.message
    abort
end
# format the population to a comma seperated value
unreached['Population'] = unreached['Population'].to_s.gsub(/(\d)(?=(\d{3})+$)/,'\1,')
# Lets handle the evangelical number since it can be nil
if unreached['PercentEvangelical'].nil?
    unreached['PercentEvangelical'] = "0.00"
else
    # format the percent to a floating point (decimal)
    unreached['PercentEvangelical'] = '%.2f' % unreached['PercentEvangelical']
end
# We will write the final HTML file
begin
    # write the new file
rescue IOError => e
    # We had an error
    puts "Unable to write the HTML file"
    puts e.message
    abort
ensure
    # ensure the file closes happens if this fails
end
                    

     As you can see in the code, if an error occurs it will display on the screen. We now need to open the new file generated_code/widget.html for writing using Ruby's File .open() method. ( Ruby Docs) We will pass it the 'w' option to make it writable. We will also use Ruby's File .close() method ( Ruby Docs) in the ensure block to close the file. Here is the code:

# We will use Erubis for the templating
require "erubis"
# We need net/http to handle the request to the API
require "net/http"
# We will need to parse the JSON response
require "json"
# set some important variables
domain = "jpapi.codingstudio.org"
api_key = "YOUR_API_KEY"
api_path = "/v1/people_groups/daily_unreached.json?api_key=#{api_key}"
begin
    # Make the request to the Joshua Project API
    response = Net::HTTP.get(domain, api_path)
    # Parse the response
    data = JSON.parse(response)
    unreached = data[0]
rescue Exception => e
    # We had an error
    puts "Unable to get the API data"
    puts e.message
    abort
end
# format the population to a comma seperated value
unreached['Population'] = unreached['Population'].to_s.gsub(/(\d)(?=(\d{3})+$)/,'\1,')
# Lets handle the evangelical number since it can be nil
if unreached['PercentEvangelical'].nil?
    unreached['PercentEvangelical'] = "0.00"
else
    # format the percent to a floating point (decimal)
    unreached['PercentEvangelical'] = '%.2f' % unreached['PercentEvangelical']
end
# We will write the final HTML file
begin
    # write the new file
    # open the final file
    file = File.open("generated_code/widget.html", "w")
    file.write(widget_code)
rescue IOError => e
    # We had an error
    puts "Unable to write the HTML file"
    puts e.message
    abort
ensure
    # ensure the file closes happens if this fails
    file.close unless file == nil
end
                    

     Now run the script from your command line utility. Everytime you run it, it should generate a new generated_code/widget.html file with the latest people group. Open the generated_code/widget.html file in your favorite web browser, and you should see something similar to this:

Snapshot of Final Widget

     But why different data! If you do not supply a month or day parameter, the API will return today's unreached people group of the day by default. Most likely you are not doing this tutorial the same day as I was.

     Congratulations! You have completed the Ruby tutorial. If you would like to download the sample code, you can visit our Github Account.

     If you find any errors within these tutorials, or would like to suggest a new language/approach, please submit your request at our Github issue tracker.