How Do I Do That? Zotero Integration Template Design

Hi everyone,

I want to do two things, but I don’t know how.

1 Import Author Surname

I would like to import only the surname of an author? I want to title the annotations the following way: Surname Year PageLabel.

{% for annotation in annotations -%}

[!{{AUTHOR-SURNAME}} {{date | format(“YYYY”)}} {{annotation.pageLabel}}|{{annotation.color}}]+

A shortcut would be the citekey. But I actually just want to find out how to only import the surname of the author.

2 Sorting annotations by color

I also want to know how I can import all purple annotations under heading A of the note and all the other annotations under heading B.

Heading A

purple annotation 1
purple annotation 2
purple annotation 3

Heading B

yellow annotation 1
yellow annotation 2
green annotation 1
yellow annotation 3
blue annotation 1

Can anybody help me with this? :slight_smile: I would be very grateful, thank you a lot! :pray:

Have you looked at Zotero Integration’s data explorer? It’s an essential tool for templating

Thank you for your response, Feralflora! :blush:
Okay, so after a bit of searching I found out what this data explorer is (not a plugin as I initially thought :joy:) I examined some literature entries that I have already imported into obsidian. And under the section authors there is always the first and last name. Data explorer show’s me for example:

authors “Katharina Kinzel”


authors “Georg Kneer, Armin Nassehi”

But I couldn’t find a property in the data explorer view that was called First Name or Last Name.
What can I do with that now? Is there still a way to simply import the last name?

authors is a pre-formatted list (a text string). To get the raw data where you can pick just the last name, you need to access it from the creators array. In creators, the first and last name are stored separately as keys in a creator object, along with the creatorType.

To simply get the last name of the first author, you can get it from {{creators[0].lastName}}. However, since creators can also be stored with a single name (for example in the case of organizations), it’s best to check if the creators has a {{}} or {{creator.lastName}}.

:information_source: Tip

You can right-click things in the Data explorer to copy their template path.


However, this won’t give you for-loops and conditionals, as needed to do something for every creator, for example, or to only access creators of the author type.

Creating a formatted citation in the APA 7th citation style

Rather than always accessing only the first author, you could use the following macro to construct a formatted citation in the APA style (or another style, if you adjust it):

