Instagram: Gibt es die perfekte Uhrzeit zum Posten von Beiträgen?

Björn Tantau betrieb heute Aufklärungsarbeit(en) für die interessierten Laien in Form eines Artikels. Dieser ist soweit okay, bezieht viele externe Erkenntnisse ein und er demonstriert einige Zahlen auf Basis seines Accounts. Leider lassen die schriftlichen Gedankengänge auch viele Fragen offen und ich bemängele da u.a. die primäre Einbindung von Studienergebniszusammenfassungen in Form der typischen Infografiken und die relativ kritiklose Wiedergabe der allgemeingültigen Erkenntnisse. Vielleicht bin ich auch zu kritisch, erkenne aber auch an, dass der Tantau-Artikel halt dessen Zielgruppe(n) nahezu perfekt abholt.

Genug der Textkritik und hin zur Tiefenanalyse.

Die Frage nach DEM perfekten Zeitpunkt einer Publikation kann natürlich Gegenstand extremster Grundsatzdiskussionen sein. Privat ist mir die Suche, die immerwährende und tiefergehende Suche nach DEM einen Zeitpunkt zwar wichtig, jedoch prägen entsprechende und extrem zeitraubende Aktivitäten nicht das tägliche Management der Accounts. Teilweise neige ich auch dazu, „bei Lust“ oder „bei Laune“ zu posten, weil eben abholbare Zielgruppen und deren Aktivitäten extrem schlecht kalkulierbar sind. Mal im Ernst: natürlich existieren Gedankenspiele zu Zeitfenster im Bereich der Mittagspause, der Frühstückspause, der sonstigen Pausen oder eben dem Feierabend. Das ist alles soweit logisch, nur sagt die Logik auch, dass man eben auch „nur“ im Nebel stochert, weil das Interaktionsverhalten auf Basis der „Erfahrungswerte“ oder „Beobachtungen“ schlichtweg unkalkulierbar bleibt.

Hausintern haben wir folgende Arbeitshypothesen aufgestellt bezüglich der Feststellbarkeit möglicher ‚idealer‘ Postzeitpunkte:

(a) Der ideale Postzeitraum ist ablesbar durch die Interaktionen NACH dem Posten.
(b) Der ideale Postzeitraum ist ablesbar durch aufkommende Trends und/oder Gesprächsthemen.
(c) Der ideale Postzeitraum ist ablesbar durch das Erfassen und Auswerten von Kommunikationen innerhalb von Filterblasen.

Die Rechercheansätze wurden hier
https://www.pontipix.de/instagram-tagsuche-tagbewertungen-und-tagbegutachtungen/
– Artikel zur Tagrecherche
– allgemeine Interpretationshinweise

und dort

https://www.pontipix.de/postzeitpunkte-bei-instagram/
– Grobskizzierung eines Auswertungsalgorithmus

beschrieben.

Fragen, Anregungen, Bemerkungen oder Anfragen? Gern per Kommentar, eMail oder Telefon.

Wie kann ich Trafficvolumina von völlig fremden Projekten analysieren? (Bit.ly-Variante)

Bei einem dieser szenetypischen Verkaufsvorträge aus dem Bereich „Influencer-Marketing“/“Social-Media-Marketing“ tauchte die Frage der Überprüfbarkeit(en) diverser Werthaltigkeitsprognosen auf. Während meiner Nachfragen und Gesprächsangebote wurde signalisiert, dass die Abgabe solcher Prognosen schwer sei und die Prognosen eher auf subjektiven Begriffen wie „zwischenmenschliche Kontakte zum Influencer“ und „Erfahrungen“ beruhen. Nun gebe ich mich mit Subjektivitäten nur ungern zufrieden und mache mich selbst auf die Suche nach Antworten.

Eine bei uns etablierte Prüfvariante basiert auf dem URL-Shortener „Bit.ly“ und dessen Analysevarianten, die offensichtlich vielen Dienstleister_innen / Analysebetreibenden gar nicht so bekannt sind.

Kurzer Zwischenabsatz: Was ist eigentlich ein URL-Shortener? Wikipedia schreibt dazu:

„Unter einem Kurz-URL-Dienst, engl. URL Shortener, versteht man einen Dienst, der für beliebige URLs existierender Webseiten eine zweite, alternative URL zur Verfügung stellt. Diese Alias-URL führt über eine HTTP-Weiterleitung zum Aufruf der ursprünglichen Webseite. Der auch short URL, URL alias oder Kurzlink genannte Alias besteht meist aus wenigen (ASCII-)Buchstaben oder Zahlen. Dies dient dazu, für unhandliche, große sowie problematische Sonderzeichen enthaltende URLs, kurze und unproblematische Aliase (besser zu merken, schneller einzugeben, …) bereitzustellen. Solche URLs finden sich vor allem bei Websites, die mit Datenbankvariablen operieren. Weit verbreitet ist die Nutzung von Kurz-URLs auch in Mikroblogging-Diensten und Status-Meldungen in sozialen Netzwerken, die beide nur eine begrenzte Anzahl von Zeichen pro Nachricht erlauben. Um die Weiterleitung von Kurzlinks anzuzeigen, ohne sie zu besuchen, können „Redirect Checker“ verwendet werden.“

