# 3.3 Creating your own formatting functions

### Step 1 : Define a global function

Custom functions must be defined with the syntax `window.myFuncName = function(item) { ... }` rather than `function myFuncName(item){ ... }` , otherwise an error will be thrown. This syntax is needed to make the function globally available, so that it can be found by the extension.

### Step 2 : Construct your metadata template within the function

All formatting functions must do the following :

* The function must **take a single argument** - the item's data object, as returned by the Zotero Web API. [See here](https://gist.github.com/dstillman/f1030b9609aadc51ddec) for an official gist from the Zotero API docs, showing an example object returned for a single item.
* The function must **return a single array** - specifying the contents of the blocks that should be added to the item's page in Roam.&#x20;
  * **Each element** of the array will be processed as **a top-level Roam block** to be added to the item's Roam page. If the element is a *String* of text, the block will be childless. If the element is an *Object*, it can have children blocks (see [Nesting metadata](https://alix-lahuec.gitbook.io/zotero-roam/v0.5/customization/formatting/nesting-metadata)).
    * *String* elements will be added as top-level, childless blocks.&#x20;
    * *Object* elements will be processed recursively and support nested blocks.
  * The ordering of the blocks in Roam will reflect the ordering of the array.

To help you with writing your own functions, I've made an [Observable interactive notebook](https://observablehq.com/@greenmeen/zoteroroam-metadata-formatting), where you can try your hand at writing functions & using them to process your own Zotero data :

{% embed url="<https://observablehq.com/@greenmeen/zoteroroam-metadata-formatting>" %}

#### Default formatting function

```javascript
// By default, the extension uses the following function :
zoteroRoam.formatting.getItemMetadata = function(item){
    // Initialization of the array of blocks :
    let metadata = [];
    
    // Title of the item
    if (item.data.title) {
        metadata.push(`Title:: ${item.data.title}`)
    };
    // Creators of the item
    if (item.data.creators.length > 0) {
        metadata.push(`Author(s):: ${zoteroRoam.formatting.getCreators(item)}`) 
    };
    // Abstract for the item
    if (item.data.abstractNote) { 
        metadata.push(`Abstract:: ${item.data.abstractNote}`) 
    };
    // Type of the item
    if (item.data.itemType) {
        metadata.push(`Type:: [[${zoteroRoam.formatting.getItemType(item)}]]`) 
    };
    // Publication/Book title
    metadata.push(`Publication:: ${ item.data.publicationTitle || item.data.bookTitle || "" }`)
    // URL
    if (item.data.url) {
        metadata.push(`URL : ${item.data.url}`) 
    };
    // Date the item was added to Zotero
    if (item.data.dateAdded) {
        metadata.push(`Date Added:: ${zoteroRoam.utils.makeDNP(item.data.dateAdded, {brackets: true})}`) 
    };
    // Links to the item in Zotero (local + web links)
    metadata.push(`Zotero links:: ${zoteroRoam.formatting.getLocalLink(item)}, ${zoteroRoam.formatting.getWebLink(item)}`); // Local + Web links to the item
    // Tags attached to the item
    if (item.data.tags.length > 0) {
        metadata.push(`Tags:: ${zoteroRoam.formatting.getTags(item)}`)
    };
    
    // Requesting the item's PDF files + notes
    let children = zoteroRoam.formatting.getItemChildren(item, {pdf_as: "links", notes_as: "formatted", split_char: "\n"});
    // Links to the PDF files
    if(children.pdfItems){
        metadata.push(`PDF links : ${children.pdfItems.join(", ")}`);
    }
    // Contents of notes
    if(children.notes){
        let notesBlock = {string: `[[Notes]]`, children: []};
        notesBlock.children.push(...children.notes.flat(1));
        metadata.push(notesBlock);
    }

    return metadata; 
}
```

### Step 3 : Assign the function to item types

Custom functions can be assigned to item types using [funcmap](https://alix-lahuec.gitbook.io/zotero-roam/v0.5/customization/other/funcmap). You can assign a function to specific item types, or set it as the default formatting function.

*Assigning the `customPaperFormat` function to be used for conference papers and journal articles, and letting the extension handle other item types with its own defaults.*

```javascript
zoteroRoam_settings = {
    // dataRequests: {...},
    funcmap: {
        conferencePaper: "customPaperFormat",
        journalArticle: "customPaperFormat"
    }
}
```

*Using the `customPaperFormat` function for all item types*

```javascript
zoteroRoam_settings = {
    // dataRequests: {...},
    funcmap: {
        DEFAULT: "customPaperFormat"
    }
}
```

## Examples

Coming soon -- examples from the community will be posted here, as people share them !