{# This macro formats APA citations #}
{% macro citationFormatter() -%}
	{%- if creators -%}
	    {%- set citation = creators[0].lastName %}
		{%- if creators|length == 2 -%} 
			{% set citation = citation + " & " + creators[1].lastName %}
		{%- endif -%}
		{%- if creators|length > 2 -%} 
			{% set citation = citation + " et al." %}
		{%- endif -%}
	{%- endif -%}
    {%- if date -%} 
		{% set citation = citation + ", " + date | format("YYYY") -%}
	{%- endif -%}
{%- endmacro %}

Which you then use as follows:

{# Assign the result of citationFormatter to a variable called citation #}
{% set citation = citationFormatter() %}

{# Output the citation as needed #}

{% for annotation in annotations -%}

[!note|{{annotation.color}}]+ {{citation}} {{annotation.pageLabel}}

{# The rest of your annotation formatting #}
{% endfor %}

Saving creators to the properties

Another useful example of how to access and format data from creators:

{% for creator in creators %}
	{%- if -%}
		- "[[{{}}]]"
	{%- else -%}
		- "[[{{creator.firstName}} {{creator.lastName}}]]"
	{%- endif %}
{% endfor -%}

Or if you want to group creators by creator type, split the creatorType so it’s not in camel case, and make the property singular or plural as needed:

{%- set camelRegex = r/([a-z])([A-Z])/g %}
{%- for type, creators in creators | groupby("creatorType") %} 
{% if creators.length > 1 %}{{type | replace(camelRegex, "$1 $2") | lower | trim}}s:{%- for creator in creators %}{% if %}
- {{}}{% else%}
- {{creator.firstName}} {{creator.lastName}} {% endif %}{%- endfor %} {% else -%}
{{type | replace(camelRegex, "$1-$2") | lower | trim}}:{%- for creator in creators %}{% if %} "{{}}"{% else%} "{{creator.firstName}} {{creator.lastName}}"{% endif -%}{%- endfor -%}{% endif -%}{% endfor %}

This latter example gives you something like:

author: John Doe
- Jane Doe
- Adam Smith
1 Like

Wow, thank you so much for this extensive explanation and instruction! I’ve learned a lot so far :smiley:
One last question: Where do I put this macro? Do I have to paste it into a CSL file that I have installed in Zotero and which I then choose in Zotero Integration?

You’re welcome!

No, this is Nunjucks templating code for your Zotero Integration template. The easiest thing is to just include it directly in your main template.

But if you prefer more modularity, and keeping some of the formatting logic hidden, you can import the macro from another template file.

Let’s say the macro template file, which contains the citationFormatter macro, is called “ZI macros”. In that case, you can import it and use it in your main template like so:

{%- import "[[ZI Macros]]" as zi -%}
{% set citation = zi.citationFormatter() %}


I’m wondering where this thought came from? To be clear, CSL files have no relation to how your Zotero Intergration literature notes are formatted, other than dictating the format of the {{bibliography}} variable.

It actually just came from my cluelessness about programming :smiley: I actually come from the group of end users who have nothing to do with programming, but have discovered a great software that is incredibly useful. And because Obsidian is a software with large and now essential community work, it doesn’t take long to realize that templates are useful things. And all of a sudden you watch a tutorial on YT and you get scared because curly brackets and “code” appear. But I’m interested in learning as much as possible. And the questions that I post here simply come from the fact that I now understand a little bit of it and then a design idea of my own comes to mind. But without the know-how to implement the idea (I can only manage small steps). When you replied, I actually had to google what a macro exactly is :joy: Now you know the story! :blush:

1 Like

Right, it’s easy to forget that the jargon I use is not universally familiar. Sorry about that. In this case, I recommend having the Nunjucks templating docs handy: Nunjucks

In Nunjucks, a macro is just a reusable chunk of code that does some content formatting task(s) for us - in this case, taking available Zotero item metadata and formatting it into a citation. A macro is what would be called a function in most other programming languages.

1 Like

What I have now is a template which has your macro inside and then the following part:


{% set citation = citationFormatter() %}
{% for annotation in annotations -%}
{% if annotation.color == "#e56eee" %}
>*{{citation}}, {{shortTitle if shortTitle else title}}, p. {{annotation.pageLabel}}*
>{% if annotation.annotatedText -%}„{{annotation.annotatedText}}“([{{annotation.pageLabel}}](zotero://open-pdf/library/items/{{annotation.attachment.itemKey}}?page={{}}&annotation={{}})){% endif %}{% if annotation.imageRelativePath -%}![{{annotation.imageRelativePath}}]{%- endif %}
{% endif %}
{% endfor %}

It actually works and it pastes only the magenta annotations. But the issue is that it also creates empty lines between all the callout blocks. Sometimes only 3 or 4 empty lines but then also 8 or 9 empty lines between the blocks. Why does it do that? Maybe the gaps are bigger when there are more non-magenta annotations between two blocks of magenta annotations. But I don’t know how to change that.
I’ve tried the whitespace control after looking through the documentation you’ve sent me :blush: But that doesn’t seem to do it.

PS: I could put shortTitle inside the macro, but so far I haven’t had the time to do that. :sweat_smile:

1 Like

Congratulations on getting this far, looking good so far. For outputting a heading, see: loop.first. which you can use to output the heading for purple annotations only once.

{% if annotation.color == "#e56eee" and loop.first %}

## My purple heading

{% endif %}

I see fields without any whitespace control. Here’s what I do. Open the Data explorer and preview the template that you are editing (select the template from the dropdown that says “Preview import format”). Then, with the preview open, let loose with whitespace control until things start to get too mushed. Then, back off little by little until you find the sweet spot.

1 Like

I did it! Another problem solved! :partying_face: “Preview import format” was also an extremely helpful tip! Here are the results:

Before whitespace control:

After whitespace control:

Thank you so much for your support, I’ve learned a lot! :pray:
Now, off to more adventures and problems! Already facing some new :joy: I guess it never ends :sweat_smile:

1 Like

Hehe, I guess so. Mine keeps improving, little by little. Maybe we’ll get there someday, or change our attitude and “satisfice”.

Feel free to open new topics for further issues, and make sure to check out the showcase thread here:

You’re welcome, I’m glad to hear that! With the potential of the Data explorer unleashed, who knows what it will amount to :wink:

1 Like