(Quelle: https://de.wikipedia.org/wiki/Kurz-URL-Dienst)

Hier gibt es zwei Verfahren:

[Manuell]

Möchte man sich die Daten in einem schönen und logisch aufbereiteten Überblick anschauen, geht man so vor:
-> Schauen, ob ein Objekt mit einer Bit.ly-URL hinterlegt ist
-> Ergänzung der Bit.ly-URL mit einem „+“ und Übertrag in den Browser (Beispiel: https://bitly.com/2JJBUJC+)
Für erweiterte Daten (Ref, Land etc.) benötigt man einen Account auf Bit.ly, wo man nach Einloggen und Bestätigen an die gewünschten Informationen kommt.

[Technisch/Maschinell]

An der Stelle kommt der etwas kompliziertere Technikteil. Zur Erklärung: Nachfolgend zeige ich die interessanten Endpoints mit einer Durchnummerierung, welche wichtig für die Darstellung eines groben Algorithmuskonzeptes sein wird.

Um alle Funktionen nutzen zu können, benötigt die Anwenderin diesen Token. Den Code bekommt man, indem folgende Anleitung durchgeführt wird: „How do I find my OAuth access token?„. Nach der Tokenorganisation sollte man sich selbstverständlich mit den Abfragevolumina beschäftigen. Hier meine ich, dass 100 Abfragen je Minute ganz okay sind, jedoch definitiv nicht ausreichen, um bspw. gewaltige Systeme im Umfang von Zalando auch nur im Ansatz analysieren zu können. Das Problem löst man entspannt, indem man sich die gewünschte Menge an Accounts und Tokens besorgt. Die Tokens werden in einem solchen Fall in einer entsprechenden Liste gespeichert (Text, DB) und der Abfragealgorithmus „kann“ sich dort auch per Zufallsgenerator „bedienen“.

(1) [Basisfunktionen]
Ich nutze diese Endpoints gern für Gegenproben und allgemeine Recherchearbeiten.
https://api-ssl.bitly.com/v3/link/info?access_token=deintoken&link=bitlyurl
Die auslesbaren Informationen zeigen einen Fehlercode (bspw. Crawlingprobleme, „N/A“ usw.) und die Metriken „original_url“, „canonical_url“.

(2) [Auslesen der generierenden Accounts, „Encoders“]
https://api-ssl.bitly.com/v3/link/encoders?access_token=deintoken&link=bitlyurl
Die auslesbaren Informationen zeigen die Accounts, welche die analysierte URL bearbeitet/eingestellt hatten.

(3) [Auslesen der Querverweise inkl. Traffic]
Habe ich nun eine eindeutig identifizierbare URL vorliegen, interessiere ich mich selbstverständlich für die Beantwortung folgender Fragen:
(a) Wo befindet sich die aktive URL?
(b) Wieviel Traffic generiert die aktive URL über DEN identifizierten Linkspender?

Diese Informationen lassen sich über den folgenden „Endpoint“ Abrufen:
https://api-ssl.bitly.com/v3/link/referrers?access_token=deintoken&link=bitlyurl

Datenstruktur:
data->referrers[nr.]->referrer // -> Linkplatz
data->referrers[nr.]->click // -> Click über den Linkplatz

Eine alternative Variante ist über das Auslesen der verweisenden Domain machbar und logisch, sofern man sich nicht für den Deeplink innerhalb eines Projektes/einer Domain interessiert. Ich habe diesen Endpoint nie angebunden, weil primär die Unterseite der verweisenden Domain spannend ist
https://api-ssl.bitly.com/v3/link/referring_domains?access_token=deintoken&link=bitlyurl

(4)[Clickstatistiken, allgem.]
https://api-ssl.bitly.com/v3/link/clicks?access_token=deintoken&link=bitlyurl
Dieser Endpoint wirft nur die Clickanzahl zurück, die über den Link kommt.

(5)[Clickstatistiken, nach Ländern.]
https://api-ssl.bitly.com/v3/link/countries?access_token=deintoken&link=bitlyurl
Dieser Endpoint wirft nur die Clickanzahl zzgl. der Länder der Clickenden zurück. Hierbei handelt es sich um die Ländercodes. Diese müssten natürlich bei einer Softwareumsetzung in leicht verständliche Zeichenketten + Flaggen etc. umgewandelt werden.

Ein mögliches Umsetzungskonzept sieht so aus:
[1] Token besorgen
[2] Sitemap der Analyseprojekte besorgen UND zusammengefasste URLs extrahieren
[2.1] extrahierte URLs in geeignete Liste/Datenbank speichern
[2.2] Sitemapdownload/URLextract in eine Prozedure fassen
[3] Scraper
[3.1] Lade URL-Liste
[3.2]
for lfnr=0 to ende(URL_Liste) do
begin
//-> extrahiere Querverweise zzgl. Clicks
httpget+extract(3)
//-> extrahiere Clicks nach Ländern
httpget+extract(5)
end

Ich besprach u.a. dieses Konzept und eine konkrete Umsetzung 2015 beim Affiliatestammtisch (Leipzig) und ich bin mit der „hauseigenen“ Lösung soweit zufrieden.

Einige Performancedaten sind:

URL-Liste mit 100-5000 Einträgen
– Datenerfassungsdauer: ca. 1 Stunde

URL-Liste mit 5000-10.000 Einträgen
– Datenerfassungsdauer: ca. 1-2 Stunden

Die W&L-GbR-Lösung basiert derzeit (noch) auf die Datenspeicherung via CSV. Das liegt u.a. daran, dass ich erst sehr spät den Wert von „richtigen“ Datenbanken wie SQL & SQLite erkannt habe. Wie auch immer: Die Erfassung der o.g. Daten verlangt natürlich auch die Etablierung diverser Auswertungsansätze, weil man nicht aus purem „Selbstzweck“ diese Daten erfasst. Ich sehe folgende Szenarien, bei der die Bit.ly-Variante zum Einsatz kommen kann:

[Konkurrenzscreening]

Die typische „SEO-Denke“ geht (leider) immer davon aus, dass das Sichten via Datendienstleister (XOVI, Sistrix) und Backlinks/Backlinkstrukturen für die Marktbegutachtungsaktivitäten ausreicht. Das stimmt leider so nicht, denn diese Ansätze liefern keinerlei transparente Einblicke in mögliche Traffic- und Traffic-via-Zielgruppeninformationen. Hier rate ich schon seit 2011 zu einer projektbezogenen Einbindung einer „Nutzwertanalyse“. Die Analyse via Bit.ly-API kann bei dauerhaftem Monitoren komplexer Sitemaps eben genau aussagen, wann welche Trafficqualität über welche Social Media/Backlinks zum beobachteten Objekt kam und kommt.

[Influencermarketingbeurteilungen]
Bei dieser Variante kann man auf das umfangreiche Scrapen diverser Sitemaps verzichten und manuell die typischen Promotionslinks in den Scraper eintragen.
Ist die Erfassungsprozedure entsprechend konfiguriert, lassen sich VOR der Inanspruchname einer Influencermarketingagentur/Influenceraccounts Prognosen zu:
(a) Länderspezifische Trafficströme
(b) Clickstatistik/Zeiteinheit (Tag, Woche etc.)
(c) Weiterempfehlung des [Werbe]links, gezeigt durch „Streueffekt“
anstellen. Ich empfehle analog zu den allgemeinen Verkaufsargumenten der Sparte „Influencermarketing“ genau diese Gegenprüfvariante.

[Backlinkrecherchen und Backlinkaquise]

Diesen Ansatz hatte ich – zusammen mit Anne – bereits während den Arbeiten an den Projekten der Empora Fashion Group aufgestellt. Wenn man also bei schwierigen Projektlagen (damals: Mode, viele Produkte etc.) sich bewusst die Konkurrenz via Bit.ly-Analysen anschaut, lassen sich eben über den Ref-Endpoint plötzlich Linkspender identifizieren, welche durch die Zusammenführung mit den Clickzahlen Trafficvolumina versprechen können. Verlinkungen machen nur dann Sinn, wenn eben der gesetzte Link nicht primär im Sinne der „SEO-Denke“ wirkt, sondern Zielgruppen anspricht und via Gegenprobe auf Konkurrenzprojekte auch saubere Clickgestaltungen (Historie, Land etc.) quasi „verspricht“.

Weitere Gedanken, Ideen oder Austauschwunsch? Gerne via Kommentar, e-Mail oder Anfragen.

Wie kann ich interagierende Accounts mit Hilfe eines Instagrambugs auslesen?

In einer der letzten Vertriebs- und Verkaufsveranstaltung (Subthema: Erkennen und Bewerten von Accounts, Interaktionen usw.) wurde ich inspiriert, eine geeignete technische Lösung zu recherchieren, welche die Titelfrage beantwortet. Der Grund ist einfach: Durch die Beschneidung der Instagram-API ist die technische Erfassung o.g. Metriken schlichtweg nicht mehr möglich. Einen Ausweg bietet folgende Vorgehensweise:

[AbfrageURL]
https://www.instagram.com/[Accountname]/?__a=1

[Codekonzept]
lade_account_liste(datei,DB)
//-> Erfassen der Likenden
for l=0 to liste_ende do
begin
httpget(https://www.instagram.com/liste[l]/?__a=1
(1) extract(graphql->user->edge_owner_to_timeline_media->edges->[NrX]->node[X]->edge_media_preview_like->count)
(2) extract(graphql->user->edge_owner_to_timeline_media->edges->[NrX]->node[X]->edge_media_preview_like->edges->[NrY]->node[Y]->id)
(3) extract(graphql->user->edge_owner_to_timeline_media->edges->[NrX]->node[X]->edge_media_preview_like->edges->[NrY]->node[Y]->profile_pic_url)
(4) extract(graphql->user->edge_owner_to_timeline_media->edges->[NrX]->node[X]->edge_media_preview_like->edges->[NrY]->node[Y]->username)
end

[Erklärung]
„httpget“ = Ergebnis der Abfrage wird herunter geladen
„extract“ = Das Ergebnis der Abfrage wird nach der Variable durchsucht und die Inhalte werden im gewählten Format gespeichert.
„lade_account_liste“ = Die zu begutachtenden Accounts werden in Listenform (Textdatei, SQLTab etc.) in die Prozedur eingespielt.

Die Manuelle Sichtung der Ergebnisse kann man mit https://jsoneditoronline.org/ erledigen. Hier einfach die Abfrageurl https://www.instagram.com/[Accountname]/?__a=1 mit dem Accountnamen im Browser eintragen und das Resultat in den jsoneditor kopieren.

[Erklärung: Datensätze]
(1) Auslesen der aktuellen Likes als Zahl
(2) Auslesen des likenden Accounts in Form der InstagramID
(3) Auslesen der Profilbildurl des likenden Accounts
(4) Auslesen des likenden Accountnamens

[Fazit]
Ich bezeichne den begutachteten Erhebungsweg bewusst als „Bug“, da Instagram offziell das Erfassen dieser Datensätze im letzten API-Entwicklungsturnus geschlossen hatte. Nun mag man davon halten, was man möchte und ich sehe u.a. hier für mich den Beleg dafür, dass die geschlossenen Endpoints selbstverständlich nach wie vor aktiv sind. Vielleicht beschäftig sich Instagram mit der Bug-Bereinigung, vielleicht bleibt aber auch diese Abfragevariante „ewig“ offen. Die Sichtung des JSON-Codes zeigte mir, dass „leider“ nur eine begrenzte Anzahl an interagierenden Accounts auslesbar ist, aber auch dieses Problem lässt sich elegant über eine geeignete Timer-Variante lösen. Diese aktiviert im Prinzip im Sekundentakt den Scrapingvorgang und holt sich die gewünschten Datensätze ab, speichert und verarbeitet die Eintragungen. Hochfaszinierend ist in diesem Gedankenspiel die Metrik „Username“: Die Inhalte aus der Variable lassen sich in geeignete Listen übertragen und in das o.g. Grobkonzept einspielen. Über diesen Weg erfährt der wissensdurstige Dataminer alles aus dem Medienstream des Influenceraccounts / Accounts UND den Accounts, welche eben mit dem Hauptanalyseobjekt interagieren.

Hier setzt bei mir das kritische und hinterfragende Nachdenken an:
Welchen Wert haben umfangreiche Datenschutzerklärungen, wenn bspw. Social Media problemlos recherchierbare Lücken für die Datenerhebungen offen lassen?
Welchen Wert haben offzielle Ankündigungen und Umsetzungen zu API-Änderungen, gerade aus dem FB-Haus in Verbindung mit Cambridge Analytica?
Welchen Wert haben Äußerungen aus dem Hause Facebook bzgl. der Kontrolle der Datenzugriffe von Externen, wenn (a) dieser „Bug“ identifizierbar und (b) nutzbar ist?

Ich muss gestehen, dass ich einen gewaltigen Nutzen in diesen Datenerhebungsvarianten sehe. Natürlich habe ich über die Nutzbarmachung im Interesse der Wobus & Lehmann GbR nachgedacht, bin aber letztendlich davon abgekommen, weil mir derzeit kein sauberes Anonymisierungsverfahren bekannt ist. Ich finde es schade, dass die Influencer-Marketing-Agenturszene schweigt und keinerlei Analysen, Statements oder generell Worte zu dieser Datenproblematik veröffentlicht.

Wie kann ich Follower- und Abozahlen von beliebigen (offenen!) Accounts aus Instagram monitoren?

In einer der letzten Vertriebs- und Verkaufsveranstaltungen empfand ich Inspiration zur Recherche einer geeignenen technischen Lösung, welche die Titelfrage beantwortet. Der Grund ist einfach: durch die Beschneidung der Instagram-API ist die technische Erfassung o.g. Metriken schlichtweg nicht mehr möglich. Einen Ausweg bietet folgende Vorgehensweise:

[AbfrageURL]
https://www.instagram.com/[Accountname]/?__a=1

[Codekonzept]
lade_account_liste(datei,DB)
for l=0 to liste_ende do
begin
httpget(https://www.instagram.com/liste[l]/?__a=1
extract(graphql->user->edge_followed_by->count)
extract(graphql->user->edge_follow->count)
end

[Erklärung]
„httpget“ = Ergebnis der Abfrage wird herunter geladen
„extract“ = Das Ergebnis der Abfrage wird nach der Variable durchsucht und die Inhalte werden im gewählten Format gespeichert.
„lade_account_liste“ = Die, zu begutachtenden, Accounts werden in Listenform (Textdatei, SQLTab etc.) in die Prozedur eingespielt.

Die Umsetzung der technischen Lösung ist eigentlich relativ simpel via PHP, Delphi oder anderen Szenarien machbar. Ich würde, sofern ich Interesse hätte, hier einen zeitlichen Aufwand von maximal 1-2 Stunden inkl. Testen und Fehleranalyse einkalkulieren. Jedoch muss ich das Monitoren dieser Zahlen intern mit Anne ausdiskutieren, denn eigentlich berühren eventuelle Erfassungen natürlich auch aktuelle Datenschutzdiskussionen, denn: im Ergebnis der o.g. Abfrage befinden sich sämtliche Accountangaben aus dem Profil, die Historie der letzten Postings und auch (!) Auszüge der Likenden (also: ID, Username) auf den letzten Medien des analysierten Accounts. Hier stellt sich für mich auch die Frage, wie gut / praktikabel etc. der Einsatz der üblichen Instagramaccountbeobachtungswerkzeuge denn ist. Vielleicht werde ich das Thema etwas „entspannter“ betrachten, wenn ich eine saubere Codierungsfunktion gefunden oder erfunden habe.

[Update] Instafinal (Promowerkzeug für Instagramaccounts)

Anne informierte mich soeben, dass die Software „Instafinal“ nicht mehr die Account-IDs der hinterlegten Usernames via API extrahieren kann.

Eine Sichtung der (neuen) Endpointspezifikationen ergab auch, dass
https://api.instagram.com/v1/users/search?q=[username]&access_token=[token] inaktiv ist und die Konsquenzen sind:

-> Ein komplettes Screenen der Accountstreams ist nicht mehr via API möglich.
-> Das Analysieren von Interaktionsdaten, Likenden auf den Accountstreams ist via API nicht mehr möglich.

Ich lasse das Datenbankfeld „Account-ID“ vorerst in den Codes bestehen.

Hashtagdatenbanken: Änderungen an den Freigaben (Stand. 01.05.2018)

Im Zuge der API-Änderungen musste ich leider feststellen, dass das Datenbankpaket für 05-2018 fehlerhaft ist. Das hängt u.a. auch damit zusammen, dass besagte Änderungen eine längere API-Abfragefrequenz erforderte (spez. 20 Milisek. auf 100-150 Milisek.) und hierdurch enstanden Lücken in den Datensätzen, die eine Interpretation für 05-2018 massiv erschwert. Der 05-er Upload wird daher übersprungen und ich ändere die zukünftige Freigabe wiefolgt:

-> Upload im Wochenturnus (1. Upload 01.05 – 06.05, letzter Upload 28.05 – 31.05)
-> Vorgängerdatenbank wird mit Upload gelöscht.

Der Vorteil in dem Moduswechsel liegt darin, dass die stark verkleinerten Scraperdatenbanken schlichtweg einen schnelleren Datenerfassungsdurchlauf und deutlich mehr Abfragen erlauben. Die Recherche nach weiteren Themen, Queries / Tagwelten etc. läuft und die Ergebnisse werden kommenden Sonntag in die Prozedur eingepflegt.

Update: Datenvisualisierungsfunktion(en) – Hashtagclient

Im Zuge der Datenvisualisierungsfunktionsentwicklungen wurde die Darstellung umgestellt. Diese erlaubt nun den direkten Vergleich von mind. 2 Hashtagentwicklungsdatensätzen und liefert den Zugang zu weiteren / tiefergehenden Interpretationen bzgl. dieser Fragestellungen:

– Existieren Schnittmengen zwischen den Kommunikationshäufungen innerhalb von Tag- / Themenwelten?
– An welchen Tagen „lohnt“ sich ein Engagement zu den analysierbaren Tag- / Themenwelten?
– Welche Zielgruppenbewegungen werden in welchen Zeiträumen zu den Tag- / Themenwelten sichtbar?

Darstellungen der absoluten Reichweitenveränderungen (Rohdaten)


Darstellungen der absoluten Reichweitenveränderungen im Verhältnis zum ersten Datensatz.

Darstellungen der Reichweitenveränderungen im Verhältnis zum vorhergehenden Datensatz. (Datum [z] zu Datum [y]).

Das gezeigte Schema findet bereits jetzt Eingang in die tägliche Promopraxis und ein aktueller Account erfreut sich folgendem Wachstum:

l6.03.2018 -> (Re)start -> 0 Follower
21.03.2018 -> ~30 Follower
22.03.2018 -> ~100 Follower mit durchschn. Interaktion zu 20 – 30 „Likes“ inkl. guter Durchklickrate auf die verlinkte Webseite.

Die Prognose läuft darauf hinaus, dass besagter Account zum Monatsende sich zwischen 150 – 200 Follower einpendeln wird. Bereits jetzt sind Wechselwirkungen zwischen dem Auftritt, Trafficströme UND (!) positiver Rankingeffekte sichtbar. Eine finale Verifikation steht aus und wird via Gegenprobe realisiert werden.

Fragen? Anregungen?
Ich freue mich auf Kommentare, Telefonate und eMails unter office[at]pontipix.de

Update „Instafinal“

Ein Instagramaccount, welcher eher diverse Aspekte aus meinem Hobby „Analogfotografie“ abbildet, zeigte in den letzten 2 Tagen interessante Reichweitenentwicklungen.
Diese sind:
+ 38 Follower an einem Tag (aktuell: ~340 Follower)
~ 50 Likes im Mittelwert / Medium
Darüber hinaus fällt mir auf, dass die aktivierten / angesprochenen Follower „relativ“ sauber wirken (geringe Botdichte, relativ wenige und typische SPAM-Comments und relativ wenig Follow/Unfollow). Auch beobachte ich eine gesteigerte Kommentierbereitschaft.
Der Account wird von einer weiteren Person bedient und gepflegt. Wir wechseln uns hierbei ab und ich zeigen individuelle Stilelemente (Bildsprache, Hashtags und weitere Ausführungen).

Diese Beobachtungen werden nun als Grundlage für ein Werkzeugupdate zu „Instafinal“ genommen und folgende Features implementiert:

-> dynamische Auswahl der zu belikenden Hashtags
–> Basis (Medien): die letzten 6 Postings
–> Basis (Locations): die letzten 6 Postings aus Galerien, Influencer etc.

Im Rahmen der Weiterentwicklung werden die aktuellen Beobachtungen beobachtet. Sollten sich die aktuellen Positiventwicklungen verfestigen, werden die Hashtag- und Interaktionsdatenbanken an das Projekt angebunden.

Analyse: Orte, Location via Instagram und Facebook

Ich hatte in diversen Gesprächen und sonstigen Statements angedeutet, dass wir einige Experimente (spez. Likes, Socialmediautomatisierungen und Contentmarketingansaetze) mit den Erkenntnissen aus „Locations“ durchführen. Diese sind flächendeckend positiv ausgegangen. Die nachfolgenden Quellcodes stammen aus dem aktuellen Recherchetool (INSTA-FINAL)

Ich nutze die Daten für das Abarbeiten folgender Szenarien:
(a) Liken via Instafinal
(b) konkrete Firmen und Locationanalyse
-> Was wird geschrieben?
-> Wieviele Menschen sind da WANN aktiv und was schreiben die, was
bewegt die?
-> Vorbereitungen auf Messen, da Messen selbstverständlich Locations sind.
-> Vorbereitungen auf konkrete Messegespräche
-> Aufbereitung der Daten für die üblichen Akquisevorbereitungen
-> Erkenntnisgewinnung, Inspiration für div. Contentmarketingansätze
(c) Hashtagrecherchen

//-> Locationrechercheprozedur

1. Schritt: Token von Facebook besorgen

How to get a Facebook Access Token

2. Schritt: Mit Facebook-Token nach Orten, Firmen usw. suchen

procedure TForm1.Button42Click(Sender: TObject);
var l_clear: integer;
var
JSONArray: tJSONArray;
JSONValue,jvalue: tJSONValue;
JSONPair: TJSONPair;
JSON, json_sub: TJSONObject;
size: integer;
j_array: tJSONArray;
s: string;
i,j: integer;
next_id: string;
chk_br: char;
begin
locsearch.text := StringReplace(locsearch.text, ‚ ‚, ‚+‘,
[rfReplaceAll, rfIgnoreCase]);
listbox2.Items.Clear;
with locs do
begin
cells[0,0]:=’Nr.‘;
cells[1,0]:=’Name‘;
cells[2,0]:=’ID-Code‘;
cells[3,0]:=’URL‘;
colcount:=4;
rowcount:=1;
end;
try
with debug do
begin
clear;
text:=idhttp1.Get(‚https://graph.facebook.com/search?q=’+locsearch.Text+’&type=place&access_token=’+fbtoken.text);
end;
JSONValue := TJSONObject.ParseJSONValue(debug.text);
JSON := TJSONObject.ParseJSONValue(debug.Lines.Text) as TJSONObject;
JSONArray := TJSONArray(JSON.Get(‚data‘).JsonValue);
memo1.Clear;
for i := 0 to JSONArray.Size – 1 do
begin
with locs do
begin
cells[0,rowcount]:=inttostr(rowcount);
cells[1,rowcount]:=TJSONPair(TJSONObject(JSONArray.Get(i)).Get(’name‘)).JsonValue.Value;
listbox2.Items.Add(cells[1,rowcount]);
cells[2,rowcount]:=TJSONPair(TJSONObject(JSONArray.Get(i)).Get(‚id‘)).JsonValue.Value;
cells[3,rowcount]:=’https://www.instagram.com/explore/locations/’+cells[2,rowcount]+’/‘;
rowcount:=rowcount+1;
end;
end;
grdColWidth(locs, 40);
except
end;
end;

3. Schritt: Medien aus Locations abholen und ggf. analysieren

procedure TForm1.get_loc_short(mytable: TStringGrid; locid: string);
var
JSONArray: tJSONArray;
JSONValue,jvalue: tJSONValue;
JSONPair: TJSONPair;
JSON, json_sub: TJSONObject;
size: integer;
j_array: tJSONArray;
s: string;
i,j: integer;
next_id: string;

begin
with mytable do
begin
cells[0,0]:=’Nr.‘;
cells[1,0]:=’URL‘;
cells[2,0]:=’Tag‘;
cells[3,0]:=’Likes‘;
cells[4,0]:=’Comments‘;
cells[5,0]:=’Erstellzeit‘;
cells[6,0]:=’ID‘;
colcount:=7;
rowcount:=1;
end;
memo3.Lines.Add(‚url =>
https://api.instagram.com/v1/locations/’+locid+’/media/recent?access_token=’+token.text);
memo3.Lines.SaveToFile(verz+’\tmp_mediaurlsapi.txt‘);
try
debug.text:=idhttp1.Get(‚https://api.instagram.com/v1/locations/’+locid+’/media/recent?access_token=’+token.text);
debug.text:=idhttp1.Get(‚https://www.instagram.com/explore/tags/’+tagsuche+’/?__a=1‘);
JSONValue := TJSONObject.ParseJSONValue(debug.text);
JSON := TJSONObject.ParseJSONValue(debug.Lines.Text) as TJSONObject;
JSONArray := TJSONArray(JSON.Get(‚data‘).JsonValue);
try next_id:= JSONValue.GetValue(‚pagination.next_url‘);
except
end;
for i := 0 to JSONArray.Size – 1 do
begin
with mytable do
begin
cells[0,rowcount]:=inttostr(rowcount);
cells[1,rowcount]:=(TJSONPair(TJSONObject(JSONArray.Get(i)).Get(‚link‘)).JsonValue.Value);
s:=(TJSONPair(TJSONObject(JSONArray.Get(i)).Get(‚tags‘)).ToString);
s:= StringReplace(s, ‚“tags“:[‚, “, [rfReplaceAll,rfIgnoreCase]);
s:= StringReplace(s, ‚]‘, “, [rfReplaceAll,rfIgnoreCase]);
cells[2,rowcount]:=s;
s:=(TJSONPair(TJSONObject(JSONArray.Get(i)).Get(‚likes‘)).ToString);
s:= StringReplace(s, ‚“likes“:{„count“:‘, “,
[rfReplaceAll,rfIgnoreCase]);
s:= StringReplace(s, ‚}‘, “, [rfReplaceAll,rfIgnoreCase]);
cells[3,rowcount]:=s;
s:=(TJSONPair(TJSONObject(JSONArray.Get(i)).Get(‚comments‘)).ToString);
s:= StringReplace(s, ‚“comments“:{„count“:‘, “,
[rfReplaceAll,rfIgnoreCase]);
s:= StringReplace(s, ‚}‘, “, [rfReplaceAll,rfIgnoreCase]);
cells[4,rowcount]:=s;
cells[5,rowcount]:=(TJSONPair(TJSONObject(JSONArray.Get(i)).Get(‚created_time‘)).JsonValue.Value);
cells[5,rowcount]:=datetimetostr(UnixToDateTime(strtoint(cells[5,rowcount])));
cells[6,rowcount]:=(TJSONPair(TJSONObject(JSONArray.Get(i)).Get(‚id‘)).JsonValue.Value);
rowcount:=rowcount+1;
end;
grdColWidth(mytable, 40);
end;
except
end;
//uebertrag auf tabelle
grdColWidth(mytable, 40);
form1.Caption:=version+‘ alle Posts herunter geladen‘;
end;

[Delphi] Instagram – Likende auf Medien identifizieren und Datensätze speichern

[Datenquellen und Erklärungen]
„mylikers“ -> Anzahl der beobachteten Medien
„mytable“ -> Stringgridobjekt für die Ergebnisse
„oritable“ -> Stringgridobjekt für die Medienrohdaten
„oritable.cols[6].text“ -> Stringreihe für die Postcodes aus Instagram

procedure TForm1.getmylikers(mylikers: integer; mytable: TStringGrid; oritable: tstringgrid);
var lauf, lauf_gl: integer;
l_clear: integer;
JSONArray: tJSONArray;
JSONValue,jvalue: tJSONValue;
JSONPair: TJSONPair;
JSON, json_sub: TJSONObject;
size: integer;
j_array: tJSONArray;
s: string;
i,j: integer;
next_id: string;
chk_br: char;
HTTP: TIdHTTP;

begin
// => hole media_daten (unique-codes!)
debug.Text:=oritable.Cols[6].Text;
debug.Lines.Delete(0);
form1.Caption:=version+‘ ‚+inttostr(debug.Lines.Count-1)+‘ IDs eingelesen‘;
debug_03.Clear;

// init tabelle
with mytable do
begin
cells[0,0]:=’Nr.‘;
cells[1,0]:=’Username‘;
cells[2,0]:=’URL‘;
cells[3,0]:=’ID‘;
cells[4,0]:=’Post-ID‘;
cells[5,0]:=’Post-URL‘;
cells[6,0]:=’Tagcloud‘;
cells[7,0]:=’Postzeit‘;
rowcount:=1;
colcount:=8;
end;
for lauf_gl := 0 to mylikers do
begin
debug_01.Clear;
debug_01.ScrollBars:=ssboth;
randomize;
token.Text:=token.Items[random(token.Items.Count-1)];
debug_03.Lines.Add(‚https://api.instagram.com/v1/media/’+debug.Lines[lauf_gl]+’/likes?access_token=’+token.text);
try
HTTP := TIdHTTP.Create(nil);
form1.Caption:=version+‘ analysiere Likende, Bild: ‚+inttostr(lauf_gl)+‘ / ‚+inttostr(mylikers);
debug_01.Text:=HTTP.Get(‚https://api.instagram.com/v1/media/’+debug.Lines[lauf_gl]+’/likes?access_token=’+token.text);
JSONValue := TJSONObject.ParseJSONValue(debug_01.text);
JSON := TJSONObject.ParseJSONValue(debug_01.Lines.Text) as TJSONObject;
JSONArray := TJSONArray(JSON.Get(‚data‘).JsonValue);
http.free;
SetProcessWorkingSetSize(GetCurrentProcess, $FFFFFFFF, $FFFFFFFF);
for i := 0 to JSONArray.Size – 1 do
begin
with mytable do
begin
cells[0,rowcount]:=inttostr(rowcount);
cells[1,rowcount]:=(TJSONPair(TJSONObject(JSONArray.Get(i)).Get(‚username‘)).JsonValue.Value);
cells[2,rowcount]:=’https://instagram.com/’+(TJSONPair(TJSONObject(JSONArray.Get(i)).Get(‚username‘)).JsonValue.Value);
cells[3,rowcount]:=(TJSONPair(TJSONObject(JSONArray.Get(i)).Get(‚id‘)).JsonValue.Value);
cells[4,rowcount]:=debug.Lines[lauf_gl]; // post-id
cells[5,rowcount]:=oritable.Cells[1,lauf_gl+1];
cells[6,rowcount]:=oritable.Cells[2,lauf_gl+1];
cells[7,rowcount]:=oritable.Cells[5,lauf_gl+1];
if zdb.Checked=true then
begin
save_infname:=prjlikeacc.Text;
save_likers:=useridlikeacc.Text;
with sql_befehle.Lines do
begin
clear;
add(‚INSERT INTO `interakt` (`name`, `url`, `uid`, `postid`, `posturl`, `tagcloud`, `inflid`, `inflname`, `postzeit`,`zeit`) Values (“’+cells[1,rowcount]+“‘, “’+cells[2,rowcount]+“‘, “’+cells[3,rowcount]+“‘, “’+cells[4,rowcount]+“‘, “’+cells[5,rowcount]+“‘, “’+escape(cells[6,rowcount])+“‘, “’+save_likers+“‘, “’+save_infname+“‘, “’+cells[7,rowcount]+“‘, “’+datetimetostr(now)+“‘ );‘);
fdquery2.ExecSQL(sql_befehle.text);
form1.Caption:=version+‘ in DB eingetragen …‘;
SetProcessWorkingSetSize(GetCurrentProcess, $FFFFFFFF, $FFFFFFFF);
end;
end;
rowcount:=rowcount+1;
end;
end;
except
form1.Caption:=version+‘ Recherche und Analyse hat nicht funktioniert …‘;
end;
delay(50);
grdColWidth(mytable, 40);
end;
SaveToCSV(mytable,verz+’data\’+save_likers+‘.csv‘);
end;

Aufruf der Prozedur
getmylikers(strtoint(anzmedia.Text), table_likers, m_rohdaten);