(because we want here an independent script so we don't use the Joomla Framework version)
- copy the code and paste it in your file
Customize your **Google Sheet** script on your website. In your file adapt the following variables
- `$csvUrl` with the url we just got from Google Sheets
- `$baseUrl`. In my case
- I replace
- `'app-001' => 'https://app-001.example.org',` by
- `'app-001' => 'https://api.joomlacustomfields.org',` (beware, without the trailing slash!)
- I delete the lines with `'app-002'` and `'app-003'` because I want to import only one 1 website, not on 3 (or more) like the script allows
- `$token`. In my case I replace
- `'app-001' => 'yourapp001token',` by
- `'app-001' => 'c2hhMjU2OjI3NDpmOGMyNGIyMmI4ZTI0YzhlN2VhMGI1YmI2MTk5ODdiODViZWIwYjBhMTkwYzYxMmZkMDEzYWUxNzg5MmE2YzNm',`
- I delete the lines with `'app-002'` and `'app-003'` because I want to import only one 1 website, not on 3 (or more) like the script allows

#### Distant CSV file of local CSV file
In the final version of the script, right next to the `$csvUrl` parameter there is a `$isLocal` parameter :
`// Public url of the sample csv used in this example (CHANGE WITH YOUR OWN CSV URL OR LOCAL CSV FILE)`
`$isLocal = false;`
If you set you set this parameter to `true` instead of `false` then `$csvUrl` will be ignored and the following file mentioned a few lines after will be used:
`$localCsvFile = __DIR__ . '/sample-data.csv';`
Of course, you could adapt this file name and even folder, for example:
`$localCsvFile = __DIR__ . '/myfiles/marc.csv';`
Beware: if you get the following error message, it could simply be that your CSV file is not accessible (for example blocked by some .htaccess rule and/or by Admin Tools):
`Error message: Syntax error, Error code line: 478, Error CSV Line:__`, that line in the script being actually `$decodedJsonOutput = json_decode($combinedHttpResponse[$dataCurrentCSVline], false, 512, JSON_THROW_ON_ERROR);`
In my own case, adding an exception in the .htaccess maker for `marc.csv` was not enough: I had to temporarily disable Admin Tools in order to have the script work (I have not figured out yet which Option triggers that behaviour)
##### Allowing the upload of a CSV file in Joomla's Media Manager
In order to allow the upload of a CSV file in Joomla directly from the interface of the Media Manager (without using FTP for example)
- go to Media Manager > Options > Legal MIME type
- add `text/csv` in the list (note that the values are separated by a comma: `,`)
Personally, instead of adding my CSV files in the `images` folder, I created another folder at the root (let's say `csv`) and then go to the plugin `FileSystem - Local` where you can add that folder... which will then become visible in the Media Manager.
##### Mmmh, possible issue with Google Sheets since October 2023
[ added in October 2023 ]
Strangely for some reasons now it seems that calling directly the link to the Google Sheet would not work any more (you get some Rrror message like "First line MUST NOT be empty. It is the header"... which is what you get also if you put a wrong link to a local CSV file). I still have to investigate.
But anyways, since the script also work with Local files you can simply do the following:
- in Google Sheets you go to File > Download > CSV
- then you upload the file to your website (naming it after the name you have chosen in the script, see above)
If you have the opportunity to help me investigating this issue, please contact me! 🙂
#### Execute your script
Simply execute your script as already explained above.
Normally this script should not necessarily display anything and just run in the background.
Still the script displays some feedback: this is clearly not necessary but allows to visually check that something indeed happened (and once I could see that some rows were not processed and could identify the cause in the Google Sheets for example).

**Beware**: I have already noted that Google Sheets sometimes take 1 minute or so before actually updating the CSV version (even if other users of the Google Sheet see your changes "live"). So if after executing your script you see no difference, simply wait 1 minute and relaunch it
#### Go back to or refresh the Articles Manager
When opening the Article Manager, we can indeed check that
- new articles have been created. Tadam!

And when opening any of them, we can also see that everything is there
- introtext of the article
- link / description / class / caption for Intro Image and Full Image
- urla, urlb, urlc
Note:
- in this case, for the Intro Image and the Full Image we simply put an link to an external image in the Google Sheets
- in real life, one would probably want
- either to use Joomla's Media Manager to select the images
- or use something more powerful than Google Sheets, like AirTable which allows to put images in a "cell" (see the AirTable script which is even capable of physically copying the Airtable images locally to the website)


#### If you want to Update your articles later on
You have probably noted that the first column in the Google Sheet was `id`, being of course the ID for each article.
Actually we wanted one single script which works both to Create and to Update Articles.
But how to make the script "smart" enough for that?
- if the `id` is 0 then the script will Create an article
- if the `id`is any other number, it will Update the article having the corresponding ID
So at this point, if there is a chance that I execute again this script in the future, I don't want to re-create the already existing articles.
Therefore, in my Google Sheet
- I put manually the `id` of each already created article
- and if I wish to create new articles next time I run the script, I can also do it by giving them the `id` 0
- and so on each time I run the script
Illustration with my adapted Google Sheet where
- I change the ID, the Title and the Alias for the first 3 articles
- I add a new row to create a new article

And the result in the Articles Manager after running the script again:

Obviously in your Google Sheets you can change the value of **any** field.
Example: language is set on `*` (meaning all languages since it is the way it is encoded in the database) but you could specify a language like `fr-FR`
#### Two rounds to process
The script runs two loops:
- first it it creates all the article it is asked to create
- but if the required alias is already taken it cannot create the article
- then it remembers that
- and once the first loop is finished it makes a second loop in order to create those articles, by adding a random number to the required alias (in the code see the section // Handle errors and retries)
#### Other smart features
Note that the script has also been made as "smart" as possible for different aspects. Examples:
- if there is an error for a given row, the script will simply skip that row but go on with the next ones. Examples
- there is a Custom Field of type Link but in the corresponding cell the User has types Text or types an email address `test@test.com`but forgets to mention the protocol `mailto:`)
- some required data are missing
- as you might know, in a given Category an alias can only be given once to an Article
- so if a certain alias is already given, the script will add a random number to the proposed alias so that it can still be processed/created. Illustration:

### Advanced example
The following steps are not necessary of course: it only applies if you intend to use the script for example
- to import other native Fields like `publish_up`, `publish_down`, `featured_up`, `featured_down` (to find the right name for these fields, simply look in the database at the table columns...)
- to import Custom Fields
#### featured_up and featured_down
Relatively recently, Joomla added 2 new fields in the Article form:
- `featured_up`
- `featured_down`
So it means that you can also use that Joomla's API (and this script) in order to import those fields, even though they are not in the `content` table but in the `content_frontpage` table!
If you do it via the script, just don't forget to add `featured_up` and/or `featured_down` in the list of Fields that are to be synchronized...
Pay attention: apparently if from the work via Joomla's interface, those fields will be emptied (even if you fill them in)
- if you Save the Article *without* having set `Featured` to `Yes`
- if you change the Featured/Unfeatured option by clicking on the icon from the Articles Manager
So obviously if you use Joomla's API the same thing happens: you have to have a column `featured` set to `1` otherwise your columns `featured_up` and/or `featured_down` will just remain empty in Joomla even if you had filled in values in your Sheet.
#### Create Custom Fields in Joomla
Let's suppose we create a website for a Rock band. It would be much easier for the musicians to add their new concerts simply in a Google Sheets than to lean how to use a CMS.
Those concerts would then be easily imported and/or updated in the website.
So let's create a new Category `Concerts` and assign to it the 3 following Custom Fields:
- Date and Time: CF of Type Calendar with name `date-and-time`
- Venue: CF of Type Text with name `venue`
- Link to Event: CF of Type URL with name `link-to-event`



#### Adapt the Google Sheet
Since we create a new Category ("Concert" with ID 8), let us change the value of the `catid`column from 2 to 8 in the Google Sheet.
Let us also create the following columns in the Google Sheet:
- `publish_up`, `publish_down`, `featured_up`, `featured_down`
- `date-and-time`, `venue`, `link-to-event`
Note: when you type date, they should have the following format: `2022-11-23 20:00:00` (and visibly it imports dates in the real TimeZone of your website, as if you were typing them from Joomla's backend)
Here is an example with some values:

#### Adapt the script
In your script
- add the custom fields by changing
- `$customFieldKeys = [];` into
- `$customFieldKeys = ['date-and-time','venue','link-to-event'];`

- and add the following block inside the `$defaultKeys` array:
```
'publish_up',
'publish_down',
'featured_up',
'featured_down',
```

#### Go back to or refresh the Articles Manager
Tadam!
Our Categories have indeed been Updated:

Our Custom Fields have indeed been Updated:

Our other native Fields have indeed been Updated:

### Special fields like Images or Custom Fields or Type Subform or URLs
Some special fields entails "multiple values". So how to handle this?
Suppose you want to import an image or a Custom Field of Type Subform.
As you might be aware, in the database these fields are saved in **json format**.
So what should we type in our Google Sheet cell ? The easiest way is to save a real Article on the website and see in the database what the corresponding json is.
Note that we don't need in the Google Sheet to "escape the `/` character". With other words we simply type `/` and not `\/`
Example for **Image** (which includes the Intro Image and the Full Image, together with their ALT, Caption etc):
`{"image_intro":"images/test.jpg","image_intro_alt":"","float_intro":"","image_intro_caption":"","image_fulltext":"images/test.jpg","image_fulltext_alt":"","float_fulltext":"","image_fulltext_caption":""}`
Example for a **Custom Field of Type Subform** having in this case 2 Custom Fields (field2 and field7) and 3 values (row0, row1, row2) - note: it also accepts HTML tags but I can't paste them here in the presentation:
`{"row0":{"field2":1410,"field1":"This an article summary 1 for this dessert. Short & Sweet!", "field7": "What's up Super Joomlers! Alex here...Proud to be a joomler. Nowadays focusing on Joomla! 4.x Web Services Apis."}, "row1":{"field2":1410,"field1":"This an article summary 2 for this dessert. Short & Sweet!", "field7": "What's up Super Joomlers! Alex here... Proud to be a joomler. Nowadays focusing on Joomla! 4.x Web Services Apis."}, "row2":{"field2":1410,"field1":"This an article summary 3 for this dessert. Short & Sweet! ", "field7": "What's up Super Joomlers! Alex here... Proud to be a joomler. Nowadays focusing on Joomla! 4.x Web Services Apis."}}`
Example for the **urls Field** (those URL A, URL B and URL C which are native in Joomla):
`{"urla":"https://alexandree.io","urlatext":"Website","targeta":"","urlb":"https://github.com/alexandreelise","urlbtext":"Github","targetb":"","urlc":"https://twitter.com/mralexandrelise","urlctext":"Twitter","targetc":""}`
`Note: my Editor is tweaking my code snippets here. Of course all the " are regular double quotes (and not italic). And the Github icon is also added by the Editor`
### Fields with potentially multiple values like Custom Fields of Type List or Checkbox
Suppose you have a Custom Field of Type List or Checkbox. For those CF
- there is typically an Option to allow or forbid Multiple Values
- when you create your proposed options, for each of them you specify
- a Text (ie what will be displayed in the front-end and in the back-end)
- a Value (ie what is written in the database)
In that case
- if don't have Multiple Values
- in the Google Sheet you should simply type the unique Value (example: `chocolate`)
- if you have Mutiple Values
- in the Google Sheet you should then type `{"0":"fries","1":"chocolate","2":"beer"}` (without spaces) if the 3 values that I want are fries, chocolate and beer
Note: when you want to have multiple values in a CF, you typically choose between a CF of Type Checkbox and a CF of Type List
- when importing multiple values to a CF of Type Checkbox, everything runs fine
- when importing multiple values to a CF of Type List
- apparently at the moment the script might throw the following message `Cannot use object of type stdClass as array`
- but this does not prevent the script from executing and the content from being imported
- this problem could be related to this and . Please contribute!
### Fields with potentially multiple values like Custom Field of Type Articles Field by Regular Labs
Articles Fields by Regular Labs is a powerful Type of Custom Field allowing to select other Articles:
A good example : for a Library website you have typically have a Category "Books" and a Category "Authors". You could then link each Book Article to one or several Author Article(s).
If you have multiple values, I have tested succesfully the following 2 methods (let's suppose we want to link to Articles having ID 12 and 13):
1. in the Google Sheet, type `12,13` then Synchronize. After that Edit the Article in the Backend (the 2 values do appear there but are not yet correctly saved in the database) and Save it
2. in the Google Sheet, type directly the values in JSON-format, ie `{"0":"12","1":"13"}` (without spaces), then Synchronise
### Formula in Google Sheet to transform comma-separated values into the desired JSON
[ added on 30.03.2023 ]
Suppose you have multiple values on the Google Sheet in the form of comma-separated values `12,Se,Lan,Dis`.
In order to import them we need to transform them in JSON-format as explained above: `{"0":"12","1":"Se","2":"Lan","3":"Dis"}` (without spaces)
Let's see how to achieve this in a few steps, with a Custom Formula.
#### Apps Scripts
In Google Sheets, go to Extensions > Apps Scripts
Note: if you get a 404 error after a message "too many directions", it is because Google does not properly manage its redirections when you are logged in simultanously to several Google Accounts. In that case, two options:
- log out from all other Google accounts
- or simply open your Google Sheet in Private/Incognito mode in your browser
In the Apps Scripts interface
- paste the following function
- Rename the project (on the top left)
- click on the Save Project icon
```JS
/**
* Transforms a comma-separated list into indexed JSON in order to import multiple values of a Custom Fields into the website
*/
function CREATEJSON(input) {
if (input) {
let result = {};
let key = 0;
input.split(',')
.forEach(item => {
let val = item;
result[key] = val;
key = key + 1;
}); // we now have an array which is formatted as we wish
let myjson = JSON.stringify(result, null, ' '); // we transform the array in JSON format
myjson = myjson.replace(/\n/g,""); // we remove the line breaks \n globally g
myjson = myjson.replaceAll(" ",""); // we remove all spaces
return myjson;
} else return '';
}
```
What does this script do?
- if the source cell is empty we do nothing
- we split the comma-separated list in order to create an array
- we transform the array in JSON format
- we remove the line breaks `\n` globally `g`
- we remove all spaces
- if the source cell is empty we simply return '', namely nothing
Note: mmmh apparently this formula works when being in the Google Sheet itself... but it displays as `#NAME?` when *Publishing To Web* (be it in the browser or in CSV). So a temporary workaround would be to copy the result of the custom function/formula and to paste it as value/text in a new "extra column" in the Google Sheet.
**Please help if you find a better workaround for this!**
#### Formula in your Google Cell
In your Google Sheet you can now type the following : `CREATEJSON(A2)` where A2 is your source cell with `12,Se,Lan,Dis` for example.
Then you will see the JSON exactly as needed, ie `{"0":"12","1":"Se","2":"Lan","3":"Dis"}`.
### Formula in Google Sheets in order to transform a Title into an Alias or Slug
`=LOWER(REGEXREPLACE(REGEXREPLACE(REGEXREPLACE(REGEXREPLACE(REGEXREPLACE(REGEXREPLACE(REGEXREPLACE(REGEXREPLACE(REGEXREPLACE(TRIM(A1);"([àáâãäå])";"a");"([èéêë])";"e");"([ìíîï])";"i");"([òóôõöø])";"o");"([ùúûü])";"u");"([ç])";"c");"[^a-zA-Z0-9]+";"-");"-{2,}";"-");"^-+|-+$";""))`
Here’s how the formula works:
`TRIM(A1)` removes any leading or trailing spaces from the contents of cell A1
`REGEXREPLACE(TRIM(A1), "[^a-zA-Z0-9]+", "-")` replaces sequences of non-alphanumeric characters with hyphens
`REGEXREPLACE(REGEXREPLACE(TRIM(A1), "[^a-zA-Z0-9]+", "-"), "-{2,}", "-")` reduces sequences of multiple hyphens to a single hyphen
`REGEXREPLACE(REGEXREPLACE(REGEXREPLACE(TRIM(A1), "[^a-zA-Z0-9]+", "-"), "-{2,}", "-"), "^-+|-+$", "")` removes any hyphens at the start or end of the string
`REGEXREPLACE(REGEXREPLACE(REGEXREPLACE(REGEXREPLACE(REGEXREPLACE(TRIM(A1), "[^a-zA-Z0-9]+", "-"), "-{2,}", "-"), "^-+|-+$", ""), "([àáâãäå])", "a"), "([èéêë])", "e"), "([ìíîï])", "i"), "([òóôõöø])", "o"), "([ùúûü])", "u"))` replaces accented characters with their corresponding non-accented characters
## Performance
When I first started to play with this script I was importing 100 to 200 articles and it was going fine.
Then I decided to raise the bar for testing purposes and tried with some 2600 article.
I think that the script managed to create some 500 articles (having each 10 Custom Fields).
Indeed after a few minutes the script was throwing the following `Request Timeout` :
`This request takes too long to process, it is timed out by the server. If it should not be timed out, please contact administrator of this web site to increase 'Connection Timeout'.`
### Using the CLI to avoid Timout
Well, the best solution if you want to avoid any Timout is to launch the script from the Command Line (CLI).
See the corresponding section in the present presentation for more explanations
### Adapting server parameters to increase performance
Especially if you launch the script from the browser you might try to increase the following parameters on your hosting;
- max_execution_time
- max_input_time
- default_socket_timeout
- memory limit
This seems to have done the trick for me when launching the script from the browser. Indeed
- the script still displays a `Request Timeout` after 5 minutes
- but actually the process continues and I see that my articles are being further updated
### Disabling Versioning and Smart Search Indexation
If you need to increase performance even more (for example because you have a huge amount of Articles to import), I guess that the following actions would help:
- disabling Smart Search (to be more precise, the `Smart Search Content` and `Content Smart Search`. Maybe 1 of those 2 would be enough but I did not check their exact respective action)
- disabling `Versioning`
Indeed, every Article creation or update triggers the Smart Search and the Versioning which probably take extra resources before passing onto the next Article.
### Adjusting the parameters of the script
[ added on 30.03.2023, improved on 2023.04.25 ]
In the version of the script released end of March 2023, a new variable `$silent` has been added.
If set to `0` then the script will not display anything on the screen, which can only increase performance.
Of course, if you are still testing your customization of your script, you probably want to set it on `1` or `2` so that you have some feedback about what has happened.
Illustration below:
`// 0: hide both response result and key value pairs`
(gives a blank screen)
`// 1: show response result only`
(gives a summary for each processed row)

`// 2: show key value pairs only`
(gives for each row the details of all the processed columns, so custom fields included)

## Difference between using the API or using a direct SQL query in the database
One could think of importing / updating their Articles directly with a SQL query (based somehow on the same data in the Google Sheet).
Doing so would indeed directly modify the database... but it would not trigger all the Actions foreseen by Joomla (typically `onContentAfterSave`) such as
- Smart Search
- Versioning
So that if those Actions make sense for you then the API is better because it is really as if every Article would be manually edited in the backend.
But for *pure performance*, writing directly to the database can only be more performant.
## Troubleshooting
If no Article is created or updated when you launch the script, here is what you can do
1. check that everything is OK in the script (your API key, the link to the Google Sheet, the structure of the Google Sheet)
2. check the log:
- go to System > Global Configuration > tab Logging > enable `Log Almost Everything` + be sure that `Log Priorities` is set to `all`
- relaunch the script
- see /administrator/logs/everything.php
Note: if you want to make your life easier, install this little free plugin made by Yannick Gaultier, which allows to view/download/delete all logs files produced by Joomla directly from the backend:
Here are two practical examples of issues that I faced myself.
### Example 1 - some custom field is required
One day I encountered the following error message in /administrator/logs/everything.php
``#Fields: datetime priority clientip category message``
``2023-01-18T16:11:36+00:00 CRITICAL error Uncaught Throwable of type Tobscure\JsonApi\Exception\InvalidParameterException thrown with message "Field required: Event Category". Stack trace: #0 [ROOT]/libraries/src/MVC/Controller/ApiController.php(362): Joomla\CMS\MVC\Controller\ApiController->save()``
Actually the Custom Field "Event Category" was required but that Custom Field was empty in my Google Sheet.
So just like you could not Save an Article via the Interface in that case, you can't do it neither via the API...
### Example 2 - conflict caused by 3rd party extension
I have already had the case that an extension (CFI plugin in my case) would prevent the API from working, which I also discovered thanks to the Log file.
My workaround was to restrict the plugin to Super Users so that it would not interfere.
### Example 3 - special characters in the Google Sheet
The following one was quite tricky: somes Articles would be imported normally with the script... but some other ones would throw such an error :
`Fatal error: Uncaught ValueError: array_combine(): Argument #1 ($keys) and argument #2 ($values) must have the same number of elements in /home/my-sync-file.php:151 Stack trace: #0 /home/my-sync-file.php(151): array_combine(Array, Array) #1 /home/my-sync-file.php(194): {closure}('https://docs.go...', Array, Object(Closure)) #2 {main} thrown in /home/my-sync-file.php on line 151`
After some time, I realized that the users were using a kind of "curly single quote" instead of the "regular single quote"... and that "curly single quote" would be interpreted as the end of the field, causing a discrepancy :
- wrong: `l’oasis`
- correct: `l'oasis`
Similarly, the "compressed three dots":
- wrong: `…`
- correct: `...`
The following were working fine in my case :
- `"Rumba Rules“` (ie a kind of curly *double* quote)
- `« covid-19 »` (ie "guillemets français")
The only solution to those cases is to make a Search a Replace for the whole Google Sheet.
How to identify them easily: copy-paste your texte in Visual Studio Code (or some other pro editor or even maybe Nopedpad++): it highlights all the special characters like accented characters and those nasty cases.
### Example 4 - Break Line in the Google Sheet
When you type text in some cell of a Google Sheet, if you want to create a new line within that given cell, you can simply press `CTRL+ENTER`.
Apparently (I should test further to be 100% sure), having this at the end of a Field like Title which is pure text would cause the import/synchronization of the corresponding Article to fail.
For Custom Fields of Type Editor, this would be no problem - I have tested it - although you would loose the "break line" in Joomla, having then one unique long paragraph in the Article (want a solution for that? see the tip in the next section).
## Final tip
One final tip if you want to have multiple paragraphs in the cells of your Google Sheet :
If you want a formula to replace automatically all the "Break Lines" that users have typed in the cells of your Google Sheet by proper HTML tags like `` and `
`, you can simply use a Regular Expression (REGEX) like the following one, the "Bread Line" being identified by `\n` :
`=if(A1="";"";""®EXREPLACE(A1;"\n";"
")&"
")`
If you don't need a formula but simply need to "Search and Replace all" in your Google Sheets once and for all then simply enable the Regex Option when Searching `\n` (enable the Regex option) and replace by *nothing*.
## Using the Joomla API to Import and Update Articles directly from AirTable

You have probably already heard of AirTable:
If not, let's simplify it by saying that it is a big like a Google Sheet but really more powerful:
- its goal is not to make calculations
- since it is a real online database
In practice, more and more companies/associations are moving their data to Airtable so that they are interconnected and no more in silos.
Note:
- even if you use AirTable you could still use the CSV script above since it is possible to export an AirTable View to CSV. See indeed "Download a View to CSV":
- in their newsletter of Thursday 16-02-23, Airtable announces the end of the current system of API Key:
### Prepare Airtable
After creating a table in Airtable and before using it in our script, we need to make that table publicly available with the Airtable API
Details coming soon
### Prepare your Airtable script
See
Breaking news: now support for adding multiple downloaded and cached images as attachments
Details coming soon
### -
Details coming soon
## GraphQL API together with the Joomla API
Add or Edit Joomla! Articles Via API To Multiple Sites Chosen Randomly in from a predefined list Using Github GraphQL API
### Prepare your OMDb script
See
Details coming soon
### -
Details coming soon
## OMDb API together with the Joomla API
Note: OMDb is a Movie database
Turn your top 5 favorite movies into Joomla Articles thanks to OMDb API and Joomla API
Details coming soon
### Prepare your OMDb script
See
Details coming soon
### -
Details coming soon
## Using the Joomla API with Convert Forms by Tassos
Convert Forms 4 (released around end of February 2023) ships with new very interesting features like Tasks, including Webhooks.
It is nice because it allows for example visitors to create an article with a Form which is simpler than the native Joomla front-end article creation (which shows many fields on many tabs, even if you could always create your own override of edit.php in order to customize it).
### Small introduction as published by Tassos
One of the Apps included in the Convert Forms 4 Tasks new section is Webhooks.
A webhook allows you to automatically send real-time information from your form to some other service or tool outside of your Joomla site without writing a single line of code.
The documentation of the Webhooks App is now published, showing you how to create webhooks with Convert Forms. You can also find a detailed tutorial on utilizing Joomla's 4 Web Services API and creating a new
Article on a remote Joomla 4 site with the power of webhooks!
- Webhooks App:
- Working With Tasks:
- Download Convert Forms 4 BETA:
### My first experience
After creating easily a simple Article with Title & Text thanks to Convert Forms 4, I decided to try to go one step beyond and add Custom Fields:
- one of type Text. Just works out of the box!
- then one of type URL for an Email
- there of course the Article Creation would be refused by the API bc it expects "mailto:contact@domain.com" and not "contact@domain.com"
- so my little workaround to make it work was to type in the Task mailto:{field.5} (because in my case the Email field has ID 5)
## Other ways of importing content into Joomla Articles
The goal of this presentation was to show how to import content into your Joomla Articles with a simple & short independent script, using the Joomla API.
But of course, you might prefer to choose a ready-to-use extension. I surely don't know all of them, but if I were the first 3 coming to my mind:
- [ROCSVI by Roland Dalmulder](https://extensions.joomla.org/extension/migration-a-conversion/data-import-a-export/ro-csvi/) - paid
*clearly the most complete/universal tool to import/export content to/from Joomla*
- [JoomGrabber by Joomboost](https://extensions.joomla.org/extension/joomgrabber/) - paid
- [CFI by JoomLine](https://extensions.joomla.org/extension/authoring-a-content/custom-fields/cfi/) - free
## Thank you
**Peter Martin** for his excellent [presentation about the Joomla API](https://slides.db8.nl/md/22-joomla4-api.html) which allowed me to finally dive into this topic
**Alexandre Elisé** for all the interesting chats about the Joomla API a.o. and for taking the time to provide a [new script](https://github.com/alexandreelise/j4x-api-examples) every time I was having a new idea of improvement!
**Tim Davis** for having me on his [YouTube Channel](https://www.youtube.com/@Basicjoomla) for the first version of this presentation
**So many members of the Joomla Community** for being #jPositive
😉
## Get in touch
Any suggestion about this presentation?
Please feel free to contact me. I'll be happy to keep improving it 🙂
[Marc Dechèvre](https://www.facebook.com/marc.dechevre) | [woluweb](https://twitter.com/woluweb)
+32 474 37 13 12 | +32 2 772 58 69