Guide ·
SEO for a software product in Türkiye: what we do on our Turkish sites
Basalt Studio runs three sites in Turkish: Göçmeden, a board of remote jobs open to people in Türkiye, KahveDrop, a catalogue of Turkish specialty coffee, and Kaç Papel, a price-guessing game. Here is what we do on them for search and AI answers, a terminal check for each step, and what we cannot tell you yet.
Why it differs
Turkish searches are not English searches in translation
People type Turkish with and without its letters. They ask about Turkish tax, payments and prices, which an English page does not answer. And the sources AI answers cite for Turkish questions are often Turkish sites. A software product entering Türkiye with a translated English site misses all three.
Before you start
Set your address once
The checks use curl, grep, sed, awk and perl, which come with macOS and most Linux systems, and work the same in zsh and bash. Set your site’s address once, without a slash at the end. Steps that check one page set that page’s address too.
site=https://example.com
The steps
Six steps on our Turkish sites
Each step has what to do, a check, and what we did on Göçmeden, KahveDrop or Kaç Papel, with the date.
Research keywords in Turkish, with and without Turkish letters
- Do
Start from what Turkish buyers type, not from a translation of your English keywords. Many type without Turkish letters: ı as i, ş as s, ğ as g, ç as c, ö as o, ü as u. Collect both spellings of each phrase, and watch for short words that mean something else in English: “is” typed for “iş” (job) pulls in “island”.
- Check
Google’s autocomplete shows what people type. This prints its first five suggestions for a phrase in both spellings. The address is not an official API and can change, so treat it as a quick look, not as keyword data.
for q in "remote iş" "remote is"; do echo "== $q" curl -s -G https://suggestqueries.google.com/complete/search -d client=firefox -d hl=tr --data-urlencode "q=$q" | perl -CO -MJSON::PP -ne 'print "$_\n" for @{ decode_json($_)->[1] }' | head -5 done- On our sites
Run from Türkiye on 21 Oct 2026, it printed:
== remote iş remote iş ilanları remote işler remote iş ne demek remote iş ilanları istanbul remote iş ilanları türkçe == remote is remote is ilanları türkiye remote iş ilanları remote island remote iş remote istanbulGöçmeden, our board of remote jobs open to people in Türkiye, shows the same habit in its first Search Console data, read on 20 Oct: its top queries included “yazilim muhendisi is ilani” and “avukat is ilani”, typed without ı, ü or ş. Its page addresses use plain letters, such as
/rehber/deel-ile-turkiyeden-calismak/, and its titles keep the Turkish ones.
Write the Turkish pages in Turkish, for Turkish questions
- Do
Write each page for the question a Turkish reader has, which is often not the one your English page answers. A developer in Türkiye paid by a foreign company asks how to invoice it and what Deel means for their taxes, not what Deel is. Have a native speaker write or edit every page, and mark it as Turkish:
lang="tr"on the html element and"inLanguage": "tr"in the structured data.- Check
Set the page’s address in
page. You wantlang="tr"once andinLanguage"tr"in the JSON-LD.curl -s "$page" | grep -o -E '<html[^>]* lang="[^"]*"|"inLanguage": ?"[^"]*"' | sed -E 's/<html.* lang=/lang=/' | sort | uniq -c- On our sites
Göçmeden’s guides are written in Turkish for those questions: Deel ile Türkiye'den çalışmak (18 Oct) and Yurt dışı şirkete fatura kesmek (19 Oct). On 21 Oct both showed “Son güncelleme: 21 Ekim 2026” (last updated). Kaç Papel, our Turkish price game, got its first structured data on 19 Oct (kacpapel PR #12); before that, 0 of 6 sampled pages had any. Run on kacpapel.app on 21 Oct, the command printed:
2 "inLanguage":"tr" 1 lang="tr"
Link the language versions with hreflang: tr and x-default
- Do
Each page says which language it is in, and where its other versions are, with
<link rel="alternate" hreflang="…">in the head. A Turkish page lists itself astr. If it has an English version, both pages list both, each pointing at the other.x-defaultnames the version for everyone else. A site only in Turkish can still declaretrandx-defaulton every page.- Check
Set your site’s address in
site, without a slash at the end. The first command prints the home page’s hreflang links. The loop fetches every page in the sitemap and counts the pages by the hreflang values they carry; on a few hundred pages it takes a few minutes.curl -s "$site/" | grep -o '<link rel="alternate" hreflang="[^"]*" href="[^"]*"' curl -s "$site/sitemap.xml" | grep -o '<loc>[^<]*' | sed 's/<loc>//' | while read -r u; do curl -s "$u" | grep -o -E 'hreflang="(tr|x-default)"' | sort -u | tr '\n' ' '; echo done | sort | uniq -c- On our sites
Göçmeden is only in Turkish. It got
trandx-defaulton every page on 19 Oct (gocmeden PR #43). On 21 Oct, with 295 pages in its sitemap, the commands printed:<link rel="alternate" hreflang="tr" href="https://gocmeden.hellobasalt.dev/" <link rel="alternate" hreflang="x-default" href="https://gocmeden.hellobasalt.dev/" 295 hreflang="tr" hreflang="x-default"
Keep descriptions under 160 characters, Turkish words included
- Do
Turkish words run long, and descriptions built from a job post or a product text run longer. Write the important ones by hand, under 160 characters, and clamp the rest at build time as a safety net.
- Check
This prints how many pages in the sitemap have a description over 160 characters, counted as characters, not bytes, so ş and ğ count once.
curl -s "$site/sitemap.xml" | grep -o '<loc>[^<]*' | sed 's/<loc>//' | while read -r u; do curl -s "$u" | perl -CS -0777 -ne '($d) = /<meta\s+name="description"\s+content="([^"]*)"/is; $d =~ s/"/"/g; $d =~ s/&/&/g; print length($d), "\n"' done | awk '$1 > 160 { n++ } $1 > m { m = $1 } END { print NR, "pages,", n + 0, "over 160, longest", m }'- On our sites
Göçmeden has clamped the descriptions of its job pages to 160 characters at build since 19 Oct (gocmeden PR #42). In the sample checked that day, 9 descriptions were too long before the change and 0 after. Its clamp cuts at exactly 160, mid-word when it has to; a cut at the last whole word reads better. On 21 Oct the loop printed:
295 pages, 0 over 160, longest 160
Find the Turkish sites AI answers cite, and be listed there
- Do
Ask your Turkish customers’ questions in Turkish, in the assistants they use, and note which sites the answers cite: Turkish career sites, price comparison sites, forums and directories. Those are the listings worth having, ahead of anything in English.
- Check
Use the method in the AI answer check, in Turkish: a log of who is named and which domains are cited, then a count of the domains.
- On our sites
Our 19 Oct check asked one customer question for each Basalt product, through web search as a stand-in for the assistants that search. Only 1 of the 9 answers named our product, and it was not one of the Turkish ones. The sources cited across the nine answers included techcareer.net and jobgether.com, both job sites, and cimri.com, a Turkish price comparison site. None of our Turkish sites was named.
Publish a numbers page others can cite
- Do
A page of numbers only you have, in Turkish, updated on a schedule and dated on the page, with the same numbers in a JSON file under an open licence. Describe it with a Dataset block whose creator and publisher are Organizations; the structured data guide has a check for that. People writing about your market need a source for a number. Make yours the one that is easy to cite.
- Check
The loop prints the date line of each page; the last two lines should print 200 and a JSON content type.
for page in https://gocmeden.hellobasalt.dev/rakamlar/ https://kahve.hellobasalt.dev/veri; do curl -s "$page" | perl -0777 -pe 's/<(script|style)\b.*?<\/\1>//gis; s/<[^>]+>//g' | grep -o -m 1 -E 'Son güncelleme: [0-9]+ [^ ]+ 20[0-9]{2}' done curl -s -o /dev/null -w '%{http_code} %{content_type}\n' https://gocmeden.hellobasalt.dev/veri/v1/stats.json curl -s -o /dev/null -w '%{http_code} %{content_type}\n' https://kahve.hellobasalt.dev/veri/v1/ozet.json- On our sites
Göçmeden’s rakamlar (numbers) page went live on 19 Oct (gocmeden PR #43), with
/veri/v1/stats.jsonunder CC BY 4.0. On 21 Oct its description read “bugün 156 remote ilan Türkiye'ye açık”: 156 remote jobs open to people in Türkiye that day. KahveDrop, our catalogue of Turkish specialty coffee, followed with /veri on 20 Oct (tr-coffee-db PR #10): 425 coffees from 39 roasters on 21 Oct, with/veri/v1/ozet.json. The same change put a dated line on 27 of its catalogue landing pages. On 21 Oct the commands printed:Son güncelleme: 21 Ekim 2026 Son güncelleme: 21 Ekim 2026 200 application/json 200 application/json
Results
What we cannot tell you yet
Whether these changes bring visitors. When we first read Search Console, on 20 Oct 2026, the hellobasalt.dev property had 32 Google impressions and 0 clicks over its 3-month range, with data only from 17 and 18 Oct. 29 of the 32 were Göçmeden’s. The changes above are days old. Their numbers go on the proof page at 2, 4 and 8 weeks after each change, bad weeks included.