PRO Version: Create Custom Pages out of JSON and Custom Post Types

Usually the JSON Content Importer PRO Plugin (JCI) retrieves JSON from an API, converts the data with a template to HTML and displays this HTML. That’s it.
The PRO-Version can do more: It can create Custom Post Pages with Custom Post Fields (CPF) and Taxonomies out of a Custom Post Type.


Example:
The JSON http://api.json-content-importer.com/extra/json/meetup/1.json lists several events.

Your task:
Display and store this data in wordpress. Each event should have it’s own url and “page” (aka “Custom Post” (CP) made out of a “Custom Post Type”-template (CPT)). Also these CP should have Taxonomies (like categories for event-types) and Custom Post Fields (CPF) like latitude and longitude of the venue.


See how this works with JCI and Plugins like Toolset, Pods or Advanced Custom Fields (ACF):


See how this works with the JCI without other Plugins:

  • STEP 1
    First of all you need a Custom Post Type (CPT): This is the Template / blueprint for all the Pages that will be created. You can create such a CPT in several ways:
    • Use the WordPress-Posts- or -Pages: As they already exist Step 1 is already done
    • Use Plugins like Toolset or Pods: With that you can create CPT with CPF and Taxonomies very fast and flexible.
    • If you do not need Taxonomies and want to have direct access to all settings this is an alternative, but a bit techie, way: The JSON Content Importer-Plugin comes with it’s own “JCI-CPT-Creator”. For that see the Options of the JCI-plugin, there the Tab “Custom Post Types”. See Video and code-examples here



      Define / register a “Custom Post Type” in the Options of the JCI-plugin, there the Tab “Custom Post Types”.
      Here you have to define three parameters importains for the Custom PostType:
      – type: Singluar name of the Custom Post Type. The Plugin adds automatic “jci_” as prefix to avoid trouble with other plugins
      – ptredirect: Path for the URL of the created Custom Post
      – ptname: Menuname in the WordPress-Dashboard
      – key: Unique, random string to connect all pages created by this JSON (when deleting, all pages with that key are deleted)
      The keys and values have to be separated by “=” and the pairs by “;”. If you want to define more than one Custom Post Type separate by “##”.

      Example:
      type=mynewposttype;ptredirect=herewego;ptname=MyCreatedPost;key=34tdssg54##type=mynewposttype1;petredirect=herewego1;ptname=MyCreatedPost1;key=skjfh4312

      When setting “deleteold=some” you can use twig-code in “key”. E. g. key=date{{“now”|date(“Ymd”)}} creates keys with the current date.
      If you enhance the twig-code for the key by if-then-else and JSON-data you can build keys for each JSON-item. If the key is empty nothing is deleted or created. When updating the CPT with new JSON you can delete some old CPT and keep some CPT.

      The WordPress-Admin-Menu should have the items “MyCreatedPosts” and “MyCreatedPost1”.

       

  • STEP 2
    Set Permalink “Post name”
    Click to the general Settings of WordPress, there “Permalinks” and select the “Post name”-Radiobutton and store.

     

  • STEP 3
    Create a new JCI-template
    Click to the Plugins template-manager and add one template with

    .
    Save it.This template is used for defining the access to JSON and for building each single Custom Post (we improve that template later).

     

  • STEP 4:
    Create a new ordinary (!) WordPress Page
    There we place all we need to create Custom Posts like the shortcode (we do create one in the next step).
    Title of this page: Something like “Create Custom Post”. Store that page as draft (later we publish it).

     

  • STEP 5:
    Set up a Shortcode and add it to the WordPress Page created in Step 4:
    Example:

    [jsoncontentimporterpro debugmode=10 nameoftemplate=mytemplate1]
    
    • debugmode=10: display details of the plugin-action (r. g. how the JSON-API is used), delete in the end if all is ok
    • nameoftemplate: name of the JCI-template
    • Additional Parameter: Up to now we’re creating a usual get-and-display-page. If you need more parameter just add it.

     

  • STEP 6:
    View Creating Page
    Preview the so far created WordPress-Page which will later create the Custom Posts. You shoud see some debug-messages: Esp. the JSON-Code retrieved should be there. If not you have to check the Shortcode for missing parameter. Also the template-default-text should be there (see Step 3). If this looks good publish this page.

     

  • STEP 7:
    Check the JSON-data
    You should be familiar with the JSON you retrieve. You can copy paste the JSON into http://www.jsoneditoronline.org to see the structure. As you want to create a set of Custom Posts you need a set of data for that. You must identify the path to such a set in your JSON.

    In the example http://api.json-content-importer.com/extra/json/meetup/1.json the path is the root as the JSON is a collection (aka array) of JSON-objects.

     

  • STEP 8:
    Enhance Shortcode: Add information on how to create Custom Posts (CP) out of the CPT
    For creating CPs the plugin needs two Shortcode-Parameter: “mode” and “createoptions”. We now add these to the Shortcode created in Step 5.
    Example (when copypasting remove all linefeeds!):
    [jsoncontentimporterpro nameoftemplate=mytemplate1 mode=create createoptions='{“key”: “randomkey274t32t3″,”type”: “mynewposttype”, “loop”:””, “title”:”cp-title: {{name}}”, “minimumcptocreate”:”2″, “postpublishtime”:”{{data_of_publishing_in_json}}”, “requiredfields”:”name”, “slugname”: “cp-slug-{{name|replace({#SQM#/#SQM#: #SQM#-#SQM#})}}”, “deleteold”:”yes”, “postdateoffset”:”Europe/Berlin”}’]

    TAKE CARE: Copypaste Code from the following box – this avoids trouble with inavlaid quotation marks

    [jsoncontentimporterpro nameoftemplate=mytemaplte1 mode=create createoptions='{"key": "randomkey274t32t3","type": "mynewposttype", "loop":"", "title":"cp-title: {{name}}", "minimumcptocreate":"2", "postpublishtime":"{{data_of_publishing_in_json}}", "requiredfields":"name", "slugname": "cp-slug-{{name|replace({#SQM#/#SQM#: #SQM#-#SQM#})}}", "deleteold":"yes", "postdateoffset":"Europe/Berlin"}']
    

    In detail:

    • mode=create: This sets an plugin-call into “create Custom Posts mode”
    • – createoptions=…: JSON-coded parameter on how to build the Custom Posts
    • mandatory fields:
      • “key” or “cptkey”:”randomkey274t32t3“: A random key for identifying connected CP
      • “type”:”mynewpagetype“: This is the link to the Custom Post Type defined in Step 1. If you use WordPress-Pages or -Posts use “page” or “post”
      • “loop”:”data”: The Plugin needs a set of data (aka array) in the JSON-data. Use “#singlepage#” if you want to create a single Custom Posts with all JSON you have. This is defined here. See also Step 7 for that
      • “title”:”cp-title:{{name}}”: twig-template for building the Title of the created Custom Post. E.g. find in your JSON data for the Custom Post HTML-title. E.g. “{{name}}”
      • “slugname”: “cp-slug-{{name|replace({#SQM#/#SQM#: #SQM#-#SQM#})}}”: twig-template for building the slug/URL of the created Custom Post. Finde something in the JSON-data for that, like “{{id}}”
      • “deleteold”:”yes”: (mandatory): When creating new Custom Posts all previous Custom Posts are deleted (they are identified by “jci_uniquekey_createpost”, see Step 2). Either “yes”, “no” or “some” (see later)
    • optional fields:
      • “loopstart”:NUMBER: Start the loop at item loopstart, count from 1 on (if 0 no loopstart/loopend functionality)
      • “loopend”:NUMBER: End the loop at item loopstart+loopend
      • “minimumcptocreate” e. g. “2”: Minimum number of to be created CP. If there are less in the JSON the creation / plugin would abort
      • “postpublishtime”: Set Publishing-date and time of generated Post, e.g. from a JSON-field with this info. You can use twig-code here with #SQM# (for '), #GT# (for >), #LT# (for <)-Placeholders
      • “requiredfields” e. g. “name”: Name of required JSON-datafield. If a dataset in the loop for the CP does not have such a field it would be ignored (e. g. if the JSON does not give data but an error etc.)
      • “featuredimage”: #BRO# {“url_json_path”:”detailpage.img”, “url_default”:”http://api.json-content-importer.com/wp-content/uploads/2020/01/icon-256×256-1.png”}#BRC# : This is to set a featured image for the CP. “detailpage.img” is an example for the path in the JSON to an URL with the CPs featured image. “url_default” defines a default image if there is nothing in the JSON- #BRO” and #BRC# stand for “Bracket open/close” as we work here with JSON, but in a shortcode no other square brackets are allowed, so we mask those here.
      • “postdateoffset”:”VALUE”: Date of generated Custom Post Types:
        set “VALUE” for the time and date of the generated Custom Post Fields.
        If not set the current PHP-Servertime is used.
        “VALUE” can be numeric: Then this number is subtracted from the current Servertime, e.g. one hour is 3600 seconds or 3600000 miliseconds.
        “VALUE” can be “wptimezone”: Then the in the WordPress-installation defined timezone is used
        “VALUE” can be a valid timezonestring

    Extended Example:

    [jsoncontentimporterpro nameoftemplate=mytemplate1 mode=create createoptions='{"key": "hellomyfriend242","type": "test01", "loop":"", "title":"cp-title: {{name}}", "loopstart":1,"loopend":4, "minimumcptocreate":"2", "postpublishtime":"{{data_of_publishing_in_json}}", "postdateoffset":3600, "requiredfields":"name", "slugname": "cp-slug-{{name|replace({#SQM#/#SQM#: #SQM#-#SQM#})}}", "deleteold":"yes", "featuredimage": #BRO# {"url_json_path":"detailpage.img", "url_default":"http://api.json-content-importer.com/wp-content/uploads/2020/01/icon-256x256-1.png"}#BRC#, "postdateoffset":"Europe/Berlin"}']
    

     

  • STEP 9:
    Create Custom Posts
    Publish the creating Post with the enhanced Shortcode and call it in the browser (you can switch off the template by adding “?show=oc”): This should create Custom Posts and show some debug-messages.
    In case of success in the WordPress-Menu a entry “ptname” (see Step 1) is created with a number of pages. Thes pages should be published pages with a URL “ptredirect” (see Step 1) plus “slugname” (see Step 8).

    • Open one of the created CP for editing. The content of the created Custom Post should be the executed template-default-text with JSON-data. If you used the “featured”-image this should be there too (maybe the default image)
    • Check, if the URL of the created CP (aka slug) works. If not, do step 2 again
    • In this way you can update your CP later, using the plugin written for that: Get URL Cron: With that ypo can call the URL or insert the whole Shortcode

     

  • STEP 10:
    Improve the content in the generated Custom Pages: edit JCI-template

    • Click to the Plugins template-manager and open the template used for generating in the shortcode. Edit the default-text which is put into the content area of the created Custom Posts together with the JSON-data
    • If you want to have a Shortcode on a generated Custom Page: E. g. having another [jsoncontentimporterpro…]-Shortcode parametrized by the data from the initial JSON-API-call you must mask the Square-Brackets like this: #BRO#jsoncontentimporterpro nameoftemplate=inside#BRC#. Otherwise WordPress gets confused.

    For the Example-JSON http://api.json-content-importer.com/extra/json/meetup/1.json you can try this:

    {{name}}, {{local_date | date("d.m.Y") }}, {{local_time}}: {{venue.name}}#BRO#jsoncontentimporterpro nameoftemplate=inside#BRC#<br>end of page

     

  • STEP 11:
    Create Custom Posts again, like in Step 9
    Now the created CP should have JSON data in the content!
    If there is twig-code you have an error in the twig-code: debug this, please!

     

  • STEP 12:
    Add Custom Post Fields (CPF)
    CPFs are added either via the CPT-Plugins like Toolset or Pods. Or with Advanced Custom Fields (ACF). Or via the Shortcode. This step is about creating and filling CPF with the plugin only. How to do it with the mentioned plugins see Step 13.
    For that add “customfields” to the Shortcode in the “createoptions” JSON. E. g. in the example like this:
    “customfields”: #BRO# {“cpf-name1″:”cpf-value1”}, {“cpf2{{JSONfield}}”:”date{{#SQM#now#SQM#|date(#SQM#mdY#SQM#)}}”}#BRC#

    "customfields": #BRO# {"cpf1":"cpf-value1"}, {"cpf2{{local_date}}":"date{{#SQM#now#SQM#|date(#SQM#mdY#SQM#)}}"}#BRC#

    Recreate the CP with that (see Step 9): Then two CPF in each created CP should be there. One named “cpf1” always with the same value. And “cpf2019-02-04” with the current time.

    Complete Shortcode:

    [jsoncontentimporterpro nameoftemplate=mytemplate1 mode=create createoptions='{"key": "hellomyfriend242","type": "test01", "loop":"", "title":"cp-title: {{name}}", "loopstart":1,"loopend":4, "minimumcptocreate":"2", "postpublishtime":"{{data_of_publishing_in_json}}", "postdateoffset":3600, "requiredfields":"name", "slugname": "cp-slug-{{name|replace({#SQM#/#SQM#: #SQM#-#SQM#})}}", "deleteold":"yes", "featuredimage": #BRO# {"url_json_path":"detailpage.img", "url_default":"http://api.json-content-importer.com/wp-content/uploads/2020/01/icon-256x256-1.png"}#BRC#, "customfields": #BRO# {"cpf1":"cpf-value1"}, {"cpf2{{local_date}}":"date{{#SQM#now#SQM#|date(#SQM#mdY#SQM#)}}"}#BRC#, "postdateoffset":"Europe/Berlin"}']
    

     

  • STEP 13:
    Create CP out of the CPT created by ACF, Toolset or Pods: JSON, Custom Posts, Custom Post Fields, Taxonomies
    By Toolset or Pods you define CPT with it’s CPF and Taxonomies. By ACF you can add CPF to CPT. With the JCI-plugin you can use these CPT and create CP with CPF and Taxonomies.

    • ACF:
      Add a field group with some fields. E. g. field groupt “acfgroup1” with fields “acf1” and “acf2”. Connect this to your Custom Post Type. When creating a new CPT manually you should see these two CPF.
      Add this to the shortcode:

      "cpt": #BRO# {"slug":"test01", "keeptaxonomies":"yes", "taxonomiesmatches": #BRO# {"NAME_OF_TOOLSET_OR_PODS_TAXONOMY_1":"JSON_PATH_BY_DOTS_1", "NAME_OF_TOOLSET_OR_PODS_TAXONOMY_1":"JSON_PATH_BY_DOTS_2"} #BRC#, "matches": #BRO# {"acf1":"aa{{local_date}}","acf2":"bb{{local_date}}"} #BRC# } #BRC#, 

      Full example, incl. Taxonomies:

      [jsoncontentimporterpro nameoftemplate=mytemplate1 mode=create createoptions='{"key": "hellomyfriend242","type_NOT_NEEDED_ANY_MORE_SEE_slug_in_cpt": "test01", "loop":"", "title":"cp-title: {{name}}", "cpt": #BRO# {"slug":"test01", "keeptaxonomies":"yes", "taxonomiesmatches": #BRO# {"NAME_OF_TOOLSET_OR_PODS_TAXONOMY_1":"JSON_PATH_BY_DOTS_1", "NAME_OF_TOOLSET_OR_PODS_TAXONOMY_1":"JSON_PATH_BY_DOTS_2"} #BRC#, "matches": #BRO# {"acf1":"aa{{local_date}}","acf2":"bb{{local_date}}"} #BRC# } #BRC#, "loopstart":1,"loopend":4, "minimumcptocreate":"2", "postpublishtime":"{{data_of_publishing_in_json}}", "postdateoffset":3600, "requiredfields":"name", "slugname": "cp-slug-{{name|replace({#SQM#/#SQM#: #SQM#-#SQM#})}}", "deleteold":"yes", "featuredimage": #BRO# {"url_json_path":"detailpage.img", "url_default":"http://api.json-content-importer.com/wp-content/uploads/2020/01/icon-256x256-1.png"}#BRC#, "customfields": #BRO# {"cpf1":"cpf-value1"}, {"cpf2{{local_date}}":"date{{#SQM#now#SQM#|date(#SQM#mdY#SQM#)}}"}#BRC#, "postdateoffset":"Europe/Berlin"}']

      In detail:
      “cpt”: #BRO# {
      “slug”:”SLUGNAME_OF_TOOLSET_OR_PODS_CPT: what we used before for type”,
      “keeptaxonomies”:”yes”, “taxonomiesmatches”: #BRO# {“NAME_OF_TOOLSET_OR_PODS_TAXONOMY_1″:”JSON_PATH_BY_DOTS_1”, “NAME_OF_TOOLSET_OR_PODS_TAXONOMY_1″:”JSON_PATH_BY_DOTS_2”} #BRC#,
      “matches”: #BRO# {“NAME_OF_TOOLSET_OR_PODS_OR_ACF_CPF_1″:”JSON_PATH_BY_DOTS_3″,”NAME_OF_TOOLSET_OR_PODS_OR_ACF_CPF_2″:”JSON_PATH_BY_DOTS_4”} #BRC#
      } #BRC#

      • slug”:”SLUGNAME_OF_TOOLSET_CPT” : this is the slug (Toolset, CustomPost) or type (page, post, JCI-name for CP) of the Custom Post. Use here what was used before at field “type” (which is not used when using “cpt”)
      • keeptaxonomies: “yes” or “no” : if “no” delete all previous created taxonomies, otherwise keep them (importaint, if you fill the CP in several steps)
      • taxonomiesmatches: #BRO# {“NAME_OF_TOOLSET_OR_PODS_TAXONOMY_1″:”JSON_PATH_BY_DOTS_1”, “NAME_OF_TOOLSET_OR_PODS_TAXONOMY_2″:”JSON_PATH_BY_DOTS_2”} #BRC# : list of taxonomies defined in a Toolset- or Pods-CPT and it’s counterpart in the JSON-data (notation of JSON-path: dots)
      • matches: #BRO# {“NAME_OF_TOOLSET_OR_PODS_OR_ACF_CPF_1″:”JSON_PATH_BY_DOTS_3″,”NAME_OF_TOOLSET_OR_PODS_OR_ACF_CPF_2″:”JSON_PATH_BY_DOTS_4”} #BRC# } #BRC# : list of CPF defined in a Toolset- / Pods- or ACF-CPT and it’s counterpart in the JSON-data (notation of JSON-path: dots)

       

    • With the free Pods-Plugin you can create a Custom Post Type with Custom Post Fields and Taxonomies.
      In the following Shortcode the Pod with slug (=name) “cppods1” has two CPF “podsf1” and “podsf2” plus a Taxonomy “podstax1”. Mind the masking for twig like #SQM# etc:

      [jsoncontentimporterpro nameoftemplate=mytemplate1 mode=create createoptions='{"key": "hellomyfriend242", "loop":"", "title":"pods-cp-title: {{name}}", "cpt": #BRO# {"slug":"cppods1", "keeptaxonomies":"no", "taxonomiesmatches": #BRO# {"podstax1":"tax{{local_date | date(#SQM#Ydm#SQM#) }}"} #BRC#, "matches": #BRO# {"podsf1":"aa{{local_date | date(#SQM#mdY#SQM#)}}","podsf2":"bb{{local_date}}"} #BRC# } #BRC#, "slugname": "cp-slug-{{name|replace({#SQM#/#SQM#: #SQM#-#SQM#})}}", "deleteold":"yes"}']
      

       

    • With the Toolset Types-Plugin you can create a Custom Post Type with Custom Post Fields and Taxonomies as well.
      In the following Shortcode the Toolset-CPT with slug (=name) “toolsetcpt” has two CPF “name” and “performances” plus a Taxonomy named “tstax”. Mind the masking for twig like #SQM# etc:

      [jsoncontentimporterpro nameoftemplate=mytemplate1 mode=create createoptions='{"key": "hellots1", "loop":"", "title":"ts-cp-title: {{name}}", "cpt": #BRO# {"slug":"toolsetcpt", "keeptaxonomies":"no", "taxonomiesmatches": #BRO# {"tstax":"tstax{{start_date| date(#SQM#Ydm#SQM#) }}"} #BRC#, "matches": #BRO# {"name":"ts-aa{{start_date| date(#SQM#mdY#SQM#)}}","performances": {"path":"performances", "valuefield":"twig-{{1000+id}}"}} #BRC# } #BRC#, "slugname": "ts-slug-{{name|replace({#SQM#/#SQM#: #SQM#-#SQM#})}}", "deleteold":"yes"}']
      

      It looks quite similar, but not at “matches” -> “performances”: If you want to fill a “multiple CPF” (one CPF which many different values) this can be done in the following way.
      See example-JSON at node “performances” of each item.

      • The “simple” way is just dumping all JSON-data of “performances” into the CPF by
        {{performances | json_encode}}
      • Storing multiple values in one CPF: Then go to the Toolset-setup of the CPF and check the box “Allow multiple instances of this field” to define this CPF as “multi”.
        First define ther cPF as “multi”: Go to the Toolset-setup of the CPF and check the box “Allow multiple instances of this field” to define this CPF as “multi”.

        2nd: The JSON gives us the values either in an array or an node where a field is the needed values. So we have to define the JSON-path to the data as close as possible. E. g. a path like “performances” (put together a path separated by “.”). And then, if it’s not an array, define which JSON-field should be used. In the example let’s use field “id”. With the following JSON in the shortcode we tell the plugin to use the values for “path” and “valuefield” for the CPF (twig code is executed in the “valuefield”):

        "performances": {"path":"performances", "valuefield":"twig-{{1000+id}}"}

      • Another toolset-hint: Toolset stores dates in the unix-time-format. So you have to have this format in the Shortcode. Example if you want to have a random date in da toolset-date-cpf:
        "eventdate": "{{ random(+#SQM#now#SQM#|date(#SQM#U#SQM#)) }}",
        There “U” is the formatting part, see here for more